--- title: 'Conversing with an agent' description: 'The three wire formats an agent speaks directly: OpenAI Chat Completions, Anthropic Messages and AG-UI.' position: 2 --- # Conversing with an agent > An agent speaks three standard wire formats directly, so any client built for > [OpenAI Chat Completions](https://platform.openai.com/docs/api-reference/chat), > [Anthropic Messages](https://docs.anthropic.com/en/api/messages), or > [AG-UI](https://docs.ag-ui.com) works against it with nothing but a base URL > and a key: LibreChat, Open WebUI, the Vercel AI SDK, LangChain, the AG-UI > `HttpAgent` client, or a plain `curl`. Pick the agent with the `model` field, > or with its name in the URL for AG-UI. There is no proprietary session > protocol to learn. A workspace can hold many agents. For OpenAI and Anthropic, the request's `model` names the one that should answer, and `GET /models` lists the agent names so a client can populate a dropdown (chat itself never routes through `/models`, only through the POST endpoints below). AG-UI carries no `model` field: you pick the agent by putting its name in the URL, `POST /agui/v1/agents/:name`. The OpenAI and Anthropic wires are **stateless** by default: you send the full `messages[]` array on every call, the same as calling OpenAI or Anthropic directly. There is no session id or continuation token to carry forward unless you opt in with a header (see [Session keys](/docs/cli/protocol/auth#session-keys)). AG-UI works the other way around: its `threadId` **is** a durable session key, always on, so you send only the newest turn once a thread exists. See [AG-UI](#ag-ui) below. ### OpenAI Chat Completions ```http POST /openai/v1/chat/completions Authorization: Bearer Content-Type: application/json { "model": "support", "messages": [{ "role": "user", "content": "What plans do you offer?" }], "stream": false } ``` ```jsonc { "id": "chatcmpl-…", "object": "chat.completion", "created": 1735689600, "model": "support", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "We offer Free, Pro and Team plans." }, "finish_reason": "stop", }, ], "usage": { "prompt_tokens": 42, "completion_tokens": 9, "total_tokens": 51 }, } ``` Set `"stream": true` to get `chat.completion.chunk` server-sent events instead, ending with `data: [DONE]`, the same as the OpenAI API. A turn that calls a tool sets `finish_reason: "tool_calls"` and lists the calls under `choices[0].message.tool_calls`. ### Anthropic Messages ```http POST /anthropic/v1/messages x-api-key: Content-Type: application/json { "model": "support", "max_tokens": 1024, "messages": [{ "role": "user", "content": "What plans do you offer?" }] } ``` ```jsonc { "id": "msg_…", "type": "message", "role": "assistant", "model": "support", "content": [{ "type": "text", "text": "We offer Free, Pro and Team plans." }], "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 42, "output_tokens": 9, "cache_read_input_tokens": 0, "cache_creation_input_tokens": 0, }, } ``` This is the richer of the two wires: it carries first-class `thinking` blocks (the agent's reasoning, when the model produces any) and `tool_use` blocks with structured input. Its `usage` reports cache reads and writes alongside input/output tokens, on the response above and on the streaming `message_delta`. `input_tokens` excludes the cached counts, so the three numbers add up instead of double-counting. Set `"stream": true` for the same `message_start` / `content_block_*` / `message_delta` / `message_stop` events Anthropic's own API emits. ### AG-UI ```http POST /agui/v1/agents/support Authorization: Bearer Content-Type: application/json { "threadId": "thread-1", "runId": "run-1", "messages": [{ "id": "msg-1", "role": "user", "content": "What plans do you offer?" }], "tools": [], "context": [], "state": null } ``` The response is always a Server-Sent-Events stream, even for a one-line reply: AG-UI has no non-streaming mode. Each frame is one [AG-UI event](https://docs.ag-ui.com), encoded with the protocol's own event encoder: ``` data: {"type":"RUN_STARTED","threadId":"thread-1","runId":"run-1"} data: {"type":"TEXT_MESSAGE_START","messageId":"msg_1","role":"assistant"} data: {"type":"TEXT_MESSAGE_CONTENT","messageId":"msg_1","delta":"We offer Free, Pro and Team plans."} data: {"type":"TEXT_MESSAGE_END","messageId":"msg_1"} data: {"type":"CUSTOM","name":"usage","value":{"inputTokens":42,"outputTokens":9,"cacheReadTokens":0,"cacheWriteTokens":0}} data: {"type":"RUN_FINISHED","threadId":"thread-1","runId":"run-1","outcome":{"type":"success"}} ``` `threadId` and `runId` are both required: you mint them, the agent echoes them back verbatim. There is no `model` field. You choose the agent with the `:name` in the URL, so `GET /models` has no AG-UI equivalent either. Every reasoning block the model produces streams as its own `REASONING_START` / `REASONING_MESSAGE_*` / `REASONING_END` pair, and every tool call as `TOOL_CALL_START` / `TOOL_CALL_ARGS` / `TOOL_CALL_END`, plus a `TOOL_CALL_RESULT` once a server-run tool returns. AG-UI is the only one of the three wires with a dedicated event for a tool's result. `tools` declares tools **your frontend** can execute (a modal, a browser API, anything that only makes sense client-side). See [Frontend-executed tools](/docs/cli/protocol/tools#frontend-executed-tools). `state` seeds the agent's shared state before the run starts. See [Shared state and generative UI](/docs/cli/protocol/tools#shared-state-and-generative-ui). Anything the protocol has no event for rides a `CUSTOM` frame, named by its `name` field. Besides `usage` above, a turn emits `browser_live_view` (the live-view URL of a browsing session, as soon as one opens) and `guardrail` (the decision a guardrail took on this turn). ### Listing agents ```http GET /openai/v1/models ``` ```jsonc { "object": "list", "data": [{ "id": "support", "object": "model", "created": 1735689600, "owned_by": "stackbone" }], } ``` `GET /anthropic/v1/models` returns the same names in Anthropic's model-list shape: `{ data: [{ type, id, display_name, created_at }], first_id, last_id, has_more }`. Both are catalogs only: a client uses them to populate a model picker, never to route a chat call.