a2a-nextjs
v0.1.1
Published
A2A protocol handler for Next.js. Translates AI SDK streams to A2A events.
Readme
a2a-nextjs
A2A protocol handler for Next.js. Translates AI SDK streams to A2A events.
Installation
pnpm add a2a-nextjs @a2a-js/sdkUsage
Create an agent
// lib/agents/my-agent.ts
import { createAgent, InMemoryTaskStore } from "a2a-nextjs"
export const myAgent = createAgent({
card: {
name: "my-agent",
description: "A helpful assistant",
skills: [
{ id: "chat", name: "Chat", description: "General conversation" },
],
},
taskStore: new InMemoryTaskStore(),
execute: async (prompt) => {
// Return a ReadableStream<UIMessageChunk>
},
})Create routes
// app/api/agent/route.ts
import { myAgent } from "@/lib/agents/my-agent"
export const POST = myAgent// app/.well-known/a2a/agent-card/route.ts
import { myAgent } from "@/lib/agents/my-agent"
export const GET = myAgent.cardHandler("/api/agent")With Workflow + DurableAgent
// lib/agents/my-agent.ts
import { createAgent, InMemoryTaskStore } from "a2a-nextjs"
import { start, getRun } from "workflow/api"
import { runAgentWorkflow } from "@/lib/agent"
export const myAgent = createAgent({
card: {
name: "my-agent",
description: "A helpful assistant",
skills: [],
},
taskStore: new InMemoryTaskStore(),
execute: async (prompt) => {
const run = await start(runAgentWorkflow, [{ prompt }])
return getRun(run.runId).getReadable()
},
})// lib/agent.ts
import { DurableAgent } from "@workflow/ai/agent"
import { getWritable } from "workflow"
import type { UIMessageChunk } from "ai"
export async function runAgentWorkflow({ prompt }: { prompt: string }) {
"use workflow"
const writable = getWritable<UIMessageChunk>()
const agent = new DurableAgent({
model: "anthropic/claude-sonnet-4",
system: "You are a helpful assistant.",
tools: {},
})
await agent.stream({
messages: [{ role: "user", content: prompt }],
writable,
})
}API
createAgent(config): AgentHandler
Creates an agent handler.
Config:
card- Agent metadata (name, description, skills)taskStore- Task persistence (InMemoryTaskStoreor custom)execute- ReturnsReadableStream<UIMessageChunk>
Returns a callable handler with:
(request: Request) => Promise<Response>- POST handler.cardHandler(path)- Returns GET handler that builds card with full URL from request origin.buildCard({ url })- Build full AgentCard manually
Types
interface AgentCardConfig {
name: string
description: string
version?: string
protocolVersion?: string
skills?: AgentSkillConfig[]
capabilities?: Record<string, unknown>
defaultInputModes?: string[]
defaultOutputModes?: string[]
}
interface UIMessageChunk {
type: string
delta?: string
toolCallId?: string
toolName?: string
output?: unknown
errorText?: string
}