Skip to content

Context management

Talon automatically handles context window limits. When the accumulated conversation approaches the provider’s limit, the daemon rotates the session: it compresses what happened, stores the result in memory, and starts a fresh session with that context injected. The agent never sees the boundary.

After each agent run, Talon checks the token usage. If the context is getting full, it triggers a rotation:

  1. Talon sends the agent’s reply back to the channel
  2. Talon persists that outbound message to the transcript
  3. The configured summarizer compresses the current transcript
  4. The result is written to memory_items
  5. The session ID is cleared; the next run starts a fresh session
  6. On the next run, Talon assembles the context:
    • The latest session summary
    • The last N messages verbatim (configurable)

The thing is, rotation is no longer on the critical path for user-visible replies. If a turn crosses the threshold, the user still gets the answer immediately instead of waiting on the summarizer call.

Context management is configured per provider under agentRunner.providers.<name>.contextManagement:

agentRunner:
providers:
claude-code:
enabled: true
command: claude
contextWindowTokens: 200000
contextManagement:
enabled: true
triggerMetric: cache_read_input_tokens
thresholdRatio: 0.5
recentMessageCount: 10
summarizer: session-summarizer
OptionDefaultDescription
enabledfalseEnable or disable context rotation for this provider. Set to false to keep unlimited context (useful for Claude Max subscribers)
triggerMetric—Token metric to monitor: input_tokens, cache_read_input_tokens, cache_creation_input_tokens, or cache_total_input_tokens
thresholdRatio—Fraction of contextWindowTokens that triggers rotation (0–1)
recentMessageCount10How many recent messages to inject verbatim after rotation
summarizer—Sub-agent name for history compression (session-summarizer for legacy summaries, session-observer for observational memory)

Set contextManagement.enabled: false to disable rotation entirely. This is useful for:

  • Claude Max subscribers with unlimited context
  • Short-lived conversations that never approach the limit
  • Debugging where you want the full transcript preserved
agentRunner:
providers:
claude-code:
contextManagement:
enabled: false

The per-persona context key is still supported as a fallback:

personas:
- name: assistant
context:
thresholdTokens: 150000
recentMessageCount: 10

The provider-level contextManagement config takes precedence when both are present.

The legacy session-summarizer sub-agent reads the full transcript and produces one structured summary covering:

  • Key topics discussed
  • Decisions made
  • Open questions
  • Relevant facts

That summary is injected into the next session. It is compact and reliable, but each new rotation replaces the previous summary.

PR #189 adds an alternative mode: observational memory. When summarizer: session-observer, Talon appends dated observations instead of overwriting a single summary blob. Each rotation adds a compact decision log with priority markers, plus currentTask and suggestedContinuation metadata so the next run can pick up the interrupted work cleanly.

Example:

Date: 2026-04-08
- 🔴 20:12 User wants docs updated for PRs #179, #189, and #176
- 🟡 20:18 Existing main worktree has unrelated edits; use a separate worktree
- 🔴 20:31 Providers, memory, and context docs updated together

When the observation log grows past Talon’s consolidation threshold, session-reflector merges and prunes older entries so the log stays dense enough to keep injecting.

To enable observational memory:

personas:
- name: assistant
subagents:
- session-observer
- session-reflector
- memory-groomer
- memory-retriever
agentRunner:
providers:
claude-code:
contextManagement:
enabled: true
triggerMetric: cache_read_input_tokens
thresholdRatio: 0.5
recentMessageCount: 10
summarizer: session-observer

Without session-observer and session-reflector in the persona’s subagents list, Talon cannot run the observational-memory path at runtime.

Session summaries, observations, and named memory entries accumulate in memory_items over time. The memory-groomer sub-agent consolidates them: it reads the thread’s stored memory, merges redundant entries, and prunes anything no longer relevant. Schedule it to run periodically:

# fires at 3am daily
- cronExpr: "0 3 * * *"
promptFile: memory-grooming

Every agent run receives a cache-friendly time window injected into the context:

Current time: between 17:50 and 18:00 on Wednesday 2026-04-02 (CEST, UTC+02:00). If you need precise time you can use the bash-tool.

The 10-minute window stays stable long enough for provider-side prompt caching to work. If the exact second matters, the prompt now explicitly tells the model to use a shell time command instead of guessing.

The context assembled for each run includes:

[system prompt]
[personality fragments]
[current time]
[stored context from the selected compression mode]
[last N messages verbatim]
[current message]

The agent never receives explicit notification that a session rotation occurred. The summary is presented as part of the normal context.