Documentation menu

Long-running sessions: context tracking and rotation

Coding agents slow down, forget instructions and eventually fail once their context window fills up. nid watches how full each session's context is and rotates the conversation before that happens, without losing the session's place in the team.

What nid tracks#

Each session has a context record (see Session.context in the API reference):

FieldMeaning
usedTokens in the context window after the agent's last model call
sizeThe context window size, when the agent reports it
turnsTurns since the conversation started or was last rotated
rotationsRotations so far, with the last one's time, method and reason

Where the numbers come from:

Agentusedsize
Claude Codethe latest assistant message's usage (input + cache creation + cache read + output); subagent messages are ignoredthe result's modelUsage[*].contextWindow
Codexthread/tokenUsage/updated: last.totalTokensmodelContextWindow
ACP agents (opencode, kimi, custom ACP)usage_update.usedusage_update.size
PTY / custom terminal agentsnot reportednot reported

Agents that report nothing still rotate on maxTurns and with nid rotate.

You can see it in:

  • nid ls: the CONTEXT column (62% of 200k, yellow from 75%, ↻2 after two rotations);
  • the dashboard: a context meter on the session page and ctx 62% of 200k in the group's session table.

Rotation#

A rotation happens after a turn ends when the group's policy says it is due, when the human runs nid rotate <session> (or presses Rotate on the session page), or when the agent calls the handoff_write tool by itself. There are two methods:

Compaction (compact): nid asks the agent to compact its own conversation, keeping the same vendor session: Claude Code gets /compact, Codex gets thread/compact/start. This is the cheaper method: the agent keeps a summary of everything it knew and does not have to re-read files.

Handoff (handoff):

  1. nid sends the agent one turn asking it to call handoff_write(summary) with a self-contained handoff (tasks held, what is done, next steps, decisions, gotchas). If the agent already called handoff_write on its own, this step is skipped.
  2. nid stops the agent process and starts a fresh vendor conversation on the same nid session: same session id, worktree, branch, claimed tasks and locks.
  3. The fresh conversation's first message is the handoff plus the current board (what board_read shows). If the agent never wrote a handoff, its last output is used instead and the message says so.

Every rotation is recorded as a rotation event (↻ in nid watch, the dashboard feed and transcript) with the method, the reason, and for a handoff the old and new vendor conversation ids and the summary. A failed rotation is recorded too and reported to the human inbox; a failed compaction in auto mode falls back to a handoff.

Rotations are paused while the group's budget is exhausted (they cost a turn); nid rotate still works.

Configuration#

Set rotate on a group in nid.yaml:

groups:
  web:
    goal: Add dark mode to the settings page
    rotate:
      mode: auto          # auto | compact | handoff | off   (default auto)
      contextPercent: 80  # rotate when the context window is this full (default 85)
      maxTurns: 60        # also rotate after this many turns in one conversation (default: never)
    sessions:
      - agent: claude
        name: lead
      - agent: codex

or on a running group: nid group set web rotate='{"mode":"handoff","maxTurns":40}'.

modeBehaviour
autoThe agent's own compaction when its driver has one (Claude Code, Codex), else a handoff
compactCompaction only; agents without compaction get a handoff
handoffAlways a handoff into a fresh conversation (the most predictable context size, costs a re-read)
offNever automatically; nid rotate and agent-initiated handoff_write still work

Choosing: compaction is cheaper and keeps the agent's working memory, but the vendor decides what to keep and repeated compactions can drift. A handoff gives a clean slate and forces the agent to write down its state, which also leaves a readable record in the event log. For very long runs, mode: auto with a maxTurns limit is a good default; use handoff when you want the record.

Forcing a rotation#

nid rotate web/worker                 # the group's mode (auto when the group says off)
nid rotate web/worker --mode handoff

An idle session rotates at once; a working (or rate-limited) session rotates when its current turn ends. HTTP clients call session.rotate {session, mode?}.

Agents writing their own handoff#

Every agent has the handoff_write(summary) tool. Calling it outside a rotation means "my context is cluttered: start me fresh from this summary when this turn ends". nid then rotates with that summary and does not ask again.