AgentKit SDK - Build AI agents with A2A and LangGraph protocol support
npm install @wardenprotocol/agent-kitA TypeScript SDK for building and connecting AI agents. Create your own agents or communicate with existing ones using a simple, unified API.
- Build AI Agents: Create agents that respond to messages with streaming support
- Dual Protocol Support: Expose agents via both A2A and LangGraph APIs simultaneously
- Connect to Agents: Discover and communicate with remote agents using the A2A protocol
- LangGraph Compatibility: Agents can be consumed by LangGraph SDK clients
- Stream Responses: Real-time streaming via Server-Sent Events (SSE)
- Manage Conversations: Multi-turn conversations with context preservation
``bash`
npm install @wardenprotocol/agent-kit @langchain/langgraph-sdkor
pnpm add @wardenprotocol/agent-kit @langchain/langgraph-sdkor
yarn add @wardenprotocol/agent-kit @langchain/langgraph-sdk
Create an agent server in just a few lines of code:
`typescript
import { AgentServer } from "@wardenprotocol/agent-kit";
const server = new AgentServer({
agentCard: {
name: "My Agent",
description: "A helpful assistant",
url: "http://localhost:3000",
capabilities: { streaming: true, multiTurn: true },
},
handler: async function* (context) {
const userMessage = context.message.parts
.filter((p) => p.type === "text")
.map((p) => p.text)
.join("\n");
yield {
state: "completed",
message: {
role: "agent",
parts: [{ type: "text", text: Echo: ${userMessage} }],
},
};
},
});
await server.listen(3000);
console.log("Agent server running on http://localhost:3000");
console.log("- A2A: POST / (JSON-RPC), GET /.well-known/agent-card.json");
console.log("- LangGraph: /assistants, /threads, /runs, /info");
`
Your agent is now accessible via both:
- A2A clients: Discovery at GET /.well-known/agent-card.json, JSON-RPC at POST //assistants
- LangGraph SDK clients: REST API at , /threads, /runs/*
`typescript
import { Client } from "@langchain/langgraph-sdk";
// Connect to your dual-protocol agent
const client = new Client({ apiUrl: "http://localhost:3000" });
// List assistants (returns your agent)
const assistants = await client.assistants.search();
console.log("Agent:", assistants[0].name);
// Create a thread
const thread = await client.threads.create();
// Stream a conversation
for await (const event of client.runs.stream(thread.thread_id, assistants[0].assistant_id, {
input: { messages: [{ role: "user", content: "Hello!" }] },
streamMode: "messages",
})) {
if (event.event === "messages") {
console.log("Response:", event.data);
}
}
`
Discover and communicate with remote agents:
`typescript
import { createA2AOnlyClient, discoverAgent } from "@wardenprotocol/agent-kit";
// Discover what an agent can do
const agentCard = await discoverAgent("https://agent.example.com");
console.log("Agent:", agentCard.name);
console.log("Skills:", agentCard.skills);
// Create a client
const client = createA2AOnlyClient({
url: "https://agent.example.com",
auth: {
type: "bearer",
credentials: "your-api-token",
},
});
// Send a message
const response = await client.sendText("Hello, agent!");
// Stream responses
for await (const event of client.streamText("Tell me a story")) {
if (event.type === "task_status_update") {
console.log("Status:", event.state);
if (event.message) {
console.log("Response:", event.message);
}
}
}
// Multi-turn conversation
const task1 = await client.sendText("My name is Alice", { contextId: "conv-1" });
const task2 = await client.sendText("What's my name?", { contextId: "conv-1" });
`
`typescript
// Get task status
const task = await client.getTask({ taskId: "task-123" });
// List all tasks
const { tasks } = await client.listTasks({ status: "completed" });
// Cancel a running task
await client.cancelTask({ taskId: "task-123" });
// Subscribe to task updates
for await (const event of client.subscribeToTask({ taskId: "task-123" })) {
console.log("Update:", event);
}
`
| Endpoint | Description |
|----------|-------------|
| GET /.well-known/agent-card.json | Agent discovery - returns capabilities and metadata |POST /
| | JSON-RPC endpoint for all A2A operations |
A2A JSON-RPC methods:
- message/send - Send a message and get a responsemessage/stream
- - Send a message and stream the response (SSE)tasks/get
- - Get task status by IDtasks/cancel
- - Cancel a running tasktasks/resubscribe
- - Subscribe to task updates
| Endpoint | Description |
|----------|-------------|
| GET /info | Server information |GET /ok
| | Health check |POST /assistants/search
| | List assistants |GET /assistants/:id
| | Get assistant details |POST /threads
| | Create a thread |POST /threads/search
| | List threads |GET /threads/:id
| | Get thread details |GET /threads/:id/state
| | Get thread state |DELETE /threads/:id
| | Delete a thread |POST /runs/stream
| | Create a stateless streaming run |POST /runs/wait
| | Create a stateless run and wait |POST /threads/:id/runs
| | Create a run on a thread |POST /threads/:id/runs/stream
| | Stream a run on a thread |POST /threads/:id/runs/wait
| | Run and wait on a thread |
Full TypeScript support with exported types:
`typescript`
import type {
// A2A types
AgentCard,
AgentSkill,
Task,
TaskState,
Message,
Part,
TextPart,
FilePart,
DataPart,
StreamEvent,
TaskContext,
TaskYieldUpdate,
// LangGraph types
LangGraphAssistant,
LangGraphThread,
LangGraphRun,
LangGraphMessage,
} from "@wardenprotocol/agent-kit";
`typescript
import { A2AError, TaskNotFoundError, A2AErrorCodes } from "@wardenprotocol/agent-kit";
try {
const task = await client.getTask({ taskId: "invalid" });
} catch (error) {
if (error instanceof TaskNotFoundError) {
console.log("Task not found");
} else if (error instanceof A2AError) {
console.log("Error:", error.code, error.message);
}
}
``
MIT