Problem
Tinycode never sends num_ctx to Ollama at any point in the request path (grep -rln "num_ctx" packages/tinycode/src/ returns nothing). This means Ollama serves every local model at its own default runtime context window, completely independent of the model's actual trained capacity.
Reproduced with qwen3.5:9b, whose real trained context length is 262,144 tokens (confirmed via ollama show//api/tags — details.context_length: 262144). With num_ctx unset, the server truncated generation at a 4096-token total window (input+output combined) — roughly 1.5% of the model's real capacity.
Evidence
A large-enough first-turn prompt (~2050 input tokens) caused qwen3.5:9b to hit step_finish reason:"length" with tokens:{"total":4096,"input":2050,"output":2046} — input+output sums exactly to 4096, identically across 3 separate runs spanning 2 different tasks and a reworded retry (rules out prompt-content as the driver; confirms a fixed, deterministic ceiling).
Tinycode's own empty-response handling in packages/tinycode/src/session/prompt.ts:1200-1218,1235 compounds this: when a turn produces no tool call and no captured text (because generation was cut off mid-stream by the context overflow, not because the model was actually silent), it injects a synthetic nudge — literally "Please analyze and respond to the tool results above." — even though no tool call ever occurred. The model's next turn faithfully reacts to that misleading nudge, producing confused meta-commentary that looks like a prompt-engineering failure but is actually a downstream symptom of the context-window bug.
Root cause detail
packages/tinycode/src/provider/local-discovery.ts:181-183 already computes, per-model, from Ollama's own reported details.context_length:
const effectiveContext = contextLimit > 0 ? Math.floor(contextLimit * 0.8) : 0
const outputLimit = contextLimit > 0 ? Math.min(4096, Math.floor(contextLimit * 0.2)) : 0
But effectiveContext is used only for tinycode's own internal token-budget bookkeeping (limit: {context, output}) — it is never transmitted as an actual num_ctx request parameter to Ollama. So tinycode's own internal accounting believes ~209,715 tokens are available for qwen3.5:9b (80% of 262,144), while the server is actually enforcing ~4096 — a ~50x mismatch between what tinycode thinks it has and what it's actually being given.
Confirmed this isn't tinycode's own requested max_tokens (also coincidentally 4096, via maxOutputTokens() in packages/tinycode/src/provider/transform.ts:1277-1279) being the binding constraint: observed output (2046) stopped short of that 4096 client-side request. If the client-side cap were binding, output would have run the full 4096 regardless of input length. It didn't — it stopped exactly where input + output = 4096, which only happens when the server's context window (not the client's requested output ceiling) is the actual limit.
No user-facing workaround exists today either — the provider options config field (packages/tinycode/src/config/provider.ts:61,84) is forwarded into provider/client construction (baseURL, headers) per provider.ts:894-1121, not into per-request generation parameters.
Fix
- Immediate mitigation: gate the empty-response nudge (
prompt.ts:1200-1218,1235) on whether a tool call occurred on a prior turn — stop injecting a "tool results above" message when no tool was ever called. This won't fix the underlying truncation but stops it from producing a confusing, misleading follow-up.
- Root fix: pass
num_ctx explicitly when constructing Ollama requests, using the already-computed effectiveContext value (currently dead-ended at bookkeeping-only use).
Not specific to any one agent persona or prompt shape — any tinycode↔Ollama request with a first-turn prompt large enough to approach the default (not actual) context window is exposed.
Related research
Full investigation writeup with additional verification: ~/projects/ollama-lab/notes/tinycode-scaffolding-benchmark-2026.md (external repo, not in this codebase).
Problem
Tinycode never sends
num_ctxto Ollama at any point in the request path (grep -rln "num_ctx" packages/tinycode/src/returns nothing). This means Ollama serves every local model at its own default runtime context window, completely independent of the model's actual trained capacity.Reproduced with
qwen3.5:9b, whose real trained context length is 262,144 tokens (confirmed viaollama show//api/tags—details.context_length: 262144). Withnum_ctxunset, the server truncated generation at a 4096-token total window (input+output combined) — roughly 1.5% of the model's real capacity.Evidence
A large-enough first-turn prompt (~2050 input tokens) caused
qwen3.5:9bto hitstep_finish reason:"length"withtokens:{"total":4096,"input":2050,"output":2046}— input+output sums exactly to 4096, identically across 3 separate runs spanning 2 different tasks and a reworded retry (rules out prompt-content as the driver; confirms a fixed, deterministic ceiling).Tinycode's own empty-response handling in
packages/tinycode/src/session/prompt.ts:1200-1218,1235compounds this: when a turn produces no tool call and no captured text (because generation was cut off mid-stream by the context overflow, not because the model was actually silent), it injects a synthetic nudge — literally"Please analyze and respond to the tool results above."— even though no tool call ever occurred. The model's next turn faithfully reacts to that misleading nudge, producing confused meta-commentary that looks like a prompt-engineering failure but is actually a downstream symptom of the context-window bug.Root cause detail
packages/tinycode/src/provider/local-discovery.ts:181-183already computes, per-model, from Ollama's own reporteddetails.context_length:But
effectiveContextis used only for tinycode's own internal token-budget bookkeeping (limit: {context, output}) — it is never transmitted as an actualnum_ctxrequest parameter to Ollama. So tinycode's own internal accounting believes ~209,715 tokens are available forqwen3.5:9b(80% of 262,144), while the server is actually enforcing ~4096 — a ~50x mismatch between what tinycode thinks it has and what it's actually being given.Confirmed this isn't tinycode's own requested
max_tokens(also coincidentally 4096, viamaxOutputTokens()inpackages/tinycode/src/provider/transform.ts:1277-1279) being the binding constraint: observed output (2046) stopped short of that 4096 client-side request. If the client-side cap were binding, output would have run the full 4096 regardless of input length. It didn't — it stopped exactly whereinput + output = 4096, which only happens when the server's context window (not the client's requested output ceiling) is the actual limit.No user-facing workaround exists today either — the provider
optionsconfig field (packages/tinycode/src/config/provider.ts:61,84) is forwarded into provider/client construction (baseURL,headers) perprovider.ts:894-1121, not into per-request generation parameters.Fix
prompt.ts:1200-1218,1235) on whether a tool call occurred on a prior turn — stop injecting a "tool results above" message when no tool was ever called. This won't fix the underlying truncation but stops it from producing a confusing, misleading follow-up.num_ctxexplicitly when constructing Ollama requests, using the already-computedeffectiveContextvalue (currently dead-ended at bookkeeping-only use).Not specific to any one agent persona or prompt shape — any tinycode↔Ollama request with a first-turn prompt large enough to approach the default (not actual) context window is exposed.
Related research
Full investigation writeup with additional verification:
~/projects/ollama-lab/notes/tinycode-scaffolding-benchmark-2026.md(external repo, not in this codebase).