Client or integration
Codex CLI and the Anthropic Python SDK through the OpenCodex Anthropic adapter.
Provider or upstream service
AgentRouter (https://agentrouter.org), using its Anthropic-compatible /v1/messages API.
OpenCodex version
2.7.42
Endpoint or capability
Anthropic-compatible streaming and tool calls via /v1/messages.
Current behaviour
Some non-Claude models exposed by this provider emit valid Anthropic-compatible SSE content but close the connection before content_block_stop, message_delta, and message_stop.
The OpenCodex Anthropic adapter treats that EOF as a fatal truncation for every provider. It discards otherwise valid visible text and completed tool-call arguments, returning an adapter error instead of completing the response.
The affected provider can also omit tool_use.id, and may return tool_use.input as a malformed concatenation such as {}{\"value\":42} in non-streaming responses.
Expected behaviour
For a deliberately configured compatibility profile for this provider, OpenCodex should be able to:
- preserve text when the upstream emits valid content and then closes without terminal SSE frames;
- complete a tool call only when the accumulated arguments form a valid JSON object;
- synthesize a stable non-empty tool-call ID when the upstream omits it;
- normalize malformed tool arguments to a valid JSON object.
The default behavior for native Anthropic and other strict providers should remain unchanged: incomplete streams must continue to fail.
Minimal redacted reproduction
import anthropic
# Instantiate the SDK with a redacted local proxy credential and this base URL.
client = anthropic.Anthropic("REDACTED", base_url="http://127.0.0.1:10100")
# The direct upstream call returns the visible text. Through OpenCodex before
# the patch, the same request fails with an adapter EOF error.
with client.messages.stream(
model="PROVIDER/glm-5.2",
max_tokens=64,
messages=[{"role": "user", "content": "Reply exactly: OK"}],
) as stream:
print("".join(stream.text_stream))
Raw redacted upstream SSE shape observed for text:
message_start
content_block_start (text)
content_block_delta (text_delta with visible text)
EOF
Raw redacted upstream SSE shape observed for a tool call:
message_start
content_block_start (tool_use; id may be present or absent)
content_block_delta (input_json_delta fragments forming a complete JSON object)
EOF
Actual response or error
upstream stream ended before message_stop — possible truncation
The direct AgentRouter request using the Anthropic Python SDK returned the expected text for glm-5.2 and gpt-5.5. Through OpenCodex before the local compatibility patch, both failed with the error above.
Upstream documentation
AgentRouter documents an Anthropic-compatible endpoint, but the observed stream does not consistently include the terminal Anthropic SSE frames.
Suggested mapping or implementation notes
A narrow compatibility fallback can be implemented in src/adapters/anthropic.ts, gated by an exact hostname match for agentrouter.org:
- On EOF without
message_stop, emit done only after valid content has been received and no incomplete tool call is open.
- If a tool call is open, emit
tool_call_end and done only when its accumulated arguments parse to a JSON object.
- Otherwise keep emitting the current truncation error.
- For this provider only, synthesize a
toolu_<uuid> ID when a tool_use ID is absent, and normalize non-streaming tool inputs to a JSON object.
I verified this behavior with focused regression tests covering: normal AgentRouter text EOF, incomplete tool JSON, complete tool JSON at EOF, missing tool IDs, malformed concatenated tool input, and native Anthropic EOF remaining an error.
Additional context
No credentials, correlation values, account information, local paths, usage logs, or raw provider payloads are included here. I searched existing compatibility issues and found related SSE-truncation reports, but no open issue specifically for AgentRouter.
Client or integration
Codex CLI and the Anthropic Python SDK through the OpenCodex Anthropic adapter.
Provider or upstream service
AgentRouter (
https://agentrouter.org), using its Anthropic-compatible/v1/messagesAPI.OpenCodex version
2.7.42Endpoint or capability
Anthropic-compatible streaming and tool calls via
/v1/messages.Current behaviour
Some non-Claude models exposed by this provider emit valid Anthropic-compatible SSE content but close the connection before
content_block_stop,message_delta, andmessage_stop.The OpenCodex Anthropic adapter treats that EOF as a fatal truncation for every provider. It discards otherwise valid visible text and completed tool-call arguments, returning an adapter error instead of completing the response.
The affected provider can also omit
tool_use.id, and may returntool_use.inputas a malformed concatenation such as{}{\"value\":42}in non-streaming responses.Expected behaviour
For a deliberately configured compatibility profile for this provider, OpenCodex should be able to:
The default behavior for native Anthropic and other strict providers should remain unchanged: incomplete streams must continue to fail.
Minimal redacted reproduction
Raw redacted upstream SSE shape observed for text:
Raw redacted upstream SSE shape observed for a tool call:
Actual response or error
The direct AgentRouter request using the Anthropic Python SDK returned the expected text for
glm-5.2andgpt-5.5. Through OpenCodex before the local compatibility patch, both failed with the error above.Upstream documentation
AgentRouter documents an Anthropic-compatible endpoint, but the observed stream does not consistently include the terminal Anthropic SSE frames.
Suggested mapping or implementation notes
A narrow compatibility fallback can be implemented in
src/adapters/anthropic.ts, gated by an exact hostname match foragentrouter.org:message_stop, emitdoneonly after valid content has been received and no incomplete tool call is open.tool_call_endanddoneonly when its accumulated arguments parse to a JSON object.toolu_<uuid>ID when atool_useID is absent, and normalize non-streaming tool inputs to a JSON object.I verified this behavior with focused regression tests covering: normal AgentRouter text EOF, incomplete tool JSON, complete tool JSON at EOF, missing tool IDs, malformed concatenated tool input, and native Anthropic EOF remaining an error.
Additional context
No credentials, correlation values, account information, local paths, usage logs, or raw provider payloads are included here. I searched existing compatibility issues and found related SSE-truncation reports, but no open issue specifically for AgentRouter.