How OmniRoute’s A2A Protocol Enables JSON-RPC 2.0 Communication Between Cloud Agents

OmniRoute implements an Agent-to-Agent (A2A) server that lets any AI agent invoke another agent’s capabilities through the standard JSON-RPC 2.0 protocol over HTTP.

The OmniRoute A2A protocol provides a standards-compliant bridge for autonomous agents to exchange structured requests and responses. Located in the diegosouzapw/OmniRoute repository, the A2A layer under src/lib/a2a/ exposes cloud agent capabilities via JSON-RPC 2.0 endpoints, leveraging the existing routing, resilience, and database infrastructure.

Protocol Architecture and Schema Definition

The foundation of OmniRoute’s A2A communication lies in strict schema validation using Zod. The file src/lib/a2a/schemas/a2a.ts defines the complete JSON-RPC 2.0 type system, enforcing required fields (jsonrpc, method, id, params) and agent-specific payloads including AgentCard, Task, and SSE event types.

This schema-driven approach ensures that all incoming requests conform to the JSON-RPC 2.0 specification before reaching business logic. The validation covers method signatures, parameter shapes, and response structures, preventing malformed requests from propagating through the system.

The JSON-RPC Dispatch Pipeline

Incoming HTTP requests enter through Next.js API routes that act as the transport layer for the A2A protocol.

HTTP Entry Points and Validation

The primary endpoint POST /a2a is handled by src/app/a2a/route.ts. This route parses the request body, validates it against the Zod schemas defined in the A2A module, and prepares it for execution. If validation fails, the server returns a standard JSON-RPC error response with code -32600 and message INVALID_REQUEST.

POST /a2a HTTP/1.1
Host: localhost:20128
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": "42",
  "method": "smartRouting",
  "params": {
    "messages": [
      { "role": "user", "content": "What is the weather in Paris?" }
    ],
    "model": "gpt-4o",
    "maxTokens": 256
  }
}

Method Dispatch in Task Execution

After validation, requests flow to the JSON-RPC dispatcher in src/lib/a2a/taskExecution.ts. This component maps the method field to concrete handlers such as smartRouting, quotaManagement, or providerDiscovery. The dispatcher executes the logic inside a TaskManager instance and formats the result as a JSON-RPC response:

{
  "jsonrpc": "2.0",
  "id": "42",
  "result": {
    "completion": "The weather in Paris today is..."
  }
}

Task Lifecycle and Asynchronous Operations

A task represents an asynchronous operation that may involve multiple providers, streaming responses, or long-running work. The A2A server treats every method invocation as a potential task, enabling persistent state tracking across distributed agents.

Task Creation and State Management

The TaskManager class in src/lib/a2a/taskManager.ts stores task state in memory and persists metadata to the SQLite database via the generic DB layer. Clients create tasks via POST /a2a/tasks (handled by src/app/api/a2a/tasks/route.ts), which returns a unique task ID for subsequent operations:

POST /a2a/tasks HTTP/1.1
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": "task-123",
  "method": "fusion",
  "params": {
    "targets": ["gpt-4o", "claude-3-5-sonnet"],
    "messages": [{ "role": "user", "content": "Summarize the article." }]
  }
}

Response:

{
  "jsonrpc": "2.0",
  "id": "task-123",
  "result": {
    "taskId": "f7c2e9b1-9a4d-4e6a-8f3b-2c1d9e5a6b7c",
    "status": "pending"
  }
}

Task Monitoring and Cancellation

Clients query task progress via GET /a2a/tasks/<taskId> or check aggregate status through src/app/api/a2a/status/route.ts. The system supports cancellation through /a2a/tasks/[id]/cancel, allowing agents to terminate long-running operations gracefully.

Real-Time Communication with Server-Sent Events

For operations requiring real-time updates, OmniRoute streams progress via Server-Sent Events (SSE). The streaming implementation in src/lib/a2a/streaming.ts generates events for partial results, progress percentages, and completion signals.

Clients initiate streaming by requesting GET /a2a/tasks/<taskId>/stream with Accept: text/event-stream:


event: progress
data: {"percent":30}

event: chunk
data: {"content":"First part of the answer..."}

event: done
data: {"completion":"Final answer"}

This mechanism allows cloud agents to consume incremental outputs from lengthy inference operations without maintaining open HTTP connections for the entire duration.

Transport Flexibility and Skill Architecture

OmniRoute’s A2A server abstracts the transport layer to support diverse agent environments.

HTTP and STDIO Support

While the primary transport uses HTTP/JSON-RPC, the A2A server also supports STDIO for local agents such as CLI tools. The same dispatcher code in src/lib/a2a/taskExecution.ts handles both transport modes, allowing agents to communicate either via network calls or by piping JSON-RPC messages directly to the OmniRoute process.

Modular Skill System

Each JSON-RPC method corresponds to an A2A skill located in src/lib/a2a/skills/. Skills encapsulate reusable behaviors:

  • smartRouting.ts – Uses OmniRoute’s combo routing to select optimal providers
  • quotaManagement – Tracks and enforces usage limits
  • providerDiscovery – Locates available agent capabilities
  • fusion – Aggregates responses from multiple models

The dispatcher dynamically loads the appropriate skill, passes validated parameters, and returns the skill’s result as a JSON-RPC response, maintaining clean separation between protocol handling and business logic.

Summary

  • Standards Compliance: OmniRoute implements full JSON-RPC 2.0 in src/lib/a2a/schemas/a2a.ts, using Zod for rigorous validation of requests, responses, and errors.
  • Dispatch Architecture: The pipeline flows from src/app/a2a/route.ts through src/lib/a2a/taskExecution.ts to modular skills, mapping JSON-RPC methods to concrete capabilities.
  • Task Management: src/lib/a2a/taskManager.ts provides persistent state tracking for asynchronous operations, exposed via RESTful endpoints under /a2a/tasks.
  • Streaming Support: Real-time updates use SSE formatted according to A2A schemas, implemented in src/lib/a2a/streaming.ts.
  • Transport Agnostic: The same dispatcher handles both HTTP and STDIO transports, enabling local and cloud agents to interact seamlessly.

Frequently Asked Questions

What JSON-RPC methods does OmniRoute A2A support?

OmniRoute supports methods defined as A2A skills in src/lib/a2a/skills/, including smartRouting, quotaManagement, providerDiscovery, and fusion. Additional methods can be added by implementing new skill files that export a handler matching the JSON-RPC signature expected by src/lib/a2a/taskExecution.ts.

How does OmniRoute handle errors in JSON-RPC requests?

The system validates all incoming requests against Zod schemas in src/lib/a2a/schemas/a2a.ts. Validation failures return a JSON-RPC error object with code -32600 and message INVALID_REQUEST, following the JSON-RPC 2.0 specification. Method-specific errors are handled within individual skills and returned as standard error responses with appropriate codes and messages.

Can agents communicate with OmniRoute without using HTTP?

Yes. While the primary transport is HTTP via Next.js routes like src/app/a2a/route.ts, the A2A server also supports STDIO for local agents. The same src/lib/a2a/taskExecution.ts dispatcher handles both transports, allowing CLI tools and local processes to pipe JSON-RPC messages directly to the OmniRoute process without network overhead.

Where is task state persisted in the OmniRoute A2A server?

The TaskManager in src/lib/a2a/taskManager.ts maintains task state in memory for active operations while persisting metadata to the SQLite database via the generic DB layer. This hybrid approach provides fast access to runtime state with durable storage for audit trails and recovery.

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 →