Skip to main content
The /v1/messages endpoint is Anthropic-native. Claude Code, the Anthropic Python/TypeScript SDK, and any agent built against Anthropic’s Messages API works unchanged by pointing at the gateway. Beyond plain pass-through, the gateway preserves tool-call streaming deltas byte-for-byte (load-bearing for agentic CLIs) and forwards cache_control blocks identically (load-bearing for the 90% Anthropic cache discount).

Request

Body matches Anthropic’s Messages API verbatim. Example:
Anthropic requires max_tokens, omitting it returns a 400 from upstream which the gateway surfaces.

Cache-aware system prompts

cache_control blocks are forwarded byte-identically to upstream Anthropic by default (see Caching Passthrough).

LangWatch-specific headers

Same as POST /v1/chat/completions:
  • X-LangWatch-Cache: respect|force|disable|ttl=<s>
  • X-LangWatch-Trace-Metadata: {...}
  • Trace-context headers (traceparent, X-LangWatch-Trace-Id, etc.), see SDKs → trace propagation.

Response (non-streaming)

Anthropic-shaped. Response headers:
The cache_read_input_tokens and cache_creation_input_tokens are forwarded as-is; they also flow into the debit call so budget ledgers reflect the correct cache-discounted cost.

Response (streaming)

Set "stream": true. SSE events:
The gateway forwards these byte-for-byte after the first chunk, including content_block_start, content_block_delta, content_block_stop events for tool use. See Streaming for the full contract.

Tool use

Subject to VK policy_rules.tools, a blocked tool name returns 403 tool_not_allowed before the request leaves the gateway. See Policy Rules.

Extended thinking (Claude Opus 4.7, Sonnet 4.6)

Thinking tokens are billed separately by Anthropic. The gateway forwards the thinking field unchanged; usage counts appear in response.usage.thinking_tokens, roll into langwatch.usage.output_tokens on the trace, and debit the budget. (A dedicated langwatch.reasoning_tokens span attribute that separates thinking from non-thinking output tokens is a v1.1 observability follow-up.)

Routing via model field

model is resolved via the VK’s model_aliases map (see Model Aliases):
  • "claude-haiku-4-5-20251001" → VK maps to anthropic/claude-haiku-4-5-20251001 (or bedrock/..., vertex/... if the alias points there).
  • "claude" → whatever the VK defines as “default Claude”.
  • "anthropic/claude-opus-4-7" → explicit form, bypasses aliases.
If the resolved model isn’t served by any provider in the VK, returns 403 model_not_allowed.

Errors

See API: Errors: the full type enum applies. Errors use the OpenAI-compatible envelope (not Anthropic’s native {type: "error", error: {...}}) for consistency across /v1/messages and /v1/chat/completions. This is a small deviation from stock Anthropic, the tradeoff is a single error-handling code path for clients that hit both endpoints.

Example: Claude Code CLI

Claude Code uses /v1/messages natively. Setup is:
See Claude Code for governance recipes (blocking shell tools, per-engineer budgets, fallback to Bedrock).