A2A federation
Orbit agents speak the A2A (Agent-to-Agent) protocol v1.0.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
- Opt-in discovery — each agent can publish an A2A AgentCard at a stable URL once you turn discovery on (it ships off by default — see Discovery modes). Skills are derived from the agent’s tool list.
- JSON-RPC + REST — both transports are mounted, identically authenticated.
- Signed AgentCards — every served card carries a detached EdDSA JWS
signatures[]block (A2A v1.0 Signed Agent Card extension) — see AgentCard signing. - HMAC signing (legacy) — Stripe / Svix-style
X-A2A-Signature: t=…,v1=…with a ±60s replay window, still required on the task endpoints (/a2a,/a2a/tasks). - 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.
Discovery modes
A new agent does not serve a public AgentCard. Discovery is an explicit operator opt-in, controlled by the agent’sa2a_discovery_mode field. It has three values:
Set the mode on the agent before pointing a peer at the public URL:
public, the public /.well-known/agent-card.json route returns 404 (the response shape never distinguishes “discovery off” from “agent doesn’t exist”, to avoid leaking which agents exist). tenant mode keeps the card private — it serves only the authenticated dashboard route below, never the public one.
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.
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.
AgentCard signing
Every AgentCard Orbit serves (/.well-known/agent-card.json and the authenticated /a2a/card) carries a signatures[] block — the A2A v1.0 Signed Agent Card extension:
signatures) rendered in RFC 8785 (JCS) canonical form. Because the payload isn’t duplicated on the wire, a verifier reconstructs it from the card JSON it already fetched, plus the protected header. The signing key is Orbit’s existing Ed25519 Web Bot Auth key — the same key published at /public/.well-known/http-message-signatures-directory — so a peer that already resolves that JWKS directory can verify an AgentCard’s identity without any new key-distribution step. The kid in the protected header is the RFC 7638 thumbprint of that key.
This lets a third-party A2A client cryptographically verify which agent/org served a card without a shared secret. It’s fail-open: if no signing key is provisioned, the card is served unchanged with no signatures field — a missing/unparseable key never breaks agent discovery.
The signing key is configured via the DEVOTEL_AGENT_SIGNING_PRIVATE_KEY environment variable — an Ed25519 private key accepted as a PKCS#8 PEM block, or base64/base64url of the raw 32-byte seed. It’s optional and fail-open by design: leave it unset and cards serve unsigned, and outbound agent HTTP requests (tool calls, MCP client calls, agentic-commerce checkouts, webhook fan-out) go out unsigned too — signing must never block an agent’s ability to call a tool. Provision it to enable both signed AgentCards and outbound Web Bot Auth request signing.
signatures[] authenticates the AgentCard, not individual task calls. The task endpoints (/a2a, /a2a/tasks, tasks/get) still use the HMAC scheme below.
HMAC signing (task calls)
All public POST endpoints (/a2a and /a2a/tasks) require a signed request:
${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)
Discover a peer’s AgentCard
This returns a card only when the target agent’sa2a_discovery_mode is public; otherwise it returns 404.
signatures[] block described in AgentCard signing. 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:id, status, output, etc.). Poll GET /api/v1/agents/{agentId}/a2a/tasks/{taskId} (the public REST shorthand for tasks/get, listed above) to follow progress. Like the POST endpoints, it requires an HMAC signature — sign over ${ts}. (the empty body).
Authenticated dashboard surface
These require a Clerk session and operate on the calling user’s tenant:Add a peer
(agent_id, peer_url) — re-adding upserts.
Delegate a task to a peer (outbound)
Tenant-scoping rules
- The
?tenant=<schemaName>query param value MUST match^tenant_[a-z0-9_]{8,80}$, matched case-insensitively (the regex carries the/iflag, so a mixed-case value such asTenant_Demois also accepted). If you validate the value client-side, use a case-insensitive test — e.g./^tenant_[a-z0-9_]{8,80}$/i— so you don’t reject a value the server accepts. Any other value is rejected — guards against?tenant=publicor admin-schema escalation attempts. - Tasks are stored on the tenant’s
agent_a2a_taskstable; peers onagent_a2a_peers. Both are isolated per-tenant.
Observability
Inbound + outbound tasks land in:- Dashboard — Agents → → A2A. Direction badges (
inbound/outbound), status pills, latency. Task envelopes are stored onagent_a2a_tasksand surfaced here. - Audit log — peer lifecycle is recorded as
agent.a2a.peer_addedandagent.a2a.peer_removed. (Task delivery is not audited; inspect it via the dashboard A2A tab.)
Error codes
Spec compliance
Orbit implements A2A v1.0.0, including the Signed Agent Card extension (see AgentCard signing) — 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.AP2 mandates across networks
A2A tasks a peer agent; AP2 is the adjacent protocol a peer uses to prove it was authorized to transact on someone’s behalf. When you’re federating with agents on another AP2 network — Mastercard, PayPal, or Google-side agents — a mandate can now carry an Ed25519-signed, W3C Verifiable-Credential proof instead of Orbit’s own platform-only signature, and Orbit’s mandate verifier resolves the issuer’s public key from a JWKS/DID directory (Orbit’s own by default, or a peer network’s when you point it at theirs) before trusting the mandate’s claims. That’s what lets an Orbit agent accept a mandate issued by another network’s agent, and vice versa, without the two networks sharing a secret.See also
- Agents API — agent CRUD, tools, knowledge bases.
- Webhooks → Security — same HMAC-with-replay-window scheme as A2A.
- Agent handoff targets — internal handoff between agents in the same tenant.