Repository navigation
[Compatibility] Camel DeepSeek V4 Flash misses structured tool call on the first tool round #1730
Description
Client or integration
Codex App
Provider or upstream service
Camel Stream (stream.camelai.com), model deepseek-v4-flash
Endpoint or capability
Custom-provider /v1/responses model routing and first-tool-round tool-selection behavior.
The provider-wide adapter remains openai-chat, while only deepseek-v4-flash is routed through openai-responses.
Remaining problem
This issue now tracks only whether Camel deepseek-v4-flash emits code-mode-style text/markup instead of a structured tool call on the first tool round when tool_choice: "auto" is used.
The second problem from the original report, loss of the unified exec custom-to-function input description, was fixed in #1763 and merged into dev. The exec JavaScript input contract is therefore no longer part of this issue's implementation scope.
Expected behavior
- On the first tool round for
stream.camelai.com+deepseek-v4-flash, the model should produce a structured tool call when it chooses to use a tool declared in the request. - Requests using an explicit
tool_choicemust preserve their current semantics. - Continuation turns containing tool results must preserve their current semantics.
- Other hosts, models, and providers must remain unaffected.
Evidence required before implementation
The following evidence is required against current dev:
- A redacted raw upstream response from the first tool round showing the actual text/markup shape returned instead of a structured tool call.
- Confirmation that
tool_choice: "auto"was used with the same request/tool catalog. - The result of a control request using an explicit tool choice.
- Control evidence showing that a continuation turn after tool output still behaves normally.
Without this evidence, we should not add a host/model hardcode that forces first-round tool_choice: "required" only for stream.camelai.com + deepseek-v4-flash. There is no public upstream contract for that behavior, so a provider-specific policy change requires reproducible current evidence.
Minimal redacted reproduction
{
"adapter": "openai-chat",
"baseUrl": "https://stream.camelai.com/v1",
"defaultModel": "deepseek-v4-flash",
"modelAdapters": {
"deepseek-v4-flash": "openai-responses"
},
"responsesPath": null
}- On current
dev, send a first request that includes tools. - Record the upstream request's
tool_choiceand tool catalog. - Capture the raw upstream response in redacted form.
- Run an explicit-tool-choice control under the same conditions.
- Run a continuation control that includes tool output.
Already fixed / out of scope
- Unified
execcustom-to-function JavaScript input guidance: fixed by fix(responses): preserve unified exec input contract #1763 and merged intodev. - Do not reimplement the bare-shell
execinput problem in this issue. - General custom-tool conversion changes are out of scope unless new evidence shows a separate regression.
Related
- fix(responses): preserve unified exec input contract #1763: merged shared
execinput-contract repair. - [Bug] DeepSeek V4 Flash Responses route stalls after tool calls #875, DeepSeek V4 Flash Responses tool calls stall in Codex App after upgrade from 2.8.0 to 2.10.0 #946: related compatibility context.
Checks
- I searched existing provider and compatibility issues.
- The request and response must be redacted.
- Current-
devraw first-response evidence for the remaining Camel-specific behavior is still required.
Activity
coderabbitai commentedon Aug 15, 2026
🔗 Related PRs
#1361 - fix(responses): restore DeepSeek streaming and routed code-mode tools [merged]
#1479 - fix(deepseek): preserve parallel reasoning replay [open]
#1499 - fix(deepseek): keep parallel reasoning replay on continuation [open]
#1531 - fix(openai-chat): refuse to emit an unnamed streamed tool call [merged]
#1763 - fix(responses): preserve unified exec input contract [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
github-actions commentedon Aug 15, 2026
Maintainer decision respected
A maintainer has reopened this issue. The automated closure has been deactivated.
Ingwannu commentedon Aug 15, 2026
Confirmed one real general compatibility defect, but not enough evidence to adopt the proposed host/model hardcode as-is.
The confirmed defect is the custom-to-function conversion for
exec: currentdevreplaces the original freeform contract with the generic descriptionRaw input for this client-executed custom tool.That loses the fact that the input is JavaScript evaluated by unified exec, with shell commands invoked throughtools.exec_command(...)and output returned throughtext(...). A model can therefore reasonably emit a bare shell command that the JavaScript evaluator rejects. This should be fixed at the sharedexecconversion boundary with focused regressions.The separate proposal to force
tool_choice: requiredonly forstream.camelai.com+deepseek-v4-flashon the first tool round is not ready to land yet. There is no public upstream contract for that behavior, and a hostname/model special case changes tool-selection semantics for every user of that route. Before adopting it, we need a redacted raw first-response capture showing the malformed text/markup shape on currentdev, plus confirmation that a normal explicit tool choice and continuation turn remain unchanged.I will treat the shared
execinput-contract repair independently so that confirmed behavior does not wait on the provider-specific policy decision.Ingwannu commentedon Aug 15, 2026
The confirmed shared
execconversion defect is implemented in #1763.The patch restores the JavaScript contract only for the converted unified
exectool, including the requiredtools.exec_command(...)andtext(...)usage, while leaving all other custom-tool descriptions unchanged.Validation on current
dev:This PR intentionally does not implement the proposed Camel-specific first-turn
tool_choice: requiredoverride. The issue should remain open for that separate provider-specific reproduction unless the shared contract repair alone resolves it.fix(responses): preserve unified exec input contract (#1763)
lidge-jun commentedon Aug 15, 2026
The shared half of this is now on
devas ea06086 (squash of #1763).Routed custom tools are rewritten into function tools for upstreams that do not speak the custom-tool shape, and that rewrite described every tool's input as "Raw input for this client-executed custom tool" — which told a routed model that unified exec takes a bare shell command. Codex then executed the returned string as JavaScript.
execnow carries its real contract in the converted schema, and every other custom tool keeps the generic description.Verified on the remote validation host: 89 pass / 0 fail across
tests/custom-tool-compat.test.ts,tests/openai-responses-passthrough.test.ts,tests/responses-custom-tool-repair.test.ts.Keeping this open. That fix teaches a model that already chose
exechow to format its input; it does not address the reported first-turn behavior where Cameldeepseek-v4-flashemits code-mode text instead of a structured tool call whiletool_choiceis"auto". That part needs raw-response evidence against currentdevbefore we decide whether a provider-specific first-turn policy is warranted.[-][호환성] Camel DeepSeek V4 Flash에서 초기 도구 호출과 unified exec 입력이 깨짐[/-][+][호환성] Camel DeepSeek V4 Flash 첫 도구 라운드에서 structured tool call이 누락됨[/+][-][호환성] Camel DeepSeek V4 Flash 첫 도구 라운드에서 structured tool call이 누락됨[/-][+][Compatibility] Camel DeepSeek V4 Flash misses structured tool call on the first tool round[/+]docs(devlog): adopt close-on-dev-merge for this run only
lidge-jun commentedon Aug 18, 2026
Status after the shared-half fix: the
execconversion defect landed ondevas ea06086 (#1763) — converted unifiedexecnow carries its real JavaScript contract instead of the raw-input description that was teaching routed models to return bare shell strings. That mitigation is generic and applies to Camel too, but it addresses the malformed tool call shape, not this issue's remaining half: Camel DeepSeek V4 Flash still skipping the structured tool call entirely on the first tool round. The proposed Camel-specific first-turntool_choice: requiredoverride was intentionally not implemented in #1763. So this stays open, scoped to exactly that: verify on currentdevwhether the first-round miss still reproduces with the corrected schema, and if it does, implement the provider-scoped first-turntool_choicenudge (or an equivalent Camel-specific mitigation) with the raw request/response capture as the regression fixture.idguyst commentedon Aug 18, 2026
Thank you for keeping this open while waiting for better evidence. I’m sorry for the confusion caused by my earlier conclusions.
After further investigation, I found that my OpenCodex configuration was routing
deepseek-v4-flashthrough a model-specificopenai-responsesoverride. That was not the correct Camel integration path. Camel recommends Chat Completions for agentic coding, and its supported reasoning control there isreasoning_effort.I corrected the configuration to use:
{ "adapter": "openai-chat", "baseUrl": "https://stream.camelai.com/v1", "model": "deepseek-v4-flash", "modelReasoningEfforts": { "deepseek-v4-flash": ["high"] }, "preserveReasoningContentModels": ["deepseek-v4-flash"] }There is now no
modelAdapters.deepseek-v4-flash = "openai-responses"override and no gateway-stylereasoningobject. The actual upstream request usesreasoning_effort: "high".Camel also fixed a server-side reasoning parser issue that had previously mixed reasoning into normal content. With the corrected Chat Completions route, I repeated the tests:
tool_callsdelta.camel/deepseek-v4-flash; there was no provider failover.I could no longer reproduce the remaining first-round behavior described in this issue. I also agree that my earlier 774-second figure represented accumulated time across multiple agent turns and retries, rather than one upstream TTFT.
Based on the corrected configuration and current results, I no longer think a Camel-specific first-turn
tool_choice: "required"override is warranted. Please feel free to close the remaining Camel-specific part of this issue.The shared unified-
execcontract fix in #1763 was still valid and useful independently. Thank you for separating that confirmed defect from the provider-specific hypothesis instead of implementing the proposed hardcode without sufficient evidence.lidge-jun commentedon Aug 19, 2026
리뷰 · 우선순위 22 / 80
Camel Stream의
deepseek-v4-flash가 첫 도구 라운드에서tool_choice: "auto"일 때 구조화 tool call 대신 코드 모드 텍스트/마크업을 내는지만 남은 호환 이슈입니다.exec입력 설명 손실은 #1763으로dev에 들어갔고, 이 이슈 범위가 아닙니다.needs-info가 붙어 있습니다.현재
dev에는stream.camelai.com전용 하드코드가 없습니다. 프로바이더 전체 어댑터는openai-chat이고, 해당 모델만modelAdapters로openai-responses를 타는 구성은 이슈 재현 JSON과 같습니다.src/adapters/openai-chat.ts에autoToolChoiceOnlyModels가 있고, Responses 쪽tool_choice정규화는src/adapters/openai-responses.ts에 있습니다. Camel 첫 라운드만required로 올리는 정책은 코드에 없습니다.이슈가 요구하는 현재
dev근거는 아직입니다. 첫 라운드 원문(편집된) 응답, 같은 카탈로그에서tool_choice: "auto"였는지, 명시적 tool choice 대조, 도구 결과 이후 연속 턴 대조가 필요합니다. 이 없이 호스트/모델 하드코드를 넣으면 다른 프로바이더의auto의미를 바꿀 수 있습니다.해결방안: 위 네 가지 근거가 오기 전에는 구현하지 않는 편이 맞습니다. 근거가 재현되면 그때만 Camel +
deepseek-v4-flash첫 라운드에 한정된 정책을 검토하고, 명시적tool_choice와 연속 턴, 다른 호스트는 그대로 두어야 합니다. 지금은 패치는 추측하지 않음.이 댓글은 grok-bot이 작성했습니다
lidge-jun commentedon Aug 19, 2026
Closing as not planned, per the reporter's own follow-up.
Where this landed
The report contained two problems, and separating them turned out to matter.
The half that was ours shipped. Converting custom tools into function tools overwrote every tool's input description with
"Raw input for this client-executed custom tool."For unifiedexecthat was actively wrong — its input is JavaScript, with shell commands invoked throughtools.exec_command(...)and output returned throughtext(...). A routed model reasonably replied with a bare shell string, which the JavaScript evaluator then rejected. Fixed in #1763, ondevasea0608611, andsrc/responses/custom-tool-compat.tsnow carries the real contract forexecwhile leaving every other custom tool's description unchanged.The half that was not ours does not reproduce. @idguyst found their configuration was routing
deepseek-v4-flashthrough a model-specificopenai-responsesoverride, while Camel recommends Chat Completions withreasoning_effortfor agentic coding. On the corrected route: 8 agent turns, all HTTP 200, no failover, structured tool calls and tool-result continuation normal, file edited and regression tests green. Camel also fixed a server-side reasoning-parser issue in that window.Why the hardcode was not added
The proposal was a first-round
tool_choice: "required"override scoped tostream.camelai.com+deepseek-v4-flash. We asked for four pieces of evidence against currentdevbefore touching it: a redacted raw first-response, confirmation thattool_choice: "auto"was in play for the same catalog, an explicit-choice control, and a continuation-turn control.That evidence never arrived because the behavior stopped happening. A hostname/model special case changes tool-selection semantics for every user of that route, and there is no public upstream contract to anchor it — so "we could not reproduce it" is the right outcome, not a missed opportunity.
Thanks for coming back with the corrected configuration and the retraction, @idguyst. Separating a confirmed defect from a provider-specific hypothesis is what made the
execfix land cleanly on its own.Reopen if the first-round miss returns on the Chat Completions route with a raw capture attached.
fix(responses): preserve unified exec input contract (lidge-jun#1763)
docs(devlog): adopt close-on-dev-merge for this run only