fix: preserve 5 silently-dropped Responses API fields - #4850
Open
Shaik-Sirajuddin wants to merge 5 commits into
Open
fix: preserve 5 silently-dropped Responses API fields#4850Shaik-Sirajuddin wants to merge 5 commits into
Shaik-Sirajuddin wants to merge 5 commits into
Conversation
OpenAI's image_generation_call.result is nullable while status is in_progress/generating. Bifrost modeled it as a non-pointer string, so a null result silently became "" on decode/re-encode.
Found via a systematic audit of core/schemas/responses.go against OpenAI's OpenAPI spec (all 16 tool/item types checked), each confirmed by a live decode/re-encode trace: - MCPTool.allowed_tools: no custom Marshal/Unmarshal existed at all. The array form of allowed_tools threw a hard decode error; the filter-object form silently decoded to an empty object, dropping the tool-scoping restriction entirely. - MCPToolCall.approval_request_id: missing entirely, breaking approval-gated MCP replay (the model has no way to correlate its earlier call with a later approval response). - ResponsesResponseError: missing type/param, so the specific failing request field (e.g. "input[1].server_label") was stripped from any response-level error before reaching a client. - FileSearchTool.ranking_options.hybrid_search: missing entirely. - WebSearchPreviewTool.search_content_types: missing on the web_search_preview variant specifically (already present on the plain web_search variant).
…viders Type had no omitempty, so Replicate/Gemini responses (which construct this struct with only Code/Message set) gained a spurious "type":"" that never existed on their original error.
Scoping this out of the PR to avoid any risk to other providers' error handling, even though the omitempty fix verified safe for the current Replicate/Gemini construction sites.
Contributor
📝 WalkthroughWalkthroughThis PR updates JSON handling for several OpenAI Responses API schema types in ChangesResponses schema JSON handling
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Contributor
- ResponsesToolMCPAllowedTools with a non-nil empty ToolNames slice
(Anthropic's deny-all case) now has a direct assertion that it
marshals as "[]", not "{}" or "null".
- mcp_call with both server_label and approval_request_id present
together (the common production shape) now has a combined test,
confirming approval_request_id isn't clobbered regardless of
whether ResponsesMCPToolCall was already allocated by another
decode path. server_label itself is not asserted to round-trip
here — that's tracked separately in maximhq#4844.
akshaydeo
force-pushed
the
dev
branch
2 times, most recently
from
July 18, 2026 01:10
44564de to
493bff0
Compare
akshaydeo
force-pushed
the
dev
branch
3 times, most recently
from
August 13, 2026 09:47
244a01d to
ce1b2a6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Closes #5167
A systematic audit of
core/schemas/responses.goagainst OpenAI's OpenAPI spec (all 16 tool/item types checked, each verified with a live decode/re-encode trace) found 5 fields silently dropped, one of them via a hard decode error:ImageGenerationCall.result— non-pointerstringcoerced a nullablenull(image still generating) into"".MCPTool.allowed_tools— no custom Marshal/Unmarshal existed. The common array-of-tool-names form threw a hard decode error; the filter-object form silently decoded to{}, dropping a security-relevant tool-scoping restriction.MCPToolCall.approval_request_id— missing entirely, breaking approval-gated MCP replay.FileSearchTool.ranking_options.hybrid_search— missing entirely.WebSearchPreviewTool.search_content_types— missing on theweb_search_previewvariant (already present on plainweb_search).Cross-checked against litellm's own Responses API typing where a typed model exists (
approval_request_id,allowed_toolsboth corroborated); the other two lack litellm signal but are confirmed directly against the OpenAI spec.How
Added each missing field/struct, matching its real nullability.
approval_request_idneeded manual shadowing inResponsesMessage'sUnmarshalJSON/MarshalJSON, since it sits two levels behind anonymous pointer embedding that Go's decoder won't auto-promote through — same root cause asserver_labelin #4844.allowed_toolsgot a dedicated Marshal/Unmarshal pair, mirroring the existing pattern used forResponsesToolMCPAllowedToolsApprovalSetting.Verified against Anthropic, the only other provider constructing these structs directly (via Go literals rather than JSON decode): no regressions, and the
allowed_toolsfix incidentally also fixed a second latent bug where Anthropic's empty "deny all" allowlist was marshaling to{}instead of[].Testing
core/schemas/responses_test.go, each covering decode + re-encode.go build ./...andgo test ./core/schemas/...pass, aside from one pre-existing unrelated failure (TestResponsesMessageToolCallArguments/real_tool_search_call_frames_from_openai), confirmed to fail identically on a cleandevcheckout.