Skip to main content

Overview

The A2A (Agent-to-Agent) protocol enables standardized agent discovery and inter-agent communication. aixyz implements A2A protocol version 0.3.0 with an agent card for discovery and a JSON-RPC endpoint for task execution.

Endpoints

EndpointMethodDescription
/.well-known/agent-card.jsonGETAgent discovery card with metadata, skills, and capabilities
/agentPOSTJSON-RPC task handler, x402-gated if accepts is defined

Agent Card

The agent card is automatically generated from your aixyz.config.ts. Other agents fetch this card to discover your agent’s capabilities.
curl http://localhost:3000/.well-known/agent-card.json
Example response:
{
  "name": "Weather Agent",
  "description": "Get current weather for any location worldwide.",
  "protocolVersion": "0.3.0",
  "version": "0.1.0",
  "url": "https://my-agent.vercel.app/agent",
  "capabilities": {
    "streaming": true,
    "pushNotifications": false
  },
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/plain"],
  "skills": [
    {
      "id": "get-weather",
      "name": "Get Weather",
      "description": "Get current weather conditions for any city",
      "tags": ["weather"],
      "examples": ["What's the weather in Tokyo?"]
    }
  ]
}

JSON-RPC Endpoint

The /agent endpoint accepts JSON-RPC 2.0 requests. The primary method is tasks/send:
curl -X POST http://localhost:3000/agent \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tasks/send",
    "id": "1",
    "params": {
      "id": "task-1",
      "message": {
        "role": "user",
        "parts": [{"type": "text", "text": "What is the weather in NYC?"}]
      }
    }
  }'

Capabilities

The agent card’s capabilities field is configured via the capabilities export from your agent file. If omitted, defaults to { streaming: true, pushNotifications: false }.
app/agent.ts
import type { Capabilities } from "aixyz/app/plugins/a2a";

export const capabilities: Capabilities = {
  streaming: false,
  pushNotifications: false,
};
When streaming is false, the executor uses agent.generate() instead of agent.stream(), returning a single artifact with the full response. See agent.ts — Capabilities for the full reference.

Using the A2A Plugin

The A2APlugin wires up both endpoints on your server:
import { A2APlugin } from "aixyz/app/plugins/a2a";

// agentExports is `import * as agent from "./agent"`
// reads `default` (the ToolLoopAgent), `accepts` (payment config), and `capabilities`
await server.withPlugin(new A2APlugin([{ exports: agent }]));
This registers:
  • A GET handler at /.well-known/agent-card.json serving the agent card
  • A POST handler at /agent routing JSON-RPC requests to ToolLoopAgentExecutor

Sub-Agent Routing

Pass multiple entries with a name to mount sub-agents under their own paths:
app/server.ts
import * as research from "./agents/research";
import * as implement from "./agents/implement";

await server.withPlugin(
  new A2APlugin([
    { exports: agent }, // → /agent
    { name: "research", exports: research }, // → /research/agent
    { name: "implement", exports: implement }, // → /implement/agent
  ]),
);
Each sub-agent gets its own agent card at /{name}/.well-known/agent-card.json and its own JSON-RPC endpoint at /{name}/agent. When using app/agents/, the build pipeline generates these calls automatically.

Payment Integration

When an agent exports an accepts configuration with scheme: "exact", the /agent endpoint is gated behind x402 payment. Clients must include a valid X-Payment header. Agents without accepts are served without payment requirements.

x402 Payments

How payment gating works on A2A endpoints.

MCP Protocol

Expose tools via MCP alongside A2A.