Configuring A2A Agent Protocol for Task Delegation in OmniRoute

To configure A2A agent protocol for task delegation in OmniRoute, enable the A2A_ENABLED feature flag and use the JSON-RPC endpoint at /api/a2a to submit tasks with a specified skill and messages.

OmniRoute ships a built-in A2A (Agent-to-Agent) server that exposes a JSON-RPC 2.0 endpoint together with a REST wrapper for status inspection. This system enables external agents to delegate work to OmniRoute by sending structured task descriptions, selecting from available skills, and receiving generated artifacts. According to the OmniRoute source code, the A2A subsystem is organized into distinct layers for task lifecycle management, skill dispatch, and protocol entry points.

Enabling the A2A Server

The A2A server is gated by the feature flag A2A_ENABLED, which defaults to false. To activate task delegation capabilities, set the environment variable or update the feature flag definition.

Set via environment variable:

A2A_ENABLED=1

Or modify src/shared/constants/featureFlagDefinitions.ts to enable the flag permanently.

Once enabled, verify activation by checking the REST status endpoint:

curl /api/a2a/status

This returns A2ATaskStats and confirms that A2A is active.

How the A2A Task Delegation Protocol Works

The A2A implementation in OmniRoute follows a strict three-layer architecture:

1. Task Lifecycle Management (A2ATaskManager)

Located in src/lib/a2a/taskManager.ts, the A2ATaskManager class handles:

  • UUID v4 assignment for each incoming task
  • State tracking through submitted → working → completed|failed|cancelled
  • TTL enforcement with a default 5-minute expiration
  • Automatic cleanup of expired or terminal tasks

The state machine uses VALID_TRANSITIONS to prevent illegal state jumps, ensuring deterministic task progression.

2. Skill Dispatch (A2A_SKILL_HANDLERS)

The registry in src/lib/a2a/taskExecution.ts maps skill strings to async handlers. Six built-in skills are available under src/lib/a2a/skills/:

Skill Purpose
smart-routing Intelligent request routing decisions
quota-management Usage limit enforcement and tracking
provider-discovery Available model/provider enumeration
cost-analysis Pricing estimation and comparison
health-report System status and diagnostic reporting
list-capabilities Available feature enumeration

3. JSON-RPC Entry Point (/api/a2a)

The Next.js App Router route in src/app/api/a2a/route.ts accepts JSON-RPC 2.0 requests with this structure:

{
  "jsonrpc": "2.0",
  "method": "task",
  "id": "<uuid>",
  "params": {
    "skill": "<skill-name>",
    "messages": [{"role": "...", "content": "..."}]
  }
}

The handler:

  1. Creates a task via getTaskManager().createTask()
  2. Dispatches to A2A_SKILL_HANDLERS[skill]
  3. Executes via executeA2ATaskWithState()
  4. Returns artifacts or error in the JSON-RPC response

4. Agent Discovery (.well-known/agent.json)

The REST endpoint in src/app/api/a2a/status/route.ts returns the agent card—a public manifest containing name, description, capabilities, skill catalog, and authentication scheme. This is cached for one hour and requires no authentication, allowing any A2A-compatible client to discover OmniRoute's delegation capabilities.

Task Delegation Flow

The complete sequence for A2A task delegation:

  1. Client sends JSON-RPC request to /api/a2a with skill and messages
  2. Router creates task via getTaskManager().createTask() → state submitted
  3. Skill handler executes — dynamically imports from src/lib/a2a/skills/ and runs
  4. State transitions to completed (with TaskArtifacts) or failed (with error)
  5. JSON-RPC response returns artifacts as text, JSON, or structured error

Implementing A2A Task Delegation

TypeScript Client Example

Submit a task programmatically using a JSON-RPC helper:

import { jsonRpc } from '@omniroute/open-sse';

async function runSmartRouting(messages: { role: string; content: string }[]) {
  const response = await jsonRpc.post('/api/a2a', {
    jsonrpc: '2.0',
    method: 'task',
    id: crypto.randomUUID(),
    params: {
      skill: 'smart-routing',
      messages,
    },
  });

  // response.result contains artifacts generated by the skill
  console.log('Artifacts:', response.result.artifacts);
}

CLI Inspection Commands


# Display the public agent card for discovery

omniroute a2a status card

# Submit a task and monitor state progression

omniroute a2a task submit \
  --skill smart-routing \
  --message "You are a helpful assistant."

Extending A2A with Custom Skills

Add domain-specific capabilities by creating a new skill module and registering it in the handler map.

Create src/lib/a2a/skills/myCustomSkill.ts:

import type { A2ATask, TaskArtifact } from '../taskManager';

export async function executeMyCustomSkill(task: A2ATask): Promise<{
  artifacts: TaskArtifact[];
  metadata: Record<string, unknown>;
}> {
  const result = `Echo: ${task.input.messages[0].content}`;
  
  return {
    artifacts: [{ type: 'text', content: result }],
    metadata: { echoLength: result.length },
  };
}

Register in src/lib/a2a/taskExecution.ts by adding to A2A_SKILL_HANDLERS:

"my-custom-skill": async (task) => 
  import('./skills/myCustomSkill').then(m => m.executeMyCustomSkill(task))

Configuration Reference

File Purpose
src/lib/a2a/taskManager.ts Task lifecycle, TTL cleanup, stats aggregation
src/lib/a2a/taskExecution.ts Skill registry and executeA2ATaskWithState
src/lib/a2a/skills/* Built-in and custom skill implementations
src/app/api/a2a/route.ts JSON-RPC protocol entry point
src/app/api/a2a/status/route.ts REST agent card and statistics
docs/frameworks/A2A-SERVER.md Design and extension guide

Summary

  • Enable A2A by setting A2A_ENABLED=1 or updating feature flags
  • Submit tasks via JSON-RPC to /api/a2a with a skill parameter and message array
  • Track lifecycle through A2ATaskManager states with automatic TTL cleanup
  • Discover capabilities via the unauthenticated .well-known/agent.json endpoint
  • Extend functionality by adding TypeScript modules to src/lib/a2a/skills/ and registering in A2A_SKILL_HANDLERS

Frequently Asked Questions

What is the A2A protocol in OmniRoute?

The A2A (Agent-to-Agent) protocol is a JSON-RPC 2.0 based task delegation system that allows external agents to offload work to OmniRoute. It provides structured task submission, skill-based routing, stateful tracking, and artifact retrieval through a publicly discoverable agent card.

How do I enable the A2A server in OmniRoute?

Set the environment variable A2A_ENABLED=1 before starting OmniRoute, or modify src/shared/constants/featureFlagDefinitions.ts to change the default. Verify activation by querying /api/a2a/status for task statistics and server confirmation.

What skills are available for A2A task delegation?

OmniRoute includes six built-in skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, and list-capabilities. Custom skills can be added by implementing an async handler in src/lib/a2a/skills/ and registering it in A2A_SKILL_HANDLERS.

How long do A2A tasks persist in OmniRoute?

Tasks have a default TTL of 5 minutes as enforced by A2ATaskManager in src/lib/a2a/taskManager.ts. Expired or terminal tasks are automatically cleaned up from the in-memory store.

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 →