Skip to main content

Context management

Model context windows are finite. Digitorn helps you keep long chats under the limit with compaction settings in YAML.

What fills the context​

PieceNotes
System promptYour system_prompt and related injects
Tool schemasLarger when many modules are granted
Conversation historyGrows every turn
Memory snapshotGoals / facts when memory is enabled

When token pressure (used / max) crosses your threshold, compaction rewrites older history so recent messages stay intact.

Configure under runtime.context or brain.context​

app.yaml
runtime:
context:
max_tokens: 200000 # 0 = auto from the provider when possible
output_reserved: 4096 # room left for the model reply
strategy: summarize # truncate | summarize
keep_recent: 10 # recent messages kept verbatim
compression_trigger: 0.75 # pressure that starts compaction
summary_max_tokens: 1024
auto_compact: true # inject a default compact hook
summary_brain: # optional - a cheaper/faster brain just for summarizing
provider: deepseek
model: deepseek-chat
backend: openai_compat
config:
api_key: "{{env.DEEPSEEK_API_KEY}}"

summary_brain is a full nested brain, same shape as the agent's own - when set, summarize compaction calls it instead of the agent's main brain, so a fast/cheap model can do the summarizing work while the expensive model stays focused on the conversation.

Per-agent override:

app.yaml
agents:
- id: main
brain:
context:
max_tokens: 32000
strategy: summarize
keep_recent: 8

Full field list: App configuration.

Context sections​

Everything above manages the history the agent already accumulated. Context sections are a different mechanism entirely: fixed content re-injected into every single turn, regardless of history. Use it for things the agent should never have to be reminded of or search for - the current date, a policy document, the working directory it's confined to.

app.yaml
context:
sections:
- builtin: datetime
priority: 10
- id: workspace
title: Workspace
template: |
Working directory: {{session.workdir}}
Platform: {{env.platform}} · architecture {{env.arch}}.
when: session.workdir
priority: 11
- id: policy
title: Support policy
file: kb/policy.md
optional: true

This block goes under context: at the app root, or under an agent's own context: (agents[].context.sections) for a section only that agent sees. Both can be present at once - app-level sections apply everywhere, agent-level sections add to them, and a section with a matching id on the agent overrides the app-level one with the same id.

Each entry picks exactly one content source:

  • builtin - a name from a fixed list, each producing a real string computed at turn time: datetime (today's date, weekday, local time - a snapshot, does not advance mid-turn), user (name, region, locale, timezone, email, roles - whatever the session actually has), session (goal, mode, turn number, working directory, attached files), identity (this app's own name and version), environment (platform/OS/arch/shell), code_index (a generated map of the working directory - only produces anything when one is set), memory_index (the persistent file-memory directive and its current contents - only meaningful when the agent actually has a workdir to keep .digitorn/memory/ in).
  • text - a fixed string, verbatim.
  • template - a string with {{path}} placeholders resolved against user.*, app.*, agent.*, session.*, env.*, plus date, time, datetime, weekday. This is a separate, simpler placeholder syntax from a prompt's own {{app.x}} / {{sys.x}} / {{secret.x}} resolution
    • only the paths listed above resolve here, and only inside template, file, and files values.
  • file / files - one path, or several, read and injected verbatim (each one under its own ## filename heading when there is more than one). Missing and not optional: true, the section shows the read error instead of silently vanishing - useful for catching a typo in the path during development, not something to leave in a shipped app.
  • dir - every file in a folder. A dir whose name contains "memory" gets special handling: a budgeted digest (~4000 characters, feedback_* files first, then project_*, user_*, reference_*, everything else last) instead of the full contents.

Other fields, independent of the source:

  • id - lets an agent-level section override an app-level one with the same id (see above); otherwise optional.
  • title - rendered as a # Title heading above the content.
  • optional - suppress the error text when a file/files/dir source is missing, instead of surfacing it to the agent.
  • writable - appends the same persistent-file-memory directive the memory_index builtin produces, pointed at this section's own file/files/dir, telling the agent it may write back to that location across turns.
  • when - a condition against the same bag template reads from: path == value, path != value, path >= value (also <=, >, <), or a bare path for a truthy check. A section whose when fails is skipped entirely - it never renders, even as an empty block.
  • priority - lower numbers render first; ties keep declaration order.

A file/files/dir source is wrapped in <system-reminder> tags when rendered; builtin/text/template sources are not.

Explicit compact hook​

brain.context.keep_recent configures how many recent messages to preserve. On a hook action, the field name is keep_last (not keep_recent):

app.yaml
runtime:
hooks:
- id: compact_when_full
"on": turn_end
condition:
type: context_pressure
threshold: 0.75
action:
type: compact_context
strategy: summarize
keep_last: 10

If you already declare a compact_context hook, Digitorn does not add a second auto-compact hook on top.

There's a second, separate compaction check besides the hook: the engine also watches pressure continuously during the turn (not just once at turn_start, where the hook fires), so a single turn that racks up many tool calls can get compacted mid-turn before it ever reaches the hook's own threshold. This one is always on with auto_compact (no way to declare it as a hook, since it isn't one) and defaults to a slightly lower threshold (0.95 vs. the hook's 0.97) - in practice it's usually the one that fires first.

Strategies​

StrategyBehaviour
summarizeOlder turns become a short summary; recent turns stay
truncateDrops oldest turns until pressure is acceptable

Tips for app authors​

  • Prefer auto_compact: true for chat apps unless you need a custom hook.
  • Use a smaller keep_recent / keep_last on long-running background agents.
  • Grant fewer tools if tool schemas dominate the window (discovery).