# ADR-0014: Conversion-driven extensions (resolvers, typed tools, hooks, ops controls) **Status:** Accepted — 2026-06-10 ## Context Executing the mort conversion (docs/mort-migration.md) surfaced seven capabilities mort's orchestration layer needs from its model substrate. Each is general-purpose — none encodes anything mort-specific — and each was promised in the migration blueprint. ## Decision 1. **`Registry.RegisterResolver`** — dynamic alias resolution for DB/ config-backed tiers. Checked after static aliases (static wins), in registration order, without holding the registry lock (resolvers do I/O); output expands recursively under the existing cycle guard. 2. **`DefineTool[Args]`** — typed tools: parameters from `SchemaFor[Args]`, arguments unmarshaled before the handler. Schema failure panics (startup-time programming error, mirroring NewToolbox). 3. **`Usage` detail fields** — CacheReadTokens / CacheWriteTokens / ReasoningTokens, populated where providers report them (Anthropic cache fields; OpenAI prompt/completion detail objects; Google cached-content + thoughts). Input/Output remain totals; details are portions. 4. **`WithPromptCaching`** — Anthropic top-level `cache_control` auto-placement; a no-op for providers that cache implicitly or not at all. 5. **Agent loop hooks** — `WithMaxStepsFunc` (dynamic ceiling, consulted every step, for supervisor budget adjustment), `WithSteer` (per-run message injection drained before each step), `WithCompactor` (pre-Generate transcript transformation; errors fall back to the original — losing a request to a broken summarizer is worse than a long prompt), `WithToolErrorLimits` (consecutive all-error steps and identical-call repeats end the run with `ErrToolLoop` + partial result). The canonical transcript in `Result.Messages` is always the uncompacted truth; compaction affects only what is sent. 6. **Manual health controls** — `Tracker.Bench/Unbench/Snapshot` for ops surfaces (".failover bench" commands, dashboards). 7. **`ChainConfig.Observer`** — one synchronous callback per failover decision (failed attempt with classification, bench, benched-skip). This is a hook, not an observability stack; persistence/metrics remain the consumer's business (anti-creep guardrail intact). ## Consequences - mort's tier resolver, `.failover` admin surface, failover-event log, run-critic budget control, steering, and compaction all rebase onto public API. - The agent loop gains supervision points without changing its never-panic, partial-result-on-error contract.