Build your own agent on ForceAI's smart-router (A2A)
Wrap ForceAI’s smart-router in a thin A2A server so you get a governed agent whose brain is ForceAI’s own model routing.
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
client ──A2A──▶ ForceAI Gateway (key, RBAC, guardrails, system-knowledge, audit) │ forwards message/send ▼ Your A2A wrapper ──▶ POST /v1/chat/completions (model: smart-router) ▲ │ └───── answer ◀───────────┘ gateway routes to the best LLM
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
GATEWAY_URL = os.environ["FORCEAI_GATEWAY_URL"] # e.g. http://forceai-gateway:4000API_KEY = os.environ["FORCEAI_API_KEY"] # a ForceAI virtual keyMODEL = os.environ.get("FORCEAI_MODEL", "smart-router")async def ask(prompt: str) -> str: async with httpx.AsyncClient(timeout=60) as c: r = await c.post(f"{GATEWAY_URL}/v1/chat/completions", headers={"Authorization": f"Bearer {API_KEY}"}, json={"model": MODEL, "messages": [{"role": "user", "content": prompt}]}) r.raise_for_status() return r.json()["choices"][0]["message"]["content"]
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
docker compose up -d --build smart-router-agentcurl -s http://localhost:9100/.well-known/agent-card.json # sanity check the card
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
curl -X POST https://YOUR_GATEWAY_DOMAIN/v1/agents/$AGENT_ID/approve -H "Authorization: Bearer $ADMIN_KEY"
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
curl -X POST https://YOUR_GATEWAY_DOMAIN/a2a/$AGENT_ID/message/send \ -H "Authorization: Bearer $VIRTUAL_KEY" -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":"1","method":"message/send", "params":{"message":{"role":"user","parts":[{"kind":"text","text":"Write a friendly one-sentence greeting."}],"messageId":"m1"}}}'
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
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"ForceAI Gateway","description":"Onboard LLM providers and create A2A agents in the ForceAI Gateway.","colors":{"primary":"#4e81ee","light":"#58c7ff","dark":"#0a0f22"},"api":{"playground":{"display":"simple"}},"footer":{"socials":{"github":"https://github.com/Techpro-Solution/litellm_forceai"}},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"forceaisecurity","hasAudioNarration":false,"actualSubdomain":"forceaisecurity","customDomains":["gateway.forceaisecurity.com"],"gitSource":{"type":"github","owner":"forceai-gateway","repo":"litellm_forceai","deployBranch":"litellm_forceai_v1","contentDirectory":"docs/forceai/mintlify","isPrivate":true,"mountPath":"","label":""},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ad8e83bb264ebf3acb5598e","clientVersion":"0.0.4138","searchFilterCounts":[{"language":"default","tag":"Guides","count":28},{"language":"default","tag":"A2A agents","count":9},{"language":"default","tag":"Admin settings","count":6},{"language":"default","tag":"API Reference","count":4},{"language":"default","tag":"Tools","count":3},{"language":"default","tag":"Get started","count":2},{"language":"default","tag":"LLM providers","count":2},{"language":"default","tag":"Agents","count":1},{"language":"default","tag":"Keys","count":1},{"language":"default","tag":"Models","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"agents/forceai-llm-a2a-agent","slug":"/agents/forceai-llm-a2a-agent","pageMetadata":{"title":"Build your own agent on ForceAI's smart-router (A2A)","description":"Wrap ForceAI's smart-router in a thin A2A server so you get a governed agent whose brain is ForceAI's own model routing.","href":"/agents/forceai-llm-a2a-agent"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Wrap ForceAI’s smart-router in a thin A2A server so you get a governed agent whose brain is ForceAI’s own model routing.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={code:`code`,em:`em`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`ForceAI’s A2A agents proxy to an upstream A2A server; the gateway does not run a model `,_jsx(_components.em,{children:`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 `,_jsx(_components.code,{children:`/v1/chat/completions`}),` with `,_jsx(_components.code,{children:`model: smart-router`}),`, and returns the answer as an A2A artifact`]}),`\n`,_jsx(CodeBlock,{numberOfLines:`7`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`7`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`client ──A2A──▶ ForceAI Gateway (key, RBAC, guardrails, system-knowledge, audit)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` │ forwards message/send`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` ▼`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Your A2A wrapper ──▶ POST /v1/chat/completions (model: smart-router)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` ▲ │`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` └───── answer ◀───────────┘ gateway routes to the best LLM`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsxs(_components.p,{children:[`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 `,_jsx(_components.code,{children:`deploy/smart-router-agent/`})]}),`\n`,_jsx(Heading,{level:`2`,id:`the-wrapper`,children:`The wrapper`}),`\n`,_jsxs(_components.p,{children:[`A minimal FastAPI A2A server. On each `,_jsx(_components.code,{children:`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`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`11`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`11`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`GATEWAY_URL = os.environ[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"FORCEAI_GATEWAY_URL\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# e.g. http://forceai-gateway:4000`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`API_KEY = os.environ[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"FORCEAI_API_KEY\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# a ForceAI virtual key`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`MODEL = os.environ.get(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"FORCEAI_MODEL\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"smart-router\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`async`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` def`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ask(prompt: str) -> str:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` async`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` with`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` httpx.AsyncClient(timeout=60) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`as`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` c:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` r = `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` c.post(f`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"{GATEWAY_URL}/v1/chat/completions\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` headers={`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Authorization\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: f`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Bearer {API_KEY}\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`},`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` json={`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"model\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: MODEL, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"messages\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [{`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"role\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"user\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"content\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: prompt}]})`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` r.raise_for_status()`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` r.json()[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"choices\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`][0][`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"message\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`][`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"content\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`The A2A `,_jsx(_components.code,{children:`result`}),` must be a valid Task (or Message); returning a bare `,_jsx(_components.code,{children:`{\"artifacts\": [...]}`}),` makes the gateway hand the caller an empty result`]}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`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`})}),`\n`,_jsx(Heading,{level:`2`,id:`run-it`,children:`Run it`}),`\n`,_jsx(_components.p,{children:`The reference agent is wired into the compose stack and reaches the gateway over the compose network`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`docker`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` compose up -d --build smart-router-agent`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` -s http://localhost:9100/.well-known/agent-card.json `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# sanity check the card`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`onboard-it`,children:`Onboard it`}),`\n`,_jsxs(_components.p,{children:[`Register the wrapper as an A2A Standard agent, pointing at its URL (compose DNS `,_jsx(_components.code,{children:`http://smart-router-agent:9100/`}),` from the gateway’s perspective)`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`16`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`16`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` -X POST https://YOUR_GATEWAY_DOMAIN/v1/agents \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` -H `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Authorization: Bearer $ADMIN_KEY\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` -H `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Content-Type: application/json\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` -d `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'{`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"agent_name\": \"forceai-smart-router-agent\",`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"agent_card_params\": {`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"protocolVersion\": \"0.3\",`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"name\": \"ForceAI Smart-Router Agent\",`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"description\": \"Brain is ForceAI smart-router\",`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"url\": \"http://smart-router-agent:9100/\",`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"version\": \"1.0.0\",`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"defaultInputModes\": [\"text\"],`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"defaultOutputModes\": [\"text\"],`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"capabilities\": { \"streaming\": false },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"skills\": [{ \"id\": \"chat\", \"name\": \"Chat\", \"description\": \"smart-router chat\", \"tags\": [\"llm\"] }]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` }'`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`New agents start `,_jsx(_components.code,{children:`pending`}),`; approve it before it can be invoked`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` -X POST https://YOUR_GATEWAY_DOMAIN/v1/agents/$AGENT_ID/approve -H `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Authorization: Bearer $ADMIN_KEY\"`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`In the dashboard you can do the same under Agents -> Add New Agent -> A2A Standard, and optionally attach a `,_jsx(_components.strong,{children:`System knowledge`}),` document on the Configure step; it is injected as leading instructions on every call`]}),`\n`,_jsx(Heading,{level:`2`,id:`invoke-it`,children:`Invoke it`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`4`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` -X POST https://YOUR_GATEWAY_DOMAIN/a2a/$AGENT_ID/message/send \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` -H `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Authorization: Bearer $VIRTUAL_KEY\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` -H `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Content-Type: application/json\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` -d `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"method\":\"message/send\",`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"params\":{\"message\":{\"role\":\"user\",\"parts\":[{\"kind\":\"text\",\"text\":\"Write a friendly one-sentence greeting.\"}],\"messageId\":\"m1\"}}}'`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`The answer is produced by smart-router, and the Logs page records the inner hop as `,_jsx(_components.code,{children:`model: smart-router`}),`. Because the guardrail runs on that inner call, a prompt the guardrail blocks returns a `,_jsx(_components.code,{children:`400`}),` from the agent, exactly as a direct chat completion would`]}),`\n`,_jsx(Heading,{level:`2`,id:`exposing-it-to-external-users`,children:`Exposing it to external users`}),`\n`,_jsx(_components.p,{children:`Everything is the gateway, one surface, two protocols, all authenticated with a virtual key:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Models and the smart-router: `,_jsx(_components.code,{children:`POST /v1/chat/completions`}),` (OpenAI-compatible)`]}),`\n`,_jsxs(_components.li,{children:[`Agents: `,_jsx(_components.code,{children:`POST /a2a/{agent_id}/message/send`}),` and `,_jsx(_components.code,{children:`/message/stream`}),` (A2A JSON-RPC), plus `,_jsx(_components.code,{children:`GET /a2a/{agent_id}`}),` for the card`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`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`})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Build your own agent on ForceAI's smart-router (A2A)","description":"Wrap ForceAI's smart-router in a thin A2A server so you get a governed agent whose brain is ForceAI's own model routing.","href":"/agents/forceai-llm-a2a-agent"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"The wrapper","slug":"the-wrapper","depth":2,"children":[]},{"title":"Run it","slug":"run-it","depth":2,"children":[]},{"title":"Onboard it","slug":"onboard-it","depth":2,"children":[]},{"title":"Invoke it","slug":"invoke-it","depth":2,"children":[]},{"title":"Exposing it to external users","slug":"exposing-it-to-external-users","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"forceaisecurity","siteName":"ForceAI Gateway","title":"Build your own agent on ForceAI's smart-router (A2A) - ForceAI Gateway","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-09-25T09:05:24.771Z","originalFileLocation":"agents/forceai-llm-a2a-agent.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Wrap ForceAI\u0026#x27;s smart-router in a thin A2A server so you get a governed agent whose brain is ForceAI\u0026#x27;s own model routing.\">\u003cmeta data-mint-head name=\"application-name\" content=\"ForceAI Gateway\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/forceaisecurity/_generated/favicon/apple-touch-icon.png?v=3\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/forceaisecurity/_generated/favicon/favicon-32x32.png?v=3\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/forceaisecurity/_generated/favicon/favicon-16x16.png?v=3\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/forceaisecurity/_generated/favicon/favicon.ico?v=3\">\u003cmeta data-mint-head property=\"og:title\" content=\"Build your own agent on ForceAI\u0026#x27;s smart-router (A2A) - ForceAI Gateway\">\u003cmeta data-mint-head property=\"og:description\" content=\"Wrap ForceAI\u0026#x27;s smart-router in a thin A2A server so you get a governed agent whose brain is ForceAI\u0026#x27;s own model routing.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"ForceAI Gateway\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://gateway.forceaisecurity.com/agents/forceai-llm-a2a-agent\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://forceaisecurity.mintlify.site/_mintlify/api/og/v2?division=A2A+agents\u0026amp;title=Build+your+own+agent+on+ForceAI%27s+smart-router+%28A2A%29\u0026amp;description=Wrap+ForceAI%27s+smart-router+in+a+thin+A2A+server+so+you+get+a+governed+agent+whose+brain+is+ForceAI%27s+own+model+routing.\u0026amp;theme=d4241f2f52b820d35dff3f5b\u0026amp;signature=68698b8f1acec7a3326f0b47bbce799e343ac0512c37e0c88c30b726a69dae03\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Build your own agent on ForceAI\u0026#x27;s smart-router (A2A) - ForceAI Gateway\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Wrap ForceAI\u0026#x27;s smart-router in a thin A2A server so you get a governed agent whose brain is ForceAI\u0026#x27;s own model routing.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://forceaisecurity.mintlify.site/_mintlify/api/og/v2?division=A2A+agents\u0026amp;title=Build+your+own+agent+on+ForceAI%27s+smart-router+%28A2A%29\u0026amp;description=Wrap+ForceAI%27s+smart-router+in+a+thin+A2A+server+so+you+get+a+governed+agent+whose+brain+is+ForceAI%27s+own+model+routing.\u0026amp;theme=d4241f2f52b820d35dff3f5b\u0026amp;signature=68698b8f1acec7a3326f0b47bbce799e343ac0512c37e0c88c30b726a69dae03\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"https://mintlify.s3.us-west-1.amazonaws.com/forceaisecurity/_generated/favicon/browserconfig.xml?v=3\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"ForceAI Gateway\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#4e81ee\">\u003clink data-mint-head rel=\"canonical\" href=\"https://gateway.forceaisecurity.com/agents/forceai-llm-a2a-agent\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/agents/forceai-llm-a2a-agent.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://gateway.forceaisecurity.com/#organization\",\"name\":\"ForceAI Gateway\",\"url\":\"https://gateway.forceaisecurity.com\"},{\"@type\":\"WebSite\",\"@id\":\"https://gateway.forceaisecurity.com#website\",\"name\":\"ForceAI Gateway\",\"url\":\"https://gateway.forceaisecurity.com\",\"publisher\":{\"@id\":\"https://gateway.forceaisecurity.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://gateway.forceaisecurity.com/agents/forceai-llm-a2a-agent#webpage\",\"url\":\"https://gateway.forceaisecurity.com/agents/forceai-llm-a2a-agent\",\"name\":\"Build your own agent on ForceAI's smart-router (A2A)\",\"description\":\"Wrap ForceAI's smart-router in a thin A2A server so you get a governed agent whose brain is ForceAI's own model routing.\",\"dateModified\":\"2026-09-25T09:05:24.771Z\",\"isPartOf\":{\"@id\":\"https://gateway.forceaisecurity.com#website\"},\"breadcrumb\":{\"@id\":\"https://gateway.forceaisecurity.com/agents/forceai-llm-a2a-agent#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://gateway.forceaisecurity.com/agents/forceai-llm-a2a-agent#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"A2A agents\",\"item\":\"https://gateway.forceaisecurity.com/agents/overview\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Build your own agent on ForceAI's smart-router (A2A)\",\"item\":\"https://gateway.forceaisecurity.com/agents/forceai-llm-a2a-agent\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://gateway.forceaisecurity.com/agents/forceai-llm-a2a-agent#article\",\"headline\":\"Build your own agent on ForceAI's smart-router (A2A)\",\"name\":\"Build your own agent on ForceAI's smart-router (A2A)\",\"description\":\"Wrap ForceAI's smart-router in a thin A2A server so you get a governed agent whose brain is ForceAI's own model routing.\",\"url\":\"https://gateway.forceaisecurity.com/agents/forceai-llm-a2a-agent\",\"mainEntityOfPage\":{\"@id\":\"https://gateway.forceaisecurity.com/agents/forceai-llm-a2a-agent#webpage\"},\"dateModified\":\"2026-09-25T09:05:24.771Z\",\"publisher\":{\"@id\":\"https://gateway.forceaisecurity.com/#organization\"},\"isPartOf\":{\"@id\":\"https://gateway.forceaisecurity.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"ForceAI Gateway\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"ForceAI Gateway\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/agents/forceai-llm-a2a-agent.md","siteName":"ForceAI Gateway","nav":{"global":null,"tabs":[{"tab":"Guides","groups":[{"group":"Get started","pages":[{"title":"ForceAI Gateway guides","href":""},{"title":"Admin onboarding","href":"/admin-onboarding"}]},{"group":"LLM providers","pages":[{"title":"Onboard an existing provider","href":"/providers/onboard-existing-provider"},{"title":"Add a new provider","href":"/providers/add-new-provider"}]},{"group":"A2A agents","pages":[{"title":"A2A agents overview","description":"Register an external agent as an A2A endpoint in the ForceAI Gateway, then govern and call it like any model.","href":"/agents/overview"},{"title":"Build your own agent on ForceAI's smart-router (A2A)","href":"/agents/forceai-llm-a2a-agent"},{"title":"Run a single-shot ephemeral agent","description":"Spawn a ForceAI-managed agent instance on demand, run one task, and let it hard-kill itself - all over the runtime API.","href":"/agents/ephemeral-agent"},{"title":"Run an agent in an isolated sandbox","href":"/agents/isolated-sandbox"},{"title":"Run a multi-agent orchestration","href":"/agents/agent-orchestrator"},{"title":"Snowflake Cortex Agent (A2A)","href":"/agents/snowflake-cortex"},{"title":"AWS Bedrock AgentCore (A2A)","href":"/agents/aws-agentcore"},{"title":"Microsoft 365 Copilot (A2A)","href":"/agents/m365-copilot"},{"title":"Microsoft 365 Tool Adapter","href":"/agents/m365-adapter"}]},{"group":"Skills","pages":[{"title":"Configure the skill store (S3 or minio)","href":"/skills/configure-s3-store"}]},{"group":"Knowledge Catalog","pages":[{"title":"Knowledge Catalog (OKF)","href":"/knowledge-catalog/okf-grounding"}]},{"group":"Single sign-on","pages":[{"title":"Set up SSO for the dashboard","href":"/sso/configure-sso"}]},{"group":"Admin settings","pages":[{"title":"UI Settings reference","href":"/admin/ui-settings"},{"title":"Response caching","href":"/admin/response-caching"},{"title":"Memory","href":"/admin/memory"},{"title":"Budgets","href":"/admin/budgets"},{"title":"Model Evaluations","href":"/admin/model-evaluations"},{"title":"Team member key permissions","href":"/admin/team-key-permissions"}]},{"group":"Tools","pages":[{"title":"Connector providers (MCP)","href":"/tools/mcp-connector"},{"title":"Search tools","href":"/tools/search-tools"},{"title":"Tool policies","href":"/tools/tool-policies"}]},{"group":"Guardrails","pages":[{"title":"Attachment policy","href":"/guardrails/attachment-policy"}]},{"group":"Command line","pages":[{"title":"ForceAI CLI","href":"/cli/forceai-cli"}]},{"group":"Coding tools","pages":[{"title":"Connect Claude Code","href":"/coding/claude-code"}]}]},{"tab":"API Reference","pages":[{"title":"API Reference","href":"/api-reference/chat-completion"}]}]},"basePath":"","title":"Build your own agent on ForceAI's smart-router (A2A) - ForceAI Gateway","buildId":"dpl_715YoAgvjTGBDdo8RtXmHKM22b5p","deploymentId":"dpl_715YoAgvjTGBDdo8RtXmHKM22b5p","dynamics":[],"chunks":[]}