Skip to content

docs: design for Claude Code support via Anthropic Messages API#98

Merged
maralbahari merged 4 commits into
vllm-project:mainfrom
ashwing:docs/claude-code-messages-design
Jul 15, 2026
Merged

docs: design for Claude Code support via Anthropic Messages API#98
maralbahari merged 4 commits into
vllm-project:mainfrom
ashwing:docs/claude-code-messages-design

Conversation

@ashwing

@ashwing ashwing commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

A design proposal for supporting Claude Code as a client of agentic-api, the natural next client after Codex.

Codex works because it speaks the same Responses API agentic-api already serves. Claude Code speaks a different protocol — the Anthropic Messages API (/v1/messages) — which agentic-api does not serve yet. Supporting it means exposing a stateful Messages surface and giving it the same value-add Responses has, reusing the existing execution core rather than forking it (ROADMAP §4).

The doc's central finding, established by a live spike (see Test Plan): the gateway's value-add for Claude Code — server-side execution of gateway-owned tools like web_search/MCP — is real, but reachable only through a server-side tool loop that keeps gateway-owned tools invisible to the client. Claude Code executes every tool_use against its own local registry and errors on anything it didn't declare, so advertising a gateway tool to the client cannot work; the gateway must run the loop itself and surface only the final message. This is the same hide-the-call pattern the Responses path uses.

The doc also captures the Anthropic gateway protocol contract (error forwarding, header handling, the system-prompt attribution block — the places a naive proxy goes wrong), scopes a phased plan, and records what the spike settled vs. what remains open (the API-agnostic loop factoring, owned by the pending Layering ADR).

This is a docs-only change — one new file, docs/design/claude-code-integration.md. Opening as a draft to socialize the direction before any implementation.

Test Plan

The design's premise was verified live rather than assumed, in two rounds:

vLLM speaks Messages (vLLM-direct). Against a vLLM server, /v1/messages returns Anthropic-shaped bodies, streams the correct SSE event sequence (including thinking_delta), and does tool use. The real Claude Code CLI drives it end to end via ANTHROPIC_BASE_URL — a plain turn and a full client-owned tool round trip — with no gateway in the path. Corroborated by vLLM's own Claude Code doc.

What a gateway can do (gateway-in-path). The real @anthropic-ai/claude-code CLI (2.1.208) was pointed at a throwaway probe gateway sitting in front of vLLM 0.25.1 (Qwen/Qwen3-30B-A3B-FP8, hermes parser). Three experiments:

  1. Injecting a gateway tool alongside Claude Code's own tools — the model ignores it and stays client-side.
  2. Forcing the gateway tool to be the only option — the model calls it, and Claude Code returns No such tool available, confirming it never round-trips a tool it didn't declare.
  3. Running the loop server-side (gateway injects the tool only into its upstream call, executes it, hides it, surfaces only the final message) — a real claude -p session completed a gateway-executed tool turn with no client-side error. The executor was stubbed, so this proves the loop-and-hiding mechanics; wiring a real executor is Phase 1's first acceptance test.

Capability probe: vLLM 0.25.1 accepts every advanced field Claude Code sends (thinking, output_config, context_management, metadata) at HTTP 200, alone and combined — no field-level 400 hazard on current vLLM.

Mermaid diagram renders via mmdc; internal anchors and relative links resolve. Pre-commit excludes .md, so CI is DCO + the standard Rust build (no code touched).

Signed-off-by: Ashwin Giridharan <girida@amazon.com>
Comment thread docs/design/claude-code-integration.md Outdated

`agentic-api` today serves one stateful inference surface: the OpenAI-compatible Responses API (`/v1/responses`, with its supporting `/v1/conversations` and `/v1/models` routes), including persistence, `previous_response_id` continuation, gateway tool execution, and the multi-turn tool loop built around it. Codex works because Codex also speaks Responses; the only client-specific work was preserving Codex's `namespace` tool shape (see [Codex CLI Integration](./codex-integration.md)).

Claude Code speaks a different protocol — the Anthropic Messages API (`/v1/messages`). Supporting it is therefore not a tool-shape adaptation like Codex; it means exposing a stateful Messages surface and giving it the same value-add Responses has today. The model-facing half of that is already solved: vLLM implements Messages natively, and a live spike confirms it accepts everything Claude Code sends (see [Verification](#verification)). What remains is gateway work, and it is narrower than Responses was — a server-side tool loop that executes gateway-owned tools without exposing them to the client, reusing the existing execution core rather than forking it (ROADMAP §4).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the sentence exposing a stateful Messages surface and giving it the same value-add Responses has today implies that gateway requires maintain a stateful v1/messages endpoint with rehydration and persistence path. while anthropic messages api is entirely statesless in the document in section ##Statelessness and value-add discuss this more clearly that whether gateway wants to handle maintain history and rehydration is optional. but I think it is better to just keep it stateless since claude always sends full history to /v1/messages endpoint.
so need to be more clear and explicit that gateway does not use any storage layer means no rehydration/persistence for /v1/messages only mapping of tool calls and request/response payloads.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworked per this — agreed, the gateway shouldn't imply persistence.

The Summary now leads with statelessness and lists exactly what the gateway implements (proxy routes / protocol contract / server-side tool loop), and there's a dedicated "The gateway stays stateless" section stating plainly that it holds no conversation state: no storage, no rehydration, no persistence, no previous_response_id analog. Persistence is now an explicit non-goal, not a deferred phase. I also reframed the plan as tracker-able stages with #99 marked as the landed Stage 1.

Following up on the Slack thread: I'll open a parent tracking issue for the whole integration linked to this PR, with a sub-issue per stage.

@ashwing ashwing marked this pull request as ready for review July 14, 2026 06:36
ashwing added 2 commits July 14, 2026 09:42
…isting streaming

Signed-off-by: Ashwin Giridharan <girida@amazon.com>
Signed-off-by: Ashwin Giridharan <girida@amazon.com>
@ashwing

ashwing commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Opened the tracking issue for this: #113, with a sub-issue per stage (#114 proxy + contract, #115 server-side tool loop, #116 hardening). This PR is the design backing for that tracker.

franciscojavierarceo added a commit that referenced this pull request Jul 15, 2026
## Summary

- add transparent Anthropic Messages proxy routes for `/v1/messages` and
`/v1/messages/count_tokens`
- preserve raw request bodies, query parameters, Anthropic/Claude Code
headers, upstream statuses, JSON responses, SSE streams, and error
bodies
- keep the existing Responses proxy API compatible while adding a
path-aware internal proxy helper
- add recording-upstream integration coverage using Claude Code-style
client-owned `WebSearch`/`WebFetch` tools and arbitrary request fields
- cover the protocol-contract requirements tracked in issue #114:
verbatim block-first `system` forwarding, open-list `anthropic-beta`
forwarding, and unchanged `anthropic-version`

## Test Plan

- `cargo fmt -- --check`
- `cargo clippy --all-targets -- -D warnings`
- `cargo test -p agentic-server --test messages_test`
- `cargo test -p agentic-server`
- `git diff --check`

PR #98 provides the design and live-spike evidence for the follow-up
Phase 2 server-side tool loop: gateway tools must be injected only into
upstream vLLM requests, executed inside Agentic API, and hidden from
Claude Code. This PR intentionally remains the transparent proxy floor;
no gateway-owned web-search execution is included.

---------

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>
@maralbahari maralbahari merged commit a77be75 into vllm-project:main Jul 15, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants