diff --git a/docs/a2a.md b/docs/a2a.md index bd29f562..eaec6f98 100644 --- a/docs/a2a.md +++ b/docs/a2a.md @@ -61,7 +61,7 @@ Follow [this guide, to add your bedrock agentcore agent to LiteLLM Agent Gateway ### Add LangGraph Agents -Follow [this guide, to add your langgraph agent to LiteLLM Agent Gateway](./providers/langgraph#litellm-a2a-gateway) +Follow [this guide to register a LangGraph agent and configure its agent card](./providers/langgraph#register-a-langgraph-platform-agent) ### Add Pydantic AI Agents diff --git a/docs/a2a_agent_card.md b/docs/a2a_agent_card.md new file mode 100644 index 00000000..bac97830 --- /dev/null +++ b/docs/a2a_agent_card.md @@ -0,0 +1,157 @@ +# A2A Agent Card + +LiteLLM can proxy [A2A-compatible agents](https://a2a-protocol.org/latest/specification/), exposing them to your clients through LiteLLM with virtual keys, team scoping, observability, and a unified agent card. + +This page documents which A2A agent card fields LiteLLM supports today, how invocation works, and what to expect from the proxied agent card served at `/a2a/{agent_id}/.well-known/agent.json`. + +For provider-specific setup, see: + +- [Register a LangGraph Platform agent](./providers/langgraph#register-a-langgraph-platform-agent) + +## Agent card support + +The fields below mirror the A2A v1.0 specification ([§4.4 Agent Discovery Objects](https://a2a-protocol.org/latest/specification/)). A ✅ means the field is present in the agent card LiteLLM serves to clients; a ❌ means the field is not. + +### AgentCard (§4.4.1) + +| Field | Supported | +|---|---| +| `name` | ✅ | +| `description` | ✅ | +| `supportedInterfaces` | ✅ | +| `provider` | ✅ | +| `version` | ✅ | +| `documentationUrl` | ✅ | +| `capabilities` | ✅ | +| `securitySchemes` | ✅ | +| `securityRequirements` | ✅ | +| `defaultInputModes` | ✅ | +| `defaultOutputModes` | ✅ | +| `skills` | ✅ | +| `signatures` | ❌ | +| `iconUrl` | ✅ | + +### AgentProvider (§4.4.2) + +| Field | Supported | +|---|---| +| `url` | ✅ | +| `organization` | ✅ | + +### AgentCapabilities (§4.4.3) + +| Field | Supported | +|---|---| +| `streaming` | ✅ | +| `pushNotifications` | ❌ | +| `extensions` | ❌ | +| `extendedAgentCard` | ❌ | + +### AgentExtension (§4.4.4) + +| Field | Supported | +|---|---| +| `uri` | ❌ | +| `description` | ❌ | +| `required` | ❌ | +| `params` | ❌ | + +### AgentSkill (§4.4.5) + +| Field | Supported | +|---|---| +| `id` | ✅ | +| `name` | ✅ | +| `description` | ✅ | +| `tags` | ✅ | +| `examples` | ✅ | +| `inputModes` | ✅ | +| `outputModes` | ✅ | +| `securityRequirements` | ❌ | + +### AgentInterface (§4.4.6) + +| Field | Supported | +|---|---| +| `url` | ✅ | +| `protocolBinding` | ✅ | +| `tenant` | ❌ | +| `protocolVersion` | ✅ | + +### AgentCardSignature (§4.4.7) + +| Field | Supported | +|---|---| +| `protected` | ❌ | +| `signature` | ❌ | +| `header` | ❌ | + +## How A2A on LiteLLM works + +When you register an A2A agent in LiteLLM: + +1. You provide a base URL (and, for some providers, an assistant identifier). +2. LiteLLM fetches the upstream agent card from the agent's `/.well-known/agent-card.json` (or the provider-specific equivalent). +3. You review the parsed card in the LiteLLM UI and choose which skills and fields to expose. +4. LiteLLM saves the curated card and serves it at: + + ``` + GET /a2a/{agent_id}/.well-known/agent.json + ``` + +5. Clients invoke the agent at: + + ``` + POST /a2a/{agent_id} + ``` + + using standard A2A JSON-RPC (`message/send`, `message/stream`). + +## Supported A2A methods + +| Method | Supported | +|---|---| +| `message/send` | ✅ | +| `message/stream` | ✅ | +| `tasks/get` | ❌ | +| `tasks/cancel` | ❌ | +| `tasks/list` | ❌ | +| `tasks/resubscribe` | ❌ | +| `tasks/pushNotificationConfig/set` | ❌ | +| `tasks/pushNotificationConfig/get` | ❌ | +| `tasks/pushNotificationConfig/list` | ❌ | +| `tasks/pushNotificationConfig/delete` | ❌ | +| `agent/getAuthenticatedExtendedCard` | ❌ | + +--- + +## Skill routing + +Clients invoke a specific skill by including `skillId` in the message metadata: + +```json +{ + "jsonrpc": "2.0", + "id": "req-1", + "method": "message/send", + "params": { + "message": { + "messageId": "msg-001", + "role": "user", + "parts": [{"kind": "text", "text": "..."}], + "metadata": {"skillId": "triage_ticket"} + } + } +} +``` + +LiteLLM forwards the entire message envelope, including metadata, to the upstream agent unchanged. The upstream agent is responsible for reading `skillId` and routing internally. + +## Editing the agent card + +You can edit supported fields from the agent detail page in the LiteLLM UI. Use the **Re-sync from upstream** button to pick up new skills or capabilities the upstream agent has added since registration; it shows a diff and lets you accept changes selectively. + +## Related documentation + +- [Register a LangGraph Platform agent](./providers/langgraph#register-a-langgraph-platform-agent) +- [A2A Protocol Specification (v1.0)](https://a2a-protocol.org/latest/specification/) \ No newline at end of file diff --git a/docs/providers/langgraph.md b/docs/providers/langgraph.md index eea8459c..636a3cfd 100644 --- a/docs/providers/langgraph.md +++ b/docs/providers/langgraph.md @@ -235,7 +235,7 @@ curl -s --request POST \ ## LiteLLM A2A Gateway -You can also connect to LangGraph agents through LiteLLM's A2A (Agent-to-Agent) Gateway UI. This provides a visual way to register and test agents without writing code. +You can register LangGraph agents in LiteLLM's [A2A (Agent-to-Agent) Gateway](../a2a.md), discover their upstream agent card, curate skills and capabilities, and invoke them through the LiteLLM proxy. ### 1. Navigate to Agents @@ -264,34 +264,95 @@ Fill in the following fields: ![Enter API Base](https://ajeuwbhvhr.cloudimg.io/https://colony-recorder.s3.amazonaws.com/files/2025-12-13/6a6a03a7-f235-41db-b4ba-d32ced330f25/ascreenshot.jpeg?tl_px=0,251&br_px=2617,1714&force_format=jpeg&q=100&width=1120.0) -Click "Create Agent" to save. +### 4: Discover the agent card -![Create Agent](https://ajeuwbhvhr.cloudimg.io/https://colony-recorder.s3.amazonaws.com/files/2025-12-13/ddee4295-9a32-4cda-8e3f-543e5047eb6a/ascreenshot.jpeg?tl_px=416,653&br_px=2618,1883&force_format=jpeg&q=100&width=1120.0&wat=1&wat_opacity=0.7&wat_gravity=northwest&wat_url=https://colony-recorder.s3.us-west-1.amazonaws.com/images/watermarks/FB923C_standard.png&wat_pad=686,316) +Discovery runs automatically once the base URL and assistant ID are filled in. You can also trigger it manually from the discovery panel. -### 4. Test in Playground +The preview is a form. You can: +- **Edit** the name, description, provider, icon URL, and documentation URL. +- **Add, remove, or reorder skills**, and edit each skill's name, description, tags, examples, and input/output modes. +- **Toggle capabilities** that LiteLLM supports. + +Select or deselect skills and capabilities before saving. LiteLLM only persists what you keep in the form. + +Fields LiteLLM does not proxy are not shown. For the full support matrix, see [Agent card support](../a2a_agent_card.md#agent-card-support). + +![Agent Card Fields on UI](../../img/providers/langgraph/agent-card-fields-on-ui.png) + +### 5: Save the agent + +Click on Next to save. And complete the rest of the steps + +![Click on Next](../../img/providers/langgraph/click-on-next.png) + +### 6: Verify the served card + +From your terminal, fetch the agent card LiteLLM is serving: + +```bash +curl -H "Authorization: Bearer sk-1234" \ + http://localhost:4000/a2a/{agent_id}/.well-known/agent.json | jq +``` + +You should see the card you saved, with: + +- `supportedInterfaces[0].url` pointing at LiteLLM, not the upstream +- `securitySchemes` showing `LiteLLMKey` (HTTP bearer) +- The skills you kept during registration + +### 7. Test in Playground Go to "Playground" in the sidebar to test your agent. Change the endpoint type to `/v1/a2a/message/send`. ![Go to Playground](https://ajeuwbhvhr.cloudimg.io/https://colony-recorder.s3.amazonaws.com/files/2025-12-13/c4262189-95ac-4fbc-b5af-8aba8126e4f7/ascreenshot.jpeg?tl_px=0,0&br_px=2201,1230&force_format=jpeg&q=100&width=1120.0&wat=1&wat_opacity=0.7&wat_gravity=northwest&wat_url=https://colony-recorder.s3.us-west-1.amazonaws.com/images/watermarks/FB923C_standard.png&wat_pad=41,104) ![Select A2A Endpoint](https://ajeuwbhvhr.cloudimg.io/https://colony-recorder.s3.amazonaws.com/files/2025-12-13/6cbc8e93-7d0c-47fc-9ad4-562663f759d5/ascreenshot.jpeg?tl_px=0,0&br_px=2201,1230&force_format=jpeg&q=100&width=1120.0&wat=1&wat_opacity=0.7&wat_gravity=northwest&wat_url=https://colony-recorder.s3.us-west-1.amazonaws.com/images/watermarks/FB923C_standard.png&wat_pad=324,265) -### 5. Select Your Agent and Send a Message - +### 8. Select Your Agent and Send a Message Pick your LangGraph agent from the dropdown and send a test message. ![Select Agent](https://ajeuwbhvhr.cloudimg.io/https://colony-recorder.s3.amazonaws.com/files/2025-12-13/d01da2f1-3b89-47d7-ba95-de2dd8efbc1e/ascreenshot.jpeg?tl_px=0,92&br_px=2201,1323&force_format=jpeg&q=100&width=1120.0&wat=1&wat_opacity=0.7&wat_gravity=northwest&wat_url=https://colony-recorder.s3.us-west-1.amazonaws.com/images/watermarks/FB923C_standard.png&wat_pad=348,277) ![Send Message](https://ajeuwbhvhr.cloudimg.io/https://colony-recorder.s3.amazonaws.com/files/2025-12-13/79db724e-a99e-493a-9747-dc91cb398370/ascreenshot.jpeg?tl_px=51,653&br_px=2252,1883&force_format=jpeg&q=100&width=1120.0&wat=1&wat_opacity=0.7&wat_gravity=northwest&wat_url=https://colony-recorder.s3.us-west-1.amazonaws.com/images/watermarks/FB923C_standard.png&wat_pad=524,444) -The agent responds with its capabilities. You can now interact with your LangGraph agent through the A2A protocol. - ![Agent Response](https://ajeuwbhvhr.cloudimg.io/https://colony-recorder.s3.amazonaws.com/files/2025-12-13/82aa546a-0eb5-4836-b986-9aefcfe09e10/ascreenshot.jpeg?tl_px=295,28&br_px=2496,1259&force_format=jpeg&q=100&width=1120.0&wat=1&wat_opacity=0.7&wat_gravity=northwest&wat_url=https://colony-recorder.s3.us-west-1.amazonaws.com/images/watermarks/FB923C_standard.png&wat_pad=524,277) +### 9: Invoke the agent manually + +Send an A2A `message/send` request to the LiteLLM proxy URL: + +```bash +curl -X POST http://localhost:4000/a2a/{agent_id} \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d '{ + "jsonrpc": "2.0", + "id": "req-1", + "method": "message/send", + "params": { + "message": { + "messageId": "msg-001", + "role": "user", + "parts": [{"kind": "text", "text": "My order is urgent and still not delivered"}], + "metadata": {"skillId": "triage_ticket"} + } + } + }' +``` + +For streaming, use `message/stream` and add `-N -H "Accept: text/event-stream"` to the curl. + +See also [Invoking A2A Agents](../a2a_invoking_agents.md) for SDK examples. + + ## Further Reading - [LangGraph Platform Documentation](https://langchain-ai.github.io/langgraph/cloud/quick_start/) +- [LangGraph A2A endpoint docs](https://docs.langchain.com/langsmith/server-a2a) - [LangGraph GitHub](https://github.com/langchain-ai/langgraph) - [A2A Agent Gateway](../a2a.md) +- [A2A Agent Card on LiteLLM](../a2a_agent_card.md) - [A2A Cost Tracking](../a2a_cost_tracking.md) +- [A2A Protocol Specification](https://a2a-protocol.org/latest/specification/) diff --git a/img/providers/langgraph/agent-card-fields-on-ui.png b/img/providers/langgraph/agent-card-fields-on-ui.png new file mode 100644 index 00000000..06db8ed1 Binary files /dev/null and b/img/providers/langgraph/agent-card-fields-on-ui.png differ diff --git a/img/providers/langgraph/click-on-next.png b/img/providers/langgraph/click-on-next.png new file mode 100644 index 00000000..adde0923 Binary files /dev/null and b/img/providers/langgraph/click-on-next.png differ diff --git a/sidebars.js b/sidebars.js index 4bf0c9e5..9f682813 100644 --- a/sidebars.js +++ b/sidebars.js @@ -316,6 +316,7 @@ const sidebars = { label: "A2A Agent Gateway", items: [ "a2a", + "a2a_agent_card", "a2a_invoking_agents", "a2a_agent_headers", "a2a_cost_tracking",