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
| Piece | Notes |
|---|---|
| System prompt | Your system_prompt and related injects |
| Tool schemas | Larger when many modules are granted |
| Conversation history | Grows every turn |
| Memory snapshot | Goals / 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
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:
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.
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 againstuser.*,app.*,agent.*,session.*,env.*, plusdate,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, andfilesvalues.
- only the paths listed above resolve here, and only inside
file/files- one path, or several, read and injected verbatim (each one under its own## filenameheading when there is more than one). Missing and notoptional: 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. Adirwhose name contains "memory" gets special handling: a budgeted digest (~4000 characters,feedback_*files first, thenproject_*,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# Titleheading above the content.optional- suppress the error text when afile/files/dirsource is missing, instead of surfacing it to the agent.writable- appends the same persistent-file-memory directive thememory_indexbuiltin produces, pointed at this section's ownfile/files/dir, telling the agent it may write back to that location across turns.when- a condition against the same bagtemplatereads from:path == value,path != value,path >= value(also<=,>,<), or a barepathfor a truthy check. A section whosewhenfails 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):
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
| Strategy | Behaviour |
|---|---|
summarize | Older turns become a short summary; recent turns stay |
truncate | Drops oldest turns until pressure is acceptable |
Tips for app authors
- Prefer
auto_compact: truefor chat apps unless you need a custom hook. - Use a smaller
keep_recent/keep_laston long-running background agents. - Grant fewer tools if tool schemas dominate the window (discovery).
Related
- Project memory -
memory_indexand the context builtins - App config - context
- Hooks
- YAML building blocks