Prompt trimming orphans tool messages, so every trimmed request is rejected 400 by the backend #113
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agent-proxy#113
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Trace
1a49200c3bebaed778ef2ac5b79d3d99, 2026-08-13T17:05:52Z (SigNoz:http://ser8:30808/trace/1a49200c3bebaed778ef2ac5b79d3d99).A
sirens-deepDiscord turn ran 97.15s across 6 model rounds and delivered nothing — the progress message was deleted and no reply posted (discord.turn.failed,"discord_failure":"no_response").The trim is the failure
Rounds 0–4 all returned 200. Round 5 is the only request agent-proxy trimmed, and it is the only one that failed.
Round 5 carried
message_count=23— round 4's 17, plus one assistant turn and fivesteam__get_store_app_detailstool results. The trimmer dropped exactly 5 messages. DeepSeek then rejected the payload (litellm pod, 17:07:10.964):This is a structural violation of the OpenAI message contract, not a capacity or availability problem. The trimmer selects messages to drop by token budget alone, without preserving the
assistant(tool_calls)↔toolpairing that the dialect requires.Round-by-round evidence
request_bytesmessage_countThe context grows monotonically with tool results across the turn, so the first request to cross
budget_tokens=47104is the first to be trimmed and the first to die. A tool-heavy turn reaches that boundary reliably.Recurrence: 7 days, 11 trims, and the ratio does not move
request.prompt_trimmedeventsmust be a response to a preceding messageExactly 24 log lines per trim event on all three days. I counted lines, not distinct failures, so treat this as strong correlation rather than proven identity — but the ratio is invariant across three days at three different volumes, and I found no instance of this 400 on a day with no trim.
Read: every trim fails. The feature has, so far as telemetry shows, never once produced a request the backend accepted.
What I am not claiming
I have not read the trimming code —
docs/proxy-num-ctx.mdexists in this repo but is not in my checkout, and I have no live access here. The mechanism (drop-by-token-budget without group awareness) is inferred from the message arithmetic and the backend's error text, not read from source.What would change my read: a
request.prompt_trimmedevent that did not produce this 400. That would mean the trimmer is only sometimes wrong and something else selects the bad case.Acceptance
assistant(tool_calls)+ correspondingtoolmessage groups atomically, never a partial group.budget_tokenson a tool-heavy round completes rather than 400s.Related
sirens-echoturn dies; unrelated cause, same user-visible outcome.Pulled all 11
request.prompt_trimmedevents over 7d. Three corrections and additions to the issue above.Correction: the dates in my recurrence table are wrong
The day buckets were off by one. Actual event dates:
request.prompt_trimmedeventsThere were no trim events on 2026-08-12. The 24:1 ratio holds per day and the conclusion is unchanged, but query the correct dates.
The trimmer does not converge — 7 of 11 trims left the prompt over budget
Every event,
budget_tokens=47104throughout:Dropping 3 messages yields anywhere from −879 to −50,970 tokens. The trimmer removes a small number of messages, logs success, and returns — without checking whether it reached
budget_tokens. It is not a loop with a termination condition on the budget.So there are two independent defects in the same function: it breaks tool pairing (this issue), and it does not achieve the thing it exists to achieve.
The budget itself is the deeper problem — filed separately
target_num_ctx=48128is invariant across all 11 events and every logical model.num_ctxis an Ollama parameter; per DeepSeek's published pricing,deepseek-v4-flashhas a 1M context window and 384K max output. Filed as its own issue.That reframes this trace specifically: at
original_token_count=48226, the request fit the model's window with roughly 95% to spare and should never have been trimmed at all. The trim was unnecessary, and it is what broke the request.The 08-10 rows are the confirming evidence. Those prompts went upstream at 82K–171K tokens after trimming and came back with the tool-pairing error, not a context-length error. DeepSeek parsed a 171,203-token payload far enough to validate message structure.
budget_tokens=47104is not the provider's limit and never was.num_ctxis a local-inference parameter applied to a hosted route #115