OmniRoute A2A Server Documentation
v3.8.1Last updated: 2026-05-13
Was this page helpful?
Loading OmniRoute...
Last updated: 2026-05-13
Was this page helpful?
(canonical entry point, defined in ).
- REST under
for dashboards and tooling (status, task list, cancel).
(, default 5-minute TTL). Skills are dispatched via in .
curl http://localhost:20128/.well-known/agent.json
field is sourced from (see ), so it stays auto-synced with on every release.
requests require an API key via the header:
Endpoints → A2A toggle and is disabled by default. When disabled,
reports and ; JSON-RPC calls to
return HTTP 503 with JSON-RPC error code .
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"}
}
}'
Response:
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"task": { "id": "uuid", "state": "completed" },
"artifacts": [{ "type": "text", "content": "..." }],
"metadata": {
"routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
"cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
"resilience_trace": [
{ "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
],
"policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
}
}
}
but returns Server-Sent Events for real-time streaming.
curl -N -X POST http://localhost:20128/a2a \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_KEY" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "message/stream",
"params": {
"skill": "smart-routing",
"messages": [{"role": "user", "content": "Explain quantum computing"}]
}
}'
SSE Events:
curl -X POST http://localhost:20128/a2a \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_KEY" \
-d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
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/cancel","params":{"taskId":"TASK_UUID"}}'
. Each skill module lives in .
| Skill | ID | Description |
|---|---|---|
| Smart Routing | |
Routes a prompt through the optimal provider/combo using OmniRoute's combo engine + scoring |
| Quota Management | |
Reports per-provider quota state, helps callers decide when to throttle/switch |
| Provider Discovery | |
Lists installed providers with capabilities, free-tier flags, OAuth status |
| Cost Analysis | |
Estimates cost of a request/conversation given the catalog + recent usage |
| Health Report | |
Aggregates circuit breaker, cooldown, lockout state per provider |
and ). The actual catalog has grown to 180+ providers — the string should be updated in a follow-up change (tracked as a separate doc/code TODO; not modified here).
is the canonical A2A entry point. The REST endpoints below provide auxiliary access for dashboards and external tooling:
| Endpoint | Method | Description | Auth |
|---|---|---|---|
|
GET | Server status, registered skills | (public) |
|
GET | List tasks with filters | management |
|
GET | Get task by ID | management |
|
POST | Cancel running task | management |
|
GET | Agent Card (A2A discovery) | (public, cached 3600s) |
. Follow the shape of existing skills such as .
- Register handler: in
, add an entry to :
export const A2A_SKILL_HANDLERS = {
// ...existing skills
"your-skill": async (task) => {
const skillModule = await import("./skills/yourSkill");
return skillModule.executeYourSkill(task);
},
};
- Expose in Agent Card: in
, append to the array:
{
"id": "your-skill",
"name": "Your Skill",
"description": "Brief, intent-focused description",
"tags": ["routing", "quota"],
"examples": ["Sample natural-language invocation"]
}
- Write tests:
. Cover happy path + error path.
- Document the new skill in this file's
table.
(default 5 min) — configured in the constructor at . To customize, fork the instantiation and pass a different value (e.g., for 15-minute TTL). A background interval sweeps expired tasks every 60 seconds.
, | Code | Meaning |
|---|---|
| -32700 | Parse error (invalid JSON) |
| -32600 | Invalid request / Unauthorized |
| -32601 | Method or skill not found |
| -32602 | Invalid params |
| -32603 | Internal error |
| -32000 | A2A endpoint is disabled |
import requests
resp = requests.post("http://localhost:20128/a2a", json={
"jsonrpc": "2.0", "id": "1",
"method": "message/send",
"params": {
"skill": "smart-routing",
"messages": [{"role": "user", "content": "Hello"}]
}
}, headers={"Authorization": "Bearer YOUR_KEY"})
result = resp.json()["result"]
print(result["artifacts"][0]["content"])
print(result["metadata"]["routing_explanation"])
const resp = await fetch("http://localhost:20128/a2a", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer YOUR_KEY",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "message/send",
params: {
skill: "smart-routing",
messages: [{ role: "user", content: "Hello" }],
},
}),
});
const { result } = await resp.json();
console.log(result.metadata.routing_explanation);