DSH Long Sessions: Token Budgets, Message Caps & HTTP 400

Author
DeepSeekAgent.io Editorial Team
Published
Updated

A long Session can fail before it fills the model's context window. A single request is constrained by the context window, reserved output, gateway body size, message count, and tool-schema size. The first limit reached can produce HTTP 400 even while DSH's token meter still shows room.

On October 21, 2026, a community reproduction on DeepSeek Harness v0.2.1-rc.2 documented that distinction. After 180 Goal rounds, the projected request contained about 2,057 messages and 790K tokens. The model route declared a one-million-token context window, so DSH had not reached its token-pressure threshold. The upstream gateway nevertheless rejected the request at 2,048 messages, and retries rebuilt the same over-limit history.

This is not another name for a context-window calculation error. A token budget measures textual and structured volume; a message budget measures the number of discrete projected nodes. Tool-heavy agents grow both, but not at the same rate.

Two measurements for the same context

Before a model call, DSH projects Session events into provider messages. User input, assistant output, tool calls, tool results, developer messages, and compaction summaries can each become separate nodes.

Two 200K-token Sessions can have very different shapes:

  • 100 long messages at roughly 2,000 tokens each;
  • 2,000 short messages at roughly 100 tokens each.

Both may fit the model window. The second can still violate a gateway's per-request message cap. Shortening the text inside every item does not help when the gateway checks the length of the message array.

The community case bisected one captured request: 1,022 and 2,047 projected messages returned 200, while 2,048 returned 400. Truncating every message to 40 characters and removing reasoning_content did not change the boundary. This establishes the behavior of the tested compatible gateway, not a universal 2,048-message limit for DeepSeek or every OpenAI-compatible endpoint.

Why automatic compaction did not start

compaction-basic derives proactive pressure from tokens. Its threshold can be simplified as:

thresholdTokens = min(
  contextWindow × thresholdRatio,
  contextWindow − reservedCompletionTokens − headroomTokens
)

The reproduced route declared a 1M-token window, a 0.8 threshold ratio, a 32K output reservation, and 65,536 tokens of headroom. That put proactive compaction near 800K tokens. The failing request was about 790K, so DSH still considered it below pressure.

That policy protects against context overflow but cannot see an independent gateway message cap. The returned error was also not a standard context_length_exceeded response, so DSH could not classify it as overflow and invoke recovery compaction:

message count exceeds gateway limit
  → provider returns 400
  → Session history remains unchanged
  → retry projects the same messages
  → provider returns 400 again

Why tool-heavy work reaches the cap sooner

A normal chat turn often adds one user and one assistant node. An Agent round may add planning, several tool calls, matching results, state updates, and follow-up verification. A round can add only a few thousand tokens while creating dozens of messages.

Node growth accelerates when the Agent:

  • reads many small files or search results separately;
  • repeats a failed tool call with the same arguments;
  • merges several Subagent progress reports into the parent Session;
  • records tool additions or removals after a plugin change;
  • continues Goal rounds without new progress;
  • retrieves the same evidence after tool-result pruning.

Low average tokens per round therefore do not make a long Session safe. Tool-heavy work needs turn, node, and token monitoring together.

Prevention in the current release

The community proposal adds an independent maxMessages field to Compaction Policy. Pressure would become true when measurement.nodes.length reaches the budget, with the predicate rechecked after pruning and each compaction attempt. The patch passed the reporter's package tests, but it is not part of the official v0.2.1-rc.2 release. Do not treat maxMessages as a supported configuration in that version.

Without patching DSH, use operational controls:

  1. Cap task rounds. Pause a simple task that still has not converged after 20–30 rounds instead of allowing hundreds of automatic continuations.
  2. Reduce fragmented tool calls. Batch searches, range reads, and structured results produce fewer nodes than a long sequence of tiny calls.
  3. Run /compact before the long tail. Do not rely only on the token meter; compact when tool-call count starts climbing quickly.
  4. Persist milestones. Store confirmed findings in a short task note so a compacted or new Session does not need to repeat discovery.
  5. Measure each provider route. Compatible gateways can impose different request limits for the same model.

Lowering a custom model's declared contextWindow can make token pressure fire earlier. In the reported setup, reducing 1M to 500K triggered compaction at roughly 1,250 tool-heavy messages and stayed below the gateway boundary. This is only an approximation: it sacrifices usable context for every Session and does not protect a request containing many tiny messages.

Recovering a Session that always returns 400

First separate two failure shapes:

  • a new Session works while one old Session always returns the same 400: suspect a persistent limit in that history;
  • every Session fails: inspect the provider, key, credit, route, and global plugins before touching stored history.

For one affected Session:

  1. Stop automatic continuation and record the full error, DSH version, provider, and route.
  2. Export or copy the conversation while preserving the original Session.
  3. If /compact still runs, compact once and send a minimal test message.
  4. If compaction resends the same over-limit history and fails, start a new Session from a manually prepared task summary.
  5. Audit file changes, releases, payments, and remote operations before repeating work with side effects.
  6. Keep the original Session as an audit record instead of editing its compressed log directly.

Manual changes to session.v4.jsonl.zstd are risky. Session headers, sequence numbers, checksums, and projection caches are related; a log that can be decoded may still disappear from the sidebar or reject later appends. Recovery should preserve task state and side effects, not force the original artifact to remain writable.

Monitoring that closes the gap

SignalWhat to track
Input tokensPer-turn value and ten-turn growth rate
Projected messagesUser, assistant, tool, result, and developer nodes
Goal roundsWhether each continuation adds new progress
Repeated toolsDuplicate tool-and-argument combinations
CompactionTrigger, before/after tokens, and before/after nodes
Provider 400sWhether failure is fixed to one Session and request shape

A complete request budget needs more than tokens. Message count, tool-schema size, request bytes, rounds, time, and cost should be independently bounded per provider route. Compaction can then run before the first real constraint is reached instead of diagnosing it after failure.

Related reading

References