Utility-aware policy¶
The host-issued memory decision: gap planning, gap-driven retrieval, draft-relative admission, and the control plane around them. The specification is utility-aware-memory-architecture.md.
retold.policy.utility_aware ¶
Utility-aware host path: gap planning, draft-relative admission, and fail-closed orchestration.
The host decides whether stored information will improve an answer, not whether it concerns the query. On each user turn the orchestrator generates a baseline draft from public context plus the ambient profile while a gap policy names the user-specific facts the draft may be missing. Only when there are gaps does it retrieve, and only when an admission policy says a candidate would change the draft does it regenerate. Every other path returns the draft unchanged, and every path writes one turn-decision row.
Policies are protocols. Hosted adapters live outside the core package. The orchestrator takes callbacks for baseline and final generation so this module never depends on a model vendor.
UtilityAwareOrchestrator ¶
Deterministic orchestration of one turn. Fails closed to the draft on every error and budget path.
Serving, meaning shadow is off and the path is enabled, requires a bundle registry that holds a passing fitness result for this configuration's bundle. Without one the constructor refuses, so a host cannot serve an unapproved bundle by accident. Shadow mode needs no approval.
retrieval_config is the RetoldConfig the retrieve callable searches with. Given it, the
bundle's retrieval hash is derived from that configuration and a manifest that disagrees is refused.
bundle_components ¶
bundle_components(
config: UtilityAwareConfig, retrieval_config: Any = None
) -> dict[str, object]
Everything that changes what the path does. Hashing this identifies a bundle.
Pass the RetoldConfig the host retrieves with and the retrieval half of the hash is derived from it
rather than taken on trust. A manifest that declares a different retrieval_config_sha256 is refused:
a bundle's fitness result was earned under one retrieval configuration, and a hash copied from that run
into a host that retrieves differently would claim an approval nothing measured.
render_decision ¶
render_decision(decision: TurnMemoryDecision) -> str
Compact one-line rendering for logs and tests.
retold.policy.activation ¶
Ambient activation: which records sit in the always-present profile, decided by rule and audited.
A record is conditional by default and must pass retrieval and admission on each turn. A small class of
broadly applicable preferences about the principal, such as answer style or the language of code examples,
is promoted to ambient and rendered into a bounded profile at session start. Promotion is never a model's
decision alone: a category policy proposes a classification, the host verifies the supporting claim in the
principal's own transcript turns, and deterministic rules decide. Anything ambiguous, low-confidence, or
flagged unsafe goes to a durable review queue and stays conditional until a trusted reviewer resolves it.
Every record also receives a content-free retrieval category from a fixed taxonomy. The distinct categories present in a principal's conditional store form the inventory a gap planner may see; record text never does.
ActivationService ¶
Run the activation policy for one committed record and persist every step of the decision.
ProfileAssembler ¶
Render the principal's ambient records into one bounded block, built once per session.
The profile is what the model is told applies to every reply, so it has to be the same text for the whole session: a promotion, a review resolution, or an expiry landing mid-session would otherwise change the standing instructions between one turn and the next, and the turn decisions of one session would no longer be comparable. The block is therefore assembled on the session's first turn and held until the session ends, which is also what stops every turn from paying for the query.
build ¶
build(principal: Principal) -> ProfileBlock
Return this session's profile, assembling it on the first call and reusing it afterwards.
forget ¶
forget(session_id: str) -> None
Drop a finished session's profile. The next session assembles a fresh one.
ProfileBlock
dataclass
¶
ActivationDecision
dataclass
¶
CategoryPolicy ¶
Bases: Protocol
CategoryDecision
dataclass
¶
What a category policy proposes for one record. It never decides activation on its own.
inventory ¶
inventory(store: Store, principal: Principal) -> list[str]
Content-free labels of the fact categories present in the principal's readable conditional store.
decide_activation ¶
decide_activation(
record: Record,
decision: CategoryDecision | None,
principal_entity_id: str,
evidence_turn: int | None,
*,
min_confidence: float = 0.7,
) -> tuple[ActivationOutcome, str]
Deterministic activation rule. The order matters: eligibility first, safety next, classification last.
retold.policy.bundles ¶
Policy bundles: the complete set of components that produced a decision, hashed, and their fitness.
A bundle is every component that changes what the utility-aware path does: planner model and prompt, judge model and prompt, classifier, taxonomy, inventory builder, retrieval configuration, stage timeouts, budget, and candidate and gap caps. Any change to any of them is a new bundle hash. Active serving is allowed only for a bundle with a recorded passing fitness result; an unapproved bundle may run in shadow mode only.
BundleNotApprovedError ¶
Bases: RuntimeError
Raised when a host tries to serve with a bundle that has no recorded passing fitness result.
BundleMismatchError ¶
Bases: RuntimeError
Raised when a bundle's declared components do not describe the runtime that would serve them.
BundleRegistry ¶
Records fitness results and answers whether a bundle may serve.
bundle_hash ¶
bundle_hash(components: Mapping[str, Any]) -> str
Stable hash of a bundle's components; key order and whitespace do not matter.
retrieval_config_hash ¶
retrieval_config_hash(retrieval_config: Any) -> str
The retrieval half of a bundle hash, derived from the configuration a host actually retrieves with.
retrieval_config is the whole RetoldConfig when the caller has one: the hash then covers the
retrieval section and the reranker section together, because an enabled reranker changes what the judge
sees as much as a gate floor does. A bare retrieval section or a plain mapping is hashed as given.
retold.policy.metrics ¶
Metrics over the turn-decision log, for reports and for a host's rollback decisions.
Every turn decision is assigned exactly one stage outcome, so a change in served injection or recall can be attributed to one stage:
- path_disabled: the utility-aware path was off or the budget was zero, so nothing ran;
- planner_silence: the planner returned no gaps, so no retrieval happened;
- retrieval_miss: the planner named gaps but retrieval returned no conditional candidates;
- judge_rejection: candidates were judged and none admitted;
- policy_failure: a policy failed, timed out beyond its stage limit, or returned malformed output;
- budget_withheld: the per-request budget cut the path short, before admission or before regeneration;
- admitted: memory was admitted; served when it regenerated, shadow when it only would have.
Production turns carry no labels, so unsafe and unexpected admissions cannot be counted here; those come from the fitness suite. What a host can watch is the served and shadow admission rates, the stage counts, latency, cost, the admitted-record distribution, and the review backlog, per bundle and per time window.
RollbackThresholds
dataclass
¶
Limits a host applies to a report. Any breach is a reason to disable the newest stage.
stage_outcome ¶
stage_outcome(decision: Mapping[str, Any]) -> StageOutcome
Map one turn decision to its single stage outcome.
aggregate ¶
aggregate(
store: Store,
*,
since: datetime | None = None,
until: datetime | None = None,
bundle_hash: str | None = None,
session_id: str | None = None,
) -> MetricsReport
Aggregate the turn-decision log into one report. Reads only; a host may call this on a schedule.
rollback_reasons ¶
rollback_reasons(
report: MetricsReport, thresholds: RollbackThresholds
) -> list[str]
Return every threshold the report breaches; empty means no rollback signal.
summarise_many ¶
summarise_many(
reports: Iterable[MetricsReport],
) -> dict[str, Any]
Convenience for hosts comparing windows or bundles.