Skip to main content
ForceAI’s A2A agents proxy to an upstream A2A server; the gateway does not run a model for an A2A agent. So to build an agent whose brain is ForceAI’s own smart-router, you put a small A2A server in the middle. It receives the A2A message, calls the gateway’s OpenAI-compatible /v1/chat/completions with model: smart-router, and returns the answer as an A2A artifact
The outer A2A hop is fully governed, and the inner chat-completions call is routed by smart-router and is itself subject to your guardrails. A reference implementation ships in deploy/smart-router-agent/

The wrapper

A minimal FastAPI A2A server. On each message/send it joins the text parts (a ForceAI system-knowledge document, if attached, arrives as the leading part), calls the gateway, and returns a completed A2A task
The A2A result must be a valid Task (or Message); returning a bare {"artifacts": [...]} makes the gateway hand the caller an empty result
Give the wrapper a virtual key scoped to the models it may call, not your admin key. The wrapper authenticates to the gateway as any other API client

Run it

The reference agent is wired into the compose stack and reaches the gateway over the compose network

Onboard it

Register the wrapper as an A2A Standard agent, pointing at its URL (compose DNS http://smart-router-agent:9100/ from the gateway’s perspective)
New agents start pending; approve it before it can be invoked
In the dashboard you can do the same under Agents -> Add New Agent -> A2A Standard, and optionally attach a System knowledge document on the Configure step; it is injected as leading instructions on every call

Invoke it

The answer is produced by smart-router, and the Logs page records the inner hop as model: smart-router. Because the guardrail runs on that inner call, a prompt the guardrail blocks returns a 400 from the agent, exactly as a direct chat completion would

Exposing it to external users

Everything is the gateway, one surface, two protocols, all authenticated with a virtual key:
  • Models and the smart-router: POST /v1/chat/completions (OpenAI-compatible)
  • Agents: POST /a2a/{agent_id}/message/send and /message/stream (A2A JSON-RPC), plus GET /a2a/{agent_id} for the card
Mint a virtual key, scope it to the specific models and agents the user may reach, and hand them the key. They call the same endpoints you do