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
-
Authentication: Requests to
POST /a2arequire anAuthorization: Bearer <API_KEY>header unless authentication is explicitly disabled in configuration. -
Task Creation: The
A2ATaskManagerinstantiates a task record with unique UUID, storing execution state, artifacts, and metadata in memory with configurable TTL eviction. -
Skill Dispatch:
taskExecution.tsresolves the JSON-RPCmethodagainstA2A_SKILL_HANDLERSto select the appropriate skill module. -
Execution: Skills invoke OmniRoute's internal pipelines (e.g., combo routing) and return structured results containing artifacts and rich metadata.
-
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/sendfor complete responses - Streaming execution via
message/streamfor real-time chunk delivery - Task management via
tasks/getandtasks/cancelfor 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) andmetadata(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.tsmaintains stateful execution contexts with 5-minute TTL eviction and UUID-based tracking. - Skill dispatch occurs through the
A2A_SKILL_HANDLERSregistry intaskExecution.ts, routing requests to modular implementations insrc/lib/a2a/skills/*.ts. - Streaming support via
message/streamdelivers real-time chunks using Server-Sent Events managed bysrc/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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →