How the A2A v0.3 Protocol Integrates with OmniRoute Skills: Architecture and Implementation

The A2A v0.3 protocol integrates with OmniRoute skills through a JSON-RPC 2.0 transport layer that maps incoming method calls to asynchronous skill handlers in src/lib/a2a/taskExecution.ts, enabling agent-to-agent communication via a unified task lifecycle managed by A2ATaskManager.

The A2A (Agent-to-Agent) v0.3 protocol provides a standardized interface for external agents to invoke capabilities within the OmniRoute ecosystem. As implemented in the diegosouzapw/OmniRoute repository (release v3.8.49), this protocol exposes six built-in skills—from smart routing to health reporting—through a type-safe JSON-RPC endpoint. Understanding this integration reveals how OmniRoute transforms internal business logic into remotely accessible agent capabilities.

Architecture Overview

JSON-RPC 2.0 Transport Layer

The protocol implements a JSON-RPC 2.0 transport endpoint at src/app/a2a/route.ts. This Next.js API route authenticates incoming requests, parses the JSON-RPC payload, and forwards validated calls to the task manager. The implementation maintains strict compliance with the A2A v0.3 specification while bridging to OmniRoute's internal TypeScript modules.

Request Flow

Incoming requests follow a predictable pipeline: the route handler creates an A2ATask instance via A2ATaskManager, dispatches the task to a registered skill handler, and returns the results as JSON-RPC responses. For streaming operations, src/lib/a2a/streaming.ts wraps output in Server-Sent Events (SSE) while preserving the JSON-RPC envelope structure.

Task Lifecycle and Skill Dispatch

A2ATaskManager Instance

The global A2ATaskManager singleton defined in src/lib/a2a/taskManager.ts governs the complete task lifecycle: created → running → completed → failed/cancelled. When a request creates a task, the manager assigns a unique task ID, tracks execution state, and maintains the artifacts array that stores skill outputs such as Markdown tables or cost estimates.

Skill Dispatch Table

The core integration point resides in src/lib/a2a/taskExecution.ts as the A2A_SKILL_HANDLERS record. This dispatch table maps string skill names to asynchronous handler functions using the signature (task: A2ATask) => Promise<...>. Each entry points to a concrete implementation in the src/lib/a2a/skills/ directory.

Built-in A2A Skills

OmniRoute ships with six self-contained A2A skills, each exposing a specific domain capability:

  • smart-routing: Executes provider selection logic via executeSmartRouting in src/lib/a2a/skills/smartRouting.ts
  • quota-management: Reports remaining quota by querying src/lib/db/quotaSnapshots.ts through executeQuotaManagement
  • provider-discovery: Lists known providers and models via executeProviderDiscovery
  • cost-analysis: Estimates request costs using executeCostAnalysis
  • health-report: Returns router health metrics via executeHealthReport
  • list-capabilities: Generates the Agent Card "Capabilities" artifact through executeListCapabilities

Skill Signature and Artifacts

Every skill adheres to a uniform interface receiving the A2ATask object. Skills populate the task.artifacts array with structured outputs—typically Markdown content—before returning a status object. For example, executeListCapabilities retrieves skill rows from the database, renders them as a Markdown table, and pushes the result into task.artifacts before marking the task completed.

Integration Points

Database Access

A2A skills leverage existing OmniRoute data layers rather than duplicating logic. The quota-management skill directly queries src/lib/db/quotaSnapshots.ts to surface live quota data, while smart-routing utilizes internal combo-routing algorithms. This tight coupling ensures A2A responses reflect real-time system state.

Streaming Support

For long-running or incremental responses, the protocol supports streaming via src/lib/a2a/streaming.ts. The implementation wraps task outputs in SSE streams, allowing clients to receive partial results while maintaining the JSON-RPC response format. This proves essential for capabilities that require progressive disclosure of routing decisions.

Discovery and UI Integration

The Agent Card catalog at src/lib/agentSkills/catalog.ts automatically registers all six A2A skills, making them discoverable to external agents. Within the OmniRoute dashboard, src/app/(dashboard)/dashboard/a2a/A2ADashboardPage.tsx renders an "A2A" tab for manual skill invocation. Developers can also trigger skills via the CLI command wrapper at bin/cli/commands/a2a.mjs.

Code Examples

The following example demonstrates invoking the list-capabilities skill via HTTP:

// Client-side invocation of the A2A protocol
const response = await fetch("/api/a2a/tasks", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    method: "list-capabilities",
    params: {},
    id: "req-123"
  })
});

const result = await response.json();
// Returns: { taskId: "a2a-01", status: "completed", artifacts: [...] }

The dispatch table in src/lib/a2a/taskExecution.ts routes this request:

// Skill dispatch table implementation
export const A2A_SKILL_HANDLERS: Record<string, A2ASkillHandler> = {
  "smart-routing": executeSmartRouting,
  "quota-management": executeQuotaManagement,
  "provider-discovery": executeProviderDiscovery,
  "cost-analysis": executeCostAnalysis,
  "health-report": executeHealthReport,
  "list-capabilities": executeListCapabilities,
};

A skill implementation follows this pattern:

// src/lib/a2a/skills/listCapabilities.ts
export async function executeListCapabilities(task: A2ATask) {
  const rows = await getAllSkillRows(); // Database query
  const markdown = renderMarkdownTable(rows);
  
  task.artifacts.push({ 
    type: "markdown", 
    content: markdown 
  });
  
  return { 
    status: "completed", 
    artifacts: task.artifacts 
  };
}

Summary

  • The A2A v0.3 protocol exposes OmniRoute capabilities via JSON-RPC 2.0 through the endpoint src/app/a2a/route.ts
  • A2ATaskManager in src/lib/a2a/taskManager.ts handles the task lifecycle (created → running → completed)
  • The A2A_SKILL_HANDLERS dispatch table in src/lib/a2a/taskExecution.ts routes calls to six built-in skills
  • Skills reside in src/lib/a2a/skills/ and follow the signature (task: A2ATask) => Promise<...>
  • Streaming support via src/lib/a2a/streaming.ts enables Server-Sent Events for long-running operations
  • Full integration with existing data layers allows skills to query live system state without logic duplication

Frequently Asked Questions

How does OmniRoute authenticate A2A v0.3 protocol requests?

Authentication occurs at the entry point in src/app/a2a/route.ts before the JSON-RPC payload reaches the task manager. The route validates credentials according to configured OmniRoute security policies, ensuring only authorized agents can invoke skills.

Can custom skills be added to the A2A v0.3 protocol implementation?

Yes. Developers can extend the A2A_SKILL_HANDLERS record in src/lib/a2a/taskExecution.ts with new key-value pairs, implementing handlers that follow the (task: A2ATask) => Promise<...> signature. New skills must be registered in src/lib/agentSkills/catalog.ts to appear in the Agent Card discovery mechanism.

What is the difference between A2A skills and regular OmniRoute functions?

A2A skills are specifically wrapped to comply with the A2A v0.3 specification, including JSON-RPC envelope handling, artifact generation, and task lifecycle management through A2ATaskManager. Regular OmniRoute functions lack this standardized interface and task state tracking, though skills often delegate to internal functions for business logic.

How does streaming work for A2A skills that take time to execute?

Long-running skills utilize the streaming utilities in src/lib/a2a/streaming.ts, which wraps task outputs in Server-Sent Events (SSE). This allows the client to receive incremental updates while the task remains in "running" status, with final completion signaled when the handler returns and the task status updates to "completed".

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 →