Compaction¶
CompactionDetails¶
class CompactionDetails(read_files: list[str] = list(), modified_files: list[str] = list())
tau_agent_core.compaction.CompactionDetails
File-operation details stored alongside a compaction (pi: CompactionDetails).
Constructor parameters
read_files: list[str] = list()— (no description)modified_files: list[str] = list()— (no description)
CompactionError¶
class CompactionError(code: str, message: str)
tau_agent_core.compaction.CompactionError
Raised when a compaction cannot complete.
Pythonic translation of pi's Result<T, CompactionError> error arm
(types.ts:161). code is one of "aborted", "summarization_failed",
or "invalid_session". Fail-Early: callers handle the failure rather than
receive a fabricated summary.
Constructor parameters
code: str— (no description)message: str— (no description)
CompactionPolicy¶
class CompactionPolicy(mode: PolicyMode, max_turns: int | None = None, max_tokens_per_turn: int | None = None, summarizer_model: Model | None = None, summarizer_api_key: str | None = None, reserve_tokens: int = DEFAULT_COMPACTION_SETTINGS.reserve_tokens, keep_recent_tokens: int = DEFAULT_COMPACTION_SETTINGS.keep_recent_tokens)
tau_agent_core.compaction_policy.CompactionPolicy
One run's declared answer to "what happens when the context fills up?".
Construct through :meth:disabled, :meth:local_summarizer or
:meth:turn_cap — the constructors are what make the mode/field pairing
checkable. There is no default instance and no default mode.
Constructor parameters
mode: PolicyMode— (no description)max_turns: int | None = None— (no description)max_tokens_per_turn: int | None = None— (no description)summarizer_model: Model | None = None— (no description)summarizer_api_key: str | None = None— (no description)reserve_tokens: int = DEFAULT_COMPACTION_SETTINGS.reserve_tokens— (no description)keep_recent_tokens: int = DEFAULT_COMPACTION_SETTINGS.keep_recent_tokens— (no description)
admit_turn¶
admit_turn(turns_used: int) -> None
tau_agent_core.compaction_policy.CompactionPolicy.admit_turn
Admit the turns_used-th user turn, or raise (premise P2).
turns_used is 1-based and counts prompt() calls, which is the unit a
scripted scenario is written in.
Parameters
turns_used: int— (no description)
bind_to¶
bind_to(model: Model) -> None
tau_agent_core.compaction_policy.CompactionPolicy.bind_to
Check this declaration against the model it will run under; raise if not.
Called once, at session construction. Everything checkable before a token is spent is checked here rather than discovered at turn 40 of a scenario run.
Parameters
model: Model— (no description)
compaction_settings¶
tau_agent_core.compaction_policy.CompactionPolicy.compaction_settings: CompactionSettings
The :class:CompactionSettings this policy puts in force.
turn_cap leaves compaction enabled: the point of that policy is
that the measured system stays the shipped system, and the threshold is
kept out of reach by the budget rather than by switching the mechanism off.
disabled¶
disabled(*, max_turns: int) -> CompactionPolicy
tau_agent_core.compaction_policy.CompactionPolicy.disabled
Compaction off, bounded by user-turn count (§16.8 option 1).
max_turns is not decoration: with compaction off, nothing else stops
the conversation growing past the model window, and the bound is the whole
of what makes this policy safe. Exceeding it raises rather than letting the
run continue into a provider-side overflow whose cause is not recoverable
from the artifact.
Parameters
max_turns: int— (no description)
local_summarizer¶
local_summarizer(*, model: Model, api_key: str) -> CompactionPolicy
tau_agent_core.compaction_policy.CompactionPolicy.local_summarizer
Compaction on, through a separately declared model (§16.8 option 2).
api_key is required rather than inherited from the session: a
summariser on the near side of a partition is a different endpoint with
different credentials, and silently reusing the session's key is the kind
of guess that works in the lab and fails on the board. Pass the literal the
local server expects (many ignore it) — but pass it.
The key is never written to a manifest; see :meth:to_manifest.
Parameters
model: Model— (no description)api_key: str— (no description)
observe_context¶
observe_context(*, turns_used: int, context_tokens: int, context_window: int) -> None
tau_agent_core.compaction_policy.CompactionPolicy.observe_context
Check the run against its declared budget at the auto-compaction site.
Called at the one place should_compact is evaluated, before the
enabled/threshold gates, so a turn_cap run that has broken its premise
dies here rather than making the full-window model call the policy exists to
keep out of the measurement.
Modes other than turn_cap declare no per-turn token bound, so there is
nothing here for them to violate. That asymmetry is not an oversight: it is
the reason turn_cap is the stronger declaration.
Parameters
turns_used: int— (no description)context_tokens: int— (no description)context_window: int— (no description)
summarizer_for¶
summarizer_for(session_model: Model) -> tuple[Model, str | None]
tau_agent_core.compaction_policy.CompactionPolicy.summarizer_for
The (model, api_key) a compaction under this policy summarises through.
For every mode but local_summarizer that is the session's own model and
the session's own key — which is exactly the shipped behaviour, restated
rather than changed. Returning None for the key means "whatever the
session was constructed with"; the session substitutes its own.
Parameters
session_model: Model— (no description)
to_manifest¶
to_manifest() -> dict[str, Any]
tau_agent_core.compaction_policy.CompactionPolicy.to_manifest
The manifest fragment. JSON-serialisable, and it never carries a secret.
Everything a later reader needs to know what population a number came from, and nothing that would make the artifact unsafe to keep.
turn_cap¶
turn_cap(*, max_turns: int, max_tokens_per_turn: int) -> CompactionPolicy
tau_agent_core.compaction_policy.CompactionPolicy.turn_cap
Compaction as shipped, under a budget proven to keep it out of reach.
See the module docstring for the proof and for which half of it is checked where. Both numbers are the caller's to supply: this module will not invent a per-turn token bound, because an invented bound turns the proof back into the estimate §16.8 refuses.
Parameters
max_turns: int— (no description)max_tokens_per_turn: int— (no description)
CompactionPolicyError¶
tau_agent_core.compaction_policy.CompactionPolicyError
A compaction policy declaration is inadmissible.
Raised at declaration time or at bind time — never mid-run. Either the fields do not match the declared mode, or the budget does not close against the model the policy was bound to.
CompactionPolicyViolation¶
tau_agent_core.compaction_policy.CompactionPolicyViolation
A bound run exceeded the budget its policy declared.
The run is void: a measurement taken past its own declared bound describes a configuration nobody wrote down. Raised at the site the bound was crossed, with the numbers, so the failure is legible rather than a plausible value.
This is not a compaction failure and is deliberately not a
:class:~tau_agent_core.compaction.CompactionError — compaction did not fail,
the run's premise did.
CompactionPreparation¶
class CompactionPreparation(first_kept_entry_id: str, messages_to_summarize: list[dict[str, Any]], turn_prefix_messages: list[dict[str, Any]], is_split_turn: bool, tokens_before: int, file_ops: FileOperations, settings: CompactionSettings, previous_summary: str | None = None, compacted_entry_ids: list[str] = list())
tau_agent_core.compaction.CompactionPreparation
Prepared inputs for a compaction run (pi: CompactionPreparation).
Constructor parameters
first_kept_entry_id: str— (no description)messages_to_summarize: list[dict[str, Any]]— (no description)turn_prefix_messages: list[dict[str, Any]]— (no description)is_split_turn: bool— (no description)tokens_before: int— (no description)file_ops: FileOperations— (no description)settings: CompactionSettings— (no description)previous_summary: str | None = None— (no description)compacted_entry_ids: list[str] = list()— (no description)
CompactionResult¶
class CompactionResult(summary: str, first_kept_entry_id: str, tokens_before: int, details: CompactionDetails | None = None, compacted_entry_ids: list[str] = list(), tokens_saved: int = 0, usage: dict[str, int] = zero_usage())
tau_agent_core.compaction.CompactionResult
Generated compaction data ready to persist (pi: CompactionResult).
compacted_entry_ids and tokens_saved are τ additions — pi computes
these in its persistence layer; τ threads them through so
SessionManager.apply_compaction can record them on the compaction entry.
Constructor parameters
summary: str— (no description)first_kept_entry_id: str— (no description)tokens_before: int— (no description)details: CompactionDetails | None = None— (no description)compacted_entry_ids: list[str] = list()— (no description)tokens_saved: int = 0— (no description)usage: dict[str, int] = zero_usage()— (no description)
CompactionSettings¶
class CompactionSettings(enabled: bool = True, reserve_tokens: int = 16384, keep_recent_tokens: int = 20000)
tau_agent_core.compaction.CompactionSettings
Compaction thresholds and retention settings (pi: CompactionSettings).
Constructor parameters
enabled: bool = True— (no description)reserve_tokens: int = 16384— (no description)keep_recent_tokens: int = 20000— (no description)
ContextUsageEstimate¶
class ContextUsageEstimate(tokens: int, usage_tokens: int, trailing_tokens: int, last_usage_index: int | None)
tau_agent_core.compaction.ContextUsageEstimate
Estimated context-token usage for a message list (pi: ContextUsageEstimate).
Constructor parameters
tokens: int— (no description)usage_tokens: int— (no description)trailing_tokens: int— (no description)last_usage_index: int | None— (no description)
calculate_context_tokens¶
calculate_context_tokens(usage: dict[str, Any]) -> int
tau_agent_core.compaction.calculate_context_tokens
Total context tokens from a Usage dict (pi: calculateContextTokens).
Prefers the provider-reported total_tokens; falls back to the sum of the
component counts when total is absent/zero.
Parameters
usage: dict[str, Any]— (no description)
compact¶
compact(preparation: CompactionPreparation, model: Model, api_key: str | None, *, custom_instructions: str | None = None, thinking_level: str | None = None) -> CompactionResult
tau_agent_core.compaction.compact
Generate the compaction summary from prepared history (pi: compact).
On a split turn, the history and the turn prefix are summarized concurrently
and stitched together (pi uses Promise.all).
Parameters
preparation: CompactionPreparation— (no description)model: Model— (no description)api_key: str | None— (no description)custom_instructions: str | None = None— (no description)thinking_level: str | None = None— (no description)
estimate_context_tokens¶
estimate_context_tokens(messages: list[dict[str, Any]]) -> ContextUsageEstimate
tau_agent_core.compaction.estimate_context_tokens
Estimate context tokens, anchoring on the last assistant Usage when present.
Faithful port of pi's estimateContextTokens (compaction.ts:165): the provider is the source of truth for everything up to the last assistant turn; only the trailing messages after it are heuristically estimated.
Parameters
messages: list[dict[str, Any]]— (no description)
estimate_span_tokens¶
estimate_span_tokens(entries: list[dict[str, Any]]) -> int
tau_agent_core.compaction.estimate_span_tokens
Estimated context tokens a SPAN of active-path entries contributes.
The one spelling of "what did this span cost the context", so the number a
splice anchor RECORDS (coveredTokens on a compaction/elide entry —
TREE-BROWSER-AS-EDITOR.md §8.1, §8.2) is produced by the same arithmetic as the
tokensBefore it sits beside (prepare_compaction, :func:estimate_tokens
via :func:estimate_context_tokens). Two spellings would let a browser row show
"folds 12 entries, 8k tokens" against a tokensBefore computed on a different
basis, and nothing would report the mismatch.
Public because the value must be named at the CALL SITE: §11.3 makes the
provenance a required keyword argument on the appenders precisely so a caller
that cannot compute it fails there (AgentSession._perform_compaction and
tree_ops.elide_span / commit_branch). Computing it inside the five SessionLog
implementations instead would put this arithmetic — and the entry→message
flattening under it — in five places.
Non-message entries contribute nothing, exactly as they contribute nothing to
model input: an agent_spec/customEntry/navigate node in the span is
counted by coveredEntries and priced at zero here, which is the truth.
Parameters
entries: list[dict[str, Any]]— (no description)
estimate_tokens¶
estimate_tokens(message: dict[str, Any]) -> int
tau_agent_core.compaction.estimate_tokens
Estimate token count for one message dict (pi: estimateTokens).
Conservative ~4-chars-per-token heuristic over the textual payload, by role.
Parameters
message: dict[str, Any]— (no description)
policy_for_scenario¶
policy_for_scenario(scenario: str, *, max_turns: int, max_tokens_per_turn: int) -> CompactionPolicy
tau_agent_core.compaction_policy.policy_for_scenario
Build the declared policy for a lettered scenario (§7.3-§7.7).
Raises on an unknown scenario rather than falling back to anything: an unrecognised scenario letter is a harness bug, and the failure mode a default would produce is a run measured under a policy nobody chose.
Parameters
scenario: str— the scenario letter,"A"-"E".max_turns: int— the run's declared bound on user turns.max_tokens_per_turn: int— the run's declared bound on per-turn context growth.
Raises
CompactionPolicyError— unknown scenario, or the scenario's declared mode is not one this builder can construct from these arguments.
prepare_compaction¶
prepare_compaction(path_entries: list[dict[str, Any]], settings: CompactionSettings) -> CompactionPreparation | None
tau_agent_core.compaction.prepare_compaction
Prepare active-path entries for compaction, or None when inapplicable.
Faithful port of pi's prepareCompaction (compaction.ts:542), reading τ entry
dicts. Returns None when there is nothing to compact: an empty path, a path
that already ends in a compaction entry, or — τ's one divergence from pi
here, see the comment at the guard — a cut that would remove no message from
the context at all, which is what the shipped keep_recent_tokens produces
for every conversation smaller than it.
Parameters
path_entries: list[dict[str, Any]]— (no description)settings: CompactionSettings— (no description)
Raises
CompactionError('invalid_session')— when the chosen first-kept entry has no id.
should_compact¶
should_compact(context_tokens: int, context_window: int, settings: CompactionSettings) -> bool
tau_agent_core.compaction.should_compact
Whether context usage exceeds the compaction threshold (pi: shouldCompact).
Parameters
context_tokens: int— (no description)context_window: int— (no description)settings: CompactionSettings— (no description)