Documentation Index
Fetch the complete documentation index at: https://orbit-docs.devotel.io/llms.txt
Use this file to discover all available pages before exploring further.
A2A federation
Orbit agents speak the A2A (Agent-to-Agent) protocol v0.3.0, so any A2A-conformant peer can discover and task an Orbit agent, and any of your Orbit agents can task remote A2A peers (Google AgentSpace, Azure AI Foundry, Bedrock AgentCore, ServiceNow, SAP, Salesforce, Workday, IBM, custom builds — anything that implements the spec).
This is the only standardised cross-vendor agent-to-agent protocol with broad ecosystem adoption (150+ orgs in production by April 2026). On Orbit it is GA and per-tenant.
What you get
- Public discovery — every agent ships an A2A AgentCard at a stable URL. Skills are derived from the agent’s tool list.
- JSON-RPC + REST — both transports are mounted, identically authenticated.
- HMAC signing — Stripe / Svix-style
X-A2A-Signature: t=…,v1=… with a ±60s replay window.
- Per-tenant ledger — every inbound and outbound task is persisted with full input / output / status / direction so the dashboard can render task history and you have an audit trail.
- Peer registry — known peers are cached per agent. The platform fetches the peer’s AgentCard on add and stores it for discovery.
Public surface (for peers + spec-compliant clients)
These endpoints DO NOT use the dashboard session. Tenants are resolved from a ?tenant=<schemaName> query param baked into the AgentCard URL.
| Method | Path | Spec role |
|---|
GET | /v1/agents/{agentId}/.well-known/agent-card.json?tenant=<schema> | Canonical AgentCard (A2A v0.3 §4.4). |
GET | /v1/agents/{agentId}/.well-known/agent.json?tenant=<schema> | Legacy v0.2 alias — same payload. |
POST | /v1/agents/{agentId}/a2a | JSON-RPC 2.0 entry point. Methods: agent/discover, tasks/send, tasks/get, tasks/cancel. |
POST | /v1/agents/{agentId}/a2a/tasks | REST shorthand for tasks/send. |
GET | /v1/agents/{agentId}/a2a/tasks/{taskId} | REST shorthand for tasks/get. |
Get the per-agent canonical AgentCard URL from Agents → → A2A → Copy share URL in the dashboard. The URL is the only thing a peer needs.
HMAC signing
All public POST endpoints (/a2a and /a2a/tasks) require a signed request:
X-A2A-Signature: t=<unix_seconds>,v1=<hex_sha256>
The signed payload is ${ts}.${rawBody}. Replay window is ±60 s. The platform uses constant-time comparison after explicit length-equality.
The HMAC key is the per-org A2A secret, configurable via DEVOTEL_A2A_HMAC_SECRET. It falls back to DEVOTEL_API_SECRET_KEY for fresh deployments.
The A2A spec (§4.5) lists OAuth2 / OIDC / API Key / HTTP-Auth / mTLS as supported security schemes; Orbit advertises HMAC as an APIKeySecurityScheme (header location, name X-A2A-Signature) — a spec-compatible escape hatch for peers without OAuth tooling.
Signing example (Node.js)
import { createHmac } from "node:crypto";
const ts = Math.floor(Date.now() / 1000).toString();
const rawBody = JSON.stringify({ jsonrpc: "2.0", method: "tasks/send", id: 1, params: { /* ... */ } });
const sig = createHmac("sha256", process.env.A2A_HMAC_SECRET!)
.update(`${ts}.${rawBody}`)
.digest("hex");
await fetch("https://orbit-api.devotel.io/api/v1/agents/agent_abc/a2a?tenant=tenant_demo", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-A2A-Signature": `t=${ts},v1=${sig}`,
},
body: rawBody,
});
Discover a peer’s AgentCard
curl "https://orbit-api.devotel.io/api/v1/agents/agent_abc/.well-known/agent-card.json?tenant=tenant_demo"
The response follows the A2A spec. Skills are derived from the agent’s configured tools; an agent with no tools surfaces a single default skill keyed on agent.type.
Task an Orbit agent (inbound)
JSON-RPC:
curl -X POST https://orbit-api.devotel.io/api/v1/agents/agent_abc/a2a?tenant=tenant_demo \
-H "Content-Type: application/json" \
-H "X-A2A-Signature: t=1746783262,v1=..." \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tasks/send",
"params": {
"skill_id": "lookup_order",
"message": {
"role": "user",
"parts": [{ "kind": "text", "text": "What is the status of order ORD-12345?" }]
}
}
}'
REST shorthand:
curl -X POST https://orbit-api.devotel.io/api/v1/agents/agent_abc/a2a/tasks?tenant=tenant_demo \
-H "Content-Type: application/json" \
-H "X-A2A-Signature: t=1746783262,v1=..." \
-d '{
"skill_id": "lookup_order",
"message": {
"role": "user",
"parts": [{ "kind": "text", "text": "What is the status of order ORD-12345?" }]
}
}'
Both return a Task envelope (id, status, output, etc.). Poll GET /a2a/tasks/{taskId} to follow progress.
Authenticated dashboard surface
These require a Clerk session and operate on the calling user’s tenant:
| Method | Path | Purpose |
|---|
GET | /v1/agents/{agentId}/a2a/card | Full AgentCard + the operator-shareable public URL. |
GET | /v1/agents/{agentId}/a2a/tasks | Inbound + outbound task history. |
POST | /v1/agents/{agentId}/a2a/tasks/outbound | Operator-initiated outbound task to a known peer. |
GET | /v1/agents/{agentId}/a2a/peers | List known peers for this agent. |
POST | /v1/agents/{agentId}/a2a/peers | Register a peer. The platform fetches its AgentCard on add. |
DELETE | /v1/agents/{agentId}/a2a/peers/{peerId} | Remove a peer. |
Add a peer
curl -X POST https://orbit-api.devotel.io/api/v1/agents/agent_abc/a2a/peers \
-H "X-API-Key: dv_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"peer_url": "https://partner.example.com/api/v1/agents/billing-bot/.well-known/agent-card.json"
}'
The platform fetches the AgentCard, stores it on the peer row, and surfaces the peer’s skill catalog in the dashboard. The peer URL is keyed unique per (agent_id, peer_url) — re-adding upserts.
Delegate a task to a peer (outbound)
curl -X POST https://orbit-api.devotel.io/api/v1/agents/agent_abc/a2a/tasks/outbound \
-H "X-API-Key: dv_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"peer_id": "a2ap_xyz",
"skill_id": "billing_status",
"message": {
"role": "user",
"parts": [{ "kind": "text", "text": "Get the current invoice for tenant 42." }]
}
}'
Persists an outbound task envelope, signs the request, and forwards. The response carries the peer’s task id; the dashboard surfaces both sides of the round-trip in the agent’s A2A tab.
Tenant-scoping rules
- The
?tenant=<schemaName> query param value MUST match ^tenant_[a-z0-9_]{8,80}$. Any other value is rejected — guards against ?tenant=public or admin-schema escalation attempts.
- Tasks are stored on the tenant’s
agent_a2a_tasks table; peers on agent_a2a_peers. Both are isolated per-tenant.
Observability
Inbound + outbound tasks land in:
- Dashboard — Agents → → A2A. Direction badges (
inbound / outbound), status pills, latency.
- Audit log —
a2a.task.received, a2a.task.delegated, a2a.peer.added, a2a.peer.removed.
- Webhooks —
a2a.task.completed, a2a.task.failed (per-tenant subscription).
Error codes
| Code | HTTP | Cause |
|---|
A2A_INVALID_SIGNATURE | 401 | HMAC missing, malformed, expired, or mismatched. |
A2A_INVALID_TENANT | 422 | ?tenant= value does not match the required pattern. |
A2A_PEER_ERROR | 502 | Outbound delegation failed, or peer’s AgentCard endpoint is unreachable. |
A2A_SKILL_NOT_FOUND | 404 | The requested skill_id is not on the agent’s AgentCard. |
Spec compliance
Orbit implements A2A v0.3.0 — see the protocol spec and the reference proto. Task envelopes, AgentCard structure, JSON-RPC method names, and the part-oneof for messages all match the spec.
See also