How the A2A Agent Protocol Works in OmniRoute: JSON-RPC Skills Architecture

OmniRoute's A2A Agent Protocol enables external agents to invoke internal routing skills via JSON-RPC 2.0, supporting both synchronous responses and streaming Server-Sent Events for real-time task execution.

The A2A Agent Protocol implementation in the diegosouzapw/OmniRoute repository provides a structured interface for agent-to-agent communication, exposing modular capabilities like smart routing and quota management through standardized endpoints. This protocol architecture separates concerns between task management, skill execution, and streaming delivery, allowing autonomous systems to programmatically access OmniRoute's AI gateway functionality with full observability.

Core Architecture and Protocol Flow

The A2A implementation follows a layered architecture that processes JSON-RPC requests through dedicated TypeScript modules:

Layer File Path Responsibility
Entry Point src/app/a2a/route.ts Exposes POST /a2a JSON-RPC endpoint and handles request routing
Task Manager src/lib/a2a/taskManager.ts Creates A2ATask objects with UUID assignment and TTL-based eviction (default 5 minutes)
Execution Engine src/lib/a2a/taskExecution.ts Maintains A2A_SKILL_HANDLERS map to dispatch tasks to appropriate skill implementations
Skill Modules src/lib/a2a/skills/*.ts Individual skill implementations (e.g., smartRouting.ts, quotaManagement.ts) returning artifacts and metadata
Streaming Layer src/lib/a2a/streaming.ts Wraps execution in Server-Sent Events for message/stream method delivery
Discovery src/app/.well-known/agent.json/route.ts Serves Agent Card describing available skills for remote agent discovery
Observability src/lib/a2a/routingLogger.ts Logs state transitions and resilience layer activity during task lifecycle

Request Processing Pipeline

  1. Authentication: Requests to POST /a2a require an Authorization: Bearer <API_KEY> header unless authentication is explicitly disabled in configuration.

  2. Task Creation: The A2ATaskManager instantiates a task record with unique UUID, storing execution state, artifacts, and metadata in memory with configurable TTL eviction.

  3. Skill Dispatch: taskExecution.ts resolves the JSON-RPC method against A2A_SKILL_HANDLERS to select the appropriate skill module.

  4. Execution: Skills invoke OmniRoute's internal pipelines (e.g., combo routing) and return structured results containing artifacts and rich metadata.

  5. Response Delivery: Synchronous methods return complete JSON-RPC responses, while streaming methods emit incremental SSE chunks until task completion.

Protocol Authentication and Endpoint Structure

All A2A interactions require Bearer token authentication passed via the Authorization header. The primary JSON-RPC endpoint resides at POST /a2a, with auxiliary REST endpoints available under /api/a2a/* for dashboard and management tooling.

The protocol supports three primary interaction patterns:

  • Synchronous execution via message/send for complete responses
  • Streaming execution via message/stream for real-time chunk delivery
  • Task management via tasks/get and tasks/cancel for lifecycle operations

Synchronous Skill Invocation with message/send

The message/send method executes skills and returns complete results in a single JSON-RPC response. This method is ideal for routing requests that require immediate, structured output including cost envelopes and routing explanations.

curl -X POST http://localhost:20128/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_KEY" \
  -d '{
        "jsonrpc":"2.0",
        "id":"1",
        "method":"message/send",
        "params":{
          "skill":"smart-routing",
          "messages":[{"role":"user","content":"Write a hello world in Python"}],
          "metadata":{"model":"auto","combo":"fast-coding"}
        }
      }'

The response includes the task state, generated artifacts, and detailed metadata:

{
  "jsonrpc":"2.0",
  "id":"1",
  "result":{
    "task":{"id":"c1e7…","state":"completed"},
    "artifacts":[{"type":"text","content":"print('Hello, world!')"}],
    "metadata":{
      "routing_explanation":"Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
      "cost_envelope":{"estimated":0.005,"actual":0.003,"currency":"USD"}
    }
  }
}

Real-Time Streaming with message/stream

For long-running generation tasks, the message/stream method delivers incremental output via Server-Sent Events. The streaming.ts module manages SSE connections, emitting chunked data while the skill executes against OmniRoute's routing pipeline.

curl -N -X POST http://localhost:20128/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_KEY" \
  -d '{
        "jsonrpc":"2.0",
        "id":"2",
        "method":"message/stream",
        "params":{
          "skill":"smart-routing",
          "messages":[{"role":"user","content":"Explain quantum computing"}]
        }
      }'

Stream events follow this structure:


data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"…","state":"working"},"chunk":{"type":"text","content":"Quantum computing…"}}}
: heartbeat 2026-03-03T17:00:00Z
data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"…","state":"completed"},"metadata":{…}}}

Task Lifecycle Management

Individual tasks persist for a configurable TTL (defaulting to 5 minutes) within the A2ATaskManager. External agents can query task status or cancel pending operations using dedicated JSON-RPC methods.

Retrieving Task Status

curl -X POST http://localhost:20128/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_KEY" \
  -d '{"jsonrpc":"2.0","id":"3","method":"tasks/get","params":{"taskId":"c1e7…"}}'

Canceling Active Tasks

curl -X POST http://localhost:20128/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_KEY" \
  -d '{"jsonrpc":"2.0","id":"4","method":"tasks/cancel","params":{"taskId":"c1e7…"}}'

Skill Implementation and Metadata Architecture

Skills reside in src/lib/a2a/skills/*.ts as async functions receiving an A2ATask object and returning structured results. Each skill implementation follows a consistent contract:

  • Input: Task parameters including conversation messages and routing metadata
  • Processing: Direct invocation of OmniRoute's internal engines (e.g., combo routing via smartRouting.ts)
  • Output: Object containing artifacts (generated content) and metadata (routing explanations, cost envelopes, policy verdicts, resilience traces)

The A2A_SKILL_HANDLERS map in taskExecution.ts provides the routing layer between JSON-RPC method names and their corresponding skill implementations.

Agent Discovery and Capabilities

The Agent Card endpoint at src/app/.well-known/agent.json/route.ts publishes machine-readable skill descriptions, enabling autonomous discovery by remote agents. This discovery mechanism allows external systems to query available capabilities—including supported models, routing policies, and quota constraints—before initiating task execution.

Summary

  • OmniRoute's A2A Agent Protocol implements JSON-RPC 2.0 standards with Bearer token authentication to expose internal routing capabilities as discrete skills.
  • Task management in src/lib/a2a/taskManager.ts maintains stateful execution contexts with 5-minute TTL eviction and UUID-based tracking.
  • Skill dispatch occurs through the A2A_SKILL_HANDLERS registry in taskExecution.ts, routing requests to modular implementations in src/lib/a2a/skills/*.ts.
  • Streaming support via message/stream delivers real-time chunks using Server-Sent Events managed by src/lib/a2a/streaming.ts.
  • Full observability is provided through src/lib/a2a/routingLogger.ts, capturing resilience layer interactions including circuit breakers and provider cooldowns.

Frequently Asked Questions

What authentication method does the OmniRoute A2A protocol require?

The protocol requires Bearer token authentication via the Authorization header on all requests to POST /a2a. If the server configuration explicitly disables API key requirements, authentication is bypassed, though this is not recommended for production deployments.

How long do tasks persist in the A2A system?

Tasks remain in memory for a configurable TTL period defaulting to 5 minutes, after which the A2ATaskManager automatically evicts them. During this window, clients can query task status using tasks/get or cancel operations using tasks/cancel.

What is the difference between message/send and message/stream methods?

The message/send method returns complete skill execution results in a single JSON-RPC response, suitable for short operations requiring immediate structured data. The message/stream method establishes a Server-Sent Events connection that emits incremental content chunks during generation, ideal for long-form text production where real-time feedback is required.

Where are skill implementations located in the OmniRoute codebase?

Skill implementations reside in the src/lib/a2a/skills/ directory, with individual modules like smartRouting.ts and quotaManagement.ts exporting async functions that process A2ATask objects. These are registered in the A2A_SKILL_HANDLERS map within src/lib/a2a/taskExecution.ts for JSON-RPC method resolution.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →