Historian
The historian is a background agent with its own model selection. It turns settled conversation into chronological compartments so your agent keeps the session’s story without carrying every raw message in the active prompt.
Understand a compartment
Section titled “Understand a compartment”A compartment is a condensed episode of session history. It records the covered message range, a title and episode type, an importance score, and four paraphrases from detailed to anchor-only.
The compartment stays in the active prompt inside the session-history block. It is not the same as a dropped tool result: a drop becomes a small placeholder, while a compartment remains readable history. The original messages also stay in the local database, where ctx_expand can retrieve them.
The historian promotes durable facts from the episode into project memory. Those facts appear in the project-memory block rather than being duplicated inside the compartment.
Follow the decay tiers
Section titled “Follow the decay tiers”New compartments enter at full detail. During a later history rebuild, Magic Context chooses a render tier deterministically from three inputs:
- Age: newer compartments keep more detail.
- Importance: higher-scored compartments decay more slowly.
- Budget pressure: a tighter history budget moves more compartments to shorter tiers.
The tiers move from full paraphrase, to compressed paraphrase, to concise summary, to an anchor-only title. The oldest low-priority compartments can be omitted from the prompt. Their stored source transcript remains available.
The render choice uses an importance-adjusted half-life. At neutral importance and normal pressure, the half-life is about 24 compartments; 25 importance points double or halve it. Rendering is deterministic and makes no extra model call. A larger active model window gives the history renderer more room without asking the historian to rewrite old compartments.
Fit history into its budget
Section titled “Fit history into its budget”history_budget_percentage reserves a fraction of the usable context at the execute threshold for the session-history block. The default is 0.15, with an allowed range of 0.05–0.5. On a 200k usable window at the default 65% execute threshold, that is 19,500 tokens; on a 1M usable window, it is 97,500 tokens.
This is a budget for history that remains in the prompt, not an amount Magic Context tries to remove. If compartment content exceeds the budget, deterministic decay uses shorter tiers or omits old compartments. Link to the generated configuration reference rather than copying configuration blocks between pages.
Know when it runs
Section titled “Know when it runs”Automatic historian work considers settled conversation before the recent protected window. It can run when:
- context pressure approaches the execute threshold and queued drops are not enough;
- enough distinct git commit clusters mark completed work phases; or
- the raw conversation tail has grown large enough to form a useful compartment.
The pressure trigger uses about 5% of the active model’s usable working range, clamped from 5k to 50k tokens. The amount sent in one historian job also respects the historian model’s own context window.
A historian run publishes a new compartment without immediately rebuilding all older history. New compartments use the additive history block at full detail. Older decay tiers are recalculated when a later cache-safe history rebuild is already warranted, such as a model change, relevant configuration change, expired assumed cache, project-memory edit, or an oversized additive history block. This keeps ordinary turns byte-identical for prompt caching.
Choose the historian model
Section titled “Choose the historian model”Summary quality comes from the historian model, not the main model answering your coding request. A smaller or less instruction-following historian can produce vague titles, miss decisions, or write confusing paraphrases even when the main model is strong.
Configure the historian independently for each harness. A configured historian uses only its model and its explicit fallback_models, in order. Retries stay on those models; if the chain is exhausted, summarization reports a failure instead of silently using the active session model. This applies to automatic summarization, /ctx-wrapup, /ctx-recomp, and their staging and compression passes. No extra setting is needed.
With no historian model configured, OpenCode inherits the session model; Pi and Oh My Pi do not summarize. A model is configured when the selected harness block has a non-empty model entry, either a string or an object with model. Metadata, reasoning settings, and schema defaults do not configure a model. Oh My Pi selects historian.omp when present, otherwise historian.pi; an explicit OMP block without a model does not inherit Pi’s model. historian.disable: true stops the historian on every host.
Named user profiles can switch historian model selections as a group; a project may select a profile but cannot define one. See the generated historian reference and model profiles for the exact schema.
In Rust mode, the module consumes the host-resolved historian chain unchanged and skips summarization when the host supplies no chain or an empty chain.
Set the primary model at historian.opencode.model. Put ordered alternatives in historian.opencode.fallback_models. OpenCode entries can set a reasoning variant; they do not accept Pi’s thinking_level field.
Set the primary model at historian.pi.model. Put ordered alternatives in historian.pi.fallback_models. Pi entries can set thinking_level; they do not accept OpenCode’s variant field.
If your compartments read badly, first choose a stronger historian model or reasoning setting. historian.two_pass can add a second cleanup call for models that need help removing low-signal lines and duplicates, at additional cost.
Expand meaningful tool calls
Section titled “Expand meaningful tool calls”historian.expand_tools makes selected tool calls readable to the historian, including their inputs and results. Built-in templates cover notes, memories, todos, questions, tasks, and fleet communication (ask, peer_send, board, room, work, knowhow). Other tools keep their compact TC: name(arg) behavior. Expanded calls remain visible alongside assistant text, in original part order.
{ "historian": { "expand_tools": { "ask": "Asked: ${input.question.truncate(200)} → ${output}", "peer_send": "PM to ${input.agent}: ${input.message.truncate(300)}", "board": false } }}Keys are exact tool names from the host, not aliases. User and project entries override built-ins; project entries override matching user entries. false disables an expansion, restoring the compact summary. This option changes only future historian/recomp input and verbose ctx_expand previews: it does not rewrite compartments, stored history, permissions, or the provider wire. The default ctx_expand transcript deliberately stays compact.
Templates support ${input.path} and ${output.path} with dotted fields. Bare ${output} is the original result text; field access parses JSON object results. Missing fields and pending results are empty. Non-string values use compact JSON with sorted object keys. Newlines become spaces.
For arrays, use [N] for an index, [*].field for projection, .each("${field}") for a relative element template (${.} means the element), .join("separator"), or .count. Lists default to comma-separated projections or semicolon-separated .each results. For example, ${input.todos.each("${status}: ${content}").join(" | ").truncate(250)}. Only one .each level is allowed. There are no expressions, conditions, or other functions; invalid templates are config errors.
Each placeholder defaults to 300 characters; optional .truncate(N) must come last. Lists show at most 10 elements, then … +N more, and the complete expansion is capped at 1,000 characters (with … marking a cut). Expansions count toward the chunk token budget, while call/result boundary rules remain unchanged. Keep templates short when a tool carries long prompts or board updates.
Compare automatic folds with /ctx-wrapup
Section titled “Compare automatic folds with /ctx-wrapup”Automatic runs react to pressure and settled work. /ctx-wrapup [messages_to_keep] is the on-demand version: it advances the historian over older live history now while leaving the newest messages raw. The default keep count is 20.
Use /ctx-wrapup before switching to a smaller-window model, ending a long work phase, or handing a session to another model. It is available only in primary sessions and refuses to run when Magic Context’s context management is disabled.
/ctx-wrapup reports progress through OpenCode notifications. If no natural cache rebuild is pending, it can suggest /ctx-flush to apply the refreshed prompt on the next message.
/ctx-wrapup streams progress in Pi’s status line, then schedules the history refresh for a safe prompt update. It does not print the OpenCode-specific /ctx-flush suggestion.
/ctx-recomp serves a different purpose: it rebuilds stored compartments from raw history when compartment state is wrong, including compartments still written in an older history layout. See the commands reference for syntax.
Read what the agent sees
Section titled “Read what the agent sees”The prompt contains a compact session-history block similar to:
<session-history><compartment start="1" end="42" title="Initial project setup"> Set up the TypeScript project and established lint and format commands.</compartment><compartment start="43" end="98" title="Authentication implementation"> Added JWT authentication and recorded the token-lifetime decision.</compartment><compartment start="99" end="115" /></session-history>The self-closing compartment is an anchor whose detailed content no longer fits the active history budget. The agent can use the message range with ctx_expand when it needs the original detail.
Use /ctx-status to inspect historian progress, compartment coverage, and the history budget. In OpenCode, the TUI sidebar also shows compartment state; Pi shows a compact status line in its footer.
Continue with Context reduction to see how compartments interact with tool-output reduction and execute thresholds.