# Configuring A2A Agent Protocol for Task Delegation in OmniRoute

> Learn how to configure the A2A agent protocol for task delegation in OmniRoute. Enable A2A and use the JSON-RPC endpoint to submit tasks with skills and messages.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-08-15

---

**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:

```bash
A2A_ENABLED=1

```

Or modify [`src/shared/constants/featureFlagDefinitions.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/featureFlagDefinitions.ts) to enable the flag permanently.

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

```bash
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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/a2a/route.ts) accepts JSON-RPC 2.0 requests with this structure:

```json
{
  "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`](https://github.com/diegosouzapw/OmniRoute/blob/main/.well-known/agent.json))

The REST endpoint in [`src/app/api/a2a/status/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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 `TaskArtifact`s) 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:

```typescript
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

```bash

# 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/a2a/skills/myCustomSkill.ts):

```typescript
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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/a2a/taskExecution.ts) by adding to `A2A_SKILL_HANDLERS`:

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

```

## Configuration Reference

| File | Purpose |
|------|---------|
| [`src/lib/a2a/taskManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/a2a/taskManager.ts) | Task lifecycle, TTL cleanup, stats aggregation |
| [`src/lib/a2a/taskExecution.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/a2a/route.ts) | JSON-RPC protocol entry point |
| [`src/app/api/a2a/status/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/a2a/status/route.ts) | REST agent card and statistics |
| [`docs/frameworks/A2A-SERVER.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/.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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/a2a/taskManager.ts). Expired or terminal tasks are automatically cleaned up from the in-memory store.