2026-09-18 pi DeepSeek Session Diagnosis and LiteLLM Routing
What I set out to do
Work out why a pi session on deepseek/deepseek-v4-flash-0731:free never produced a code review of the media-stack feat/plex-terraform branch, check SigNoz for configuration gaps, and route pi through LiteLLM.
What I actually did
- Transcript diagnosis (session
01a0b71c): 280 assistant turns, 402 tool calls, one completed answer, 45 minutes, ended aborted. 175 calls re-ran a--statdiff; the full diff was never read front to back. Reasoning restarted from scratch nearly every turn, and 29 turns claimed tool outputs were “merged/interleaved”. Context bloated to about 660K tokens on repeated diffs. The one answer was a summary built from the diffstat, not a review. - Ruled out pi message formatting: tool results are separate
role: "tool"messages; all 402 tool-call ids unique. The upstream was a single free fp8 deployment (OpenInference) per the OpenRouter generation API. Reasoning was 26 to 83 tokens per turn at thinkinghigh. - SigNoz gap: pi had never reported (no service in 7 days). It called
openrouter.aidirectly withOPENROUTER_API_KEY, bypassing LiteLLM. - Routed pi through LiteLLM: new extension
coding-agents/pi/extensions/litellm-route.tsoverrides the built-inopenrouterprovider’sbaseUrltolocalhost:4000/v1and rewrites the payload model toopenrouter/<id>inbefore_provider_request. Deployed only whereprograms.litellm.enable. - Fixed a LiteLLM conflict (TDD):
litellm_deepseek_reasoning_stripdropped all structured reasoning on DeepSeek routes. DeepSeek’s thinking mode guide requiresreasoning_contentpassed back on every request that carriestools. Now kept whentoolsis non-empty;<think>text stripping for SillyTavern is unchanged. - Reasoning replay probe: planted a codeword in replayed reasoning. Recall was about 27% on the free endpoint and 40% on paid Flash for both pi’s shape and
reasoning_detailsalone; control 0%. Inconclusive about cause; not specific to pi’s format or the free tier.
Verification
- 25/25 strip-callback tests pass; prek hooks pass on the changed files.
hm switchapplied; LiteLLM restarted on the new bundle;pi --list-modelscatalog intact.- End-to-end
pi -pon the free model completed a 3-turn tool task; threechat deepseek/deepseek-v4-flash-0731:freespans landed onlitellm-proxyin SigNoz.
- Wire capture: ran a second LiteLLM (port 4002) from a copied config bundle with OpenRouter’s
api_basepointed at a logging forwarder, and a debug pi extension dumping pi’s payload. pi → LiteLLM → OpenRouter is faithful; replayedreasoning_detailssurvives. Response stream opens with a lone" "content chunk; upstream fingerprintvllm-dev-ep-17a051ab. - Root defect found via
prompt_tokensdeltas: the free endpoint drops replayed reasoning longer than 1024 characters (1005 kept, 1025 dropped, whole not truncated, every field shape). Paid Flash (Relace) keeps all lengths. In the original session 25 of 280 turns (the longest plans) were dropped.
Conclusions
- The free endpoint loses the model’s longest plans between tool calls; the other 250 turns’ reasoning did arrive, so the looping is mostly the model itself (Flash, shallow reasoning, poor use of its own replayed plan: 2/8 recall even when the plan was in the prompt).
- Recommendation: use the paid slug (about 0.12 per M tokens) or a stronger model for agentic review work.
Commits
9f5f34dfix(litellm): keep reasoning_content for DeepSeek tool-carrying requests6078abcfeat(pi): route pi’s OpenRouter traffic through LiteLLM