nemo_gym.anthropic_converter
nemo_gym.anthropic_converter
Bidirectional converter between NeMo Gym Responses API objects and Anthropic Messages.
This module is the single source of truth for the Anthropic <-> Responses mapping. It is shared by two opposite-direction consumers:
- Egress (
responses_api_models/anthropic_model): NeMo Gym is the client and Anthropic is the backend. Usesresponses_to_anthropic(request) andanthropic_to_responses(response). - Ingress (an Anthropic-Messages proxy, e.g. for the Claude Code CLI): an Anthropic client
talks to NeMo Gym, which forwards to a downstream Gym model server. Uses
anthropic_request_to_responses(request),responses_to_anthropic_response(response), andanthropic_response_to_sse(synthesize Anthropic SSE from a complete response).
The converter is transport-free and SDK-free: pure dict/Pydantic in, pure dict/Pydantic
out. All HTTP stays in the servers via nemo_gym.server_utils.request() (the anthropic
SDK is avoided because it uses httpx, whose O(n^2) connection pooling hangs at high
concurrency).
Boundary note: a few methods here implement egress-only policy (Anthropic-API-as-backend
concerns) rather than structural mapping: _validate_sampling_params_for_model,
_model_disallows_sampling_params, and the thinking-config handling in
_copy_thinking_params. They are invoked only on the egress responses_to_anthropic path;
ingress never calls them (an open-model backend has none of those restrictions). Relocating
them into the egress server is a deliberate follow-up, kept out of this refactor to avoid
changing the egress contract.
Module Contents
Classes
Data
SUPPORTED_ANTHROPIC_IMAGE_MEDIA_TYPES
API
Anthropic assistant content blocks -> ordered Responses output items.
Shared by egress anthropic_to_responses and ingress anthropic_request_to_responses
(for assistant turns in the input trajectory).
Translate one Anthropic message’s content blocks into ordered Responses items.
Text/image blocks group into a single message item; tool_use, tool_result, and thinking blocks each become their own item, preserving order.
Inverse of responses_to_anthropic (the request direction).
Parses an inbound Anthropic Messages request into Responses create params so it can be
forwarded to a downstream Gym model server’s /v1/responses.
anthropic_body is hinted with the Anthropic SDK’s native MessageCreateParams
(a TypedDict union, so it accepts stream: true). It’s a type hint only — at runtime
the value is the raw request dict; we read fields defensively so the proxy stays
permissive toward unknown / future-beta fields the Claude Code CLI may send.
Synthesize an Anthropic Messages SSE stream from a complete response object.
The downstream call is non-streaming; this fakes the event sequence the Claude Code CLI
expects: message_start -> per-block (content_block_start ->
content_block_delta -> content_block_stop) -> message_delta -> message_stop.
Inverse of anthropic_to_responses (the response direction).
Renders a downstream /v1/responses result as a complete Anthropic Messages response
object (non-streaming shape). Token-id / logprob fields are intentionally dropped here;
they are carried out-of-band by the ingress server’s side channel.
The assembled object is validated by constructing NeMoGymAnthropicMessage (a thin
subclass of the Anthropic SDK’s Message) — catching malformed blocks / bad
stop_reason / missing fields at the boundary — then
returned as a JSON dict for the SSE synthesizer and the non-streaming JSON response.
exclude_none keeps the lean Anthropic shape (drops null SDK-only fields).