Skip to main content
Tool contracts: result shape, definition, registry, and runtime (§10). Tools are narrow, typed, and self-describing. The runtime validates every call (known name, well-formed input) before executing; model-correctable errors come back as ToolResult(success=False, error=...) — recoverable feedback for the model, never an exception thrown at the loop (§10 retry semantics).

Classes

ToolDefinition

A registered tool: its schema, handler, the phases it is active in, and tier (§10). paths self-declares which of the tool’s validated inputs are filesystem paths (§11, Phase 2.5). The permission gate runs confinement + the sensitive-path denylist over them centrally, so the policy can’t drift across tools. The default is a pass-through (no paths) — only path-bearing tools override it.

ToolDefinition.paths(_args)

No description.

ToolRegistry

The set of available tools, queryable by name and by active phase (§10).

ToolRegistry.active_for_phase(self, phase: str) -> list[ToolDefinition]

Return the tools enabled in the given phase (§10/§21 capability groups). Args: phase: The phase to filter active tools by. Returns: The tool definitions whose phases include phase.

ToolRegistry.admitted_for(self, phase: str, task_kind: str) -> list[ToolDefinition]

Return the tools the runner will admit in phase for task_kind (§2.6). Like active_for_phase, but also includes the edit-intent bootstrap, so the model is advertised exactly what the runner’s gate would let it execute — notably str_replace from investigating on an edit task. Args: phase: The phase to filter by. task_kind: The task’s kind, gating the edit-intent bootstrap. Returns: The tool definitions admitted in phase for task_kind.

ToolRegistry.get(self, name: str) -> ToolDefinition | None

Return the tool registered under name, or None if unknown. Args: name: The tool name to look up. Returns: The matching ToolDefinition, or None if no tool is registered under name.

ToolRegistry.register(self, tool: ToolDefinition) -> None

Add (or replace) a tool definition by name. Args: tool: The tool definition to register, keyed by its name.

ToolResult

The typed outcome of one tool call; the model only ever sees content (§10).
Fields

ToolRuntime

Validates and dispatches tool calls; never raises into the loop (§10). Args: registry: The registry to resolve tool calls against. deps: The run-scoped RunDeps passed to every handler.

ToolRuntime.execute(self, name: str, raw_input: dict) -> ToolResult

Resolve, validate, and run a tool call; errors return as a failed ToolResult. Args: name: The registered name of the tool to invoke. raw_input: The unvalidated call arguments, validated against the tool’s input model. Returns: The handler’s ToolResult, or a failed one for an unknown name, invalid input, or a handler that raised (isolated so a buggy tool never crashes the run).

Functions

admits_transient_edit(task_kind: str, tool: ToolDefinition) -> bool

Whether tool is admitted as a transient edit in an investigate task (ADR-0005). Investigation sometimes instruments: add a debug print, run, observe, revert. Tier-1 mutation is therefore legal in investigate tasks — the enforcement point is the verifier’s unchanged net-zero-diff contract (no_unintended_diff: the tree must match the pinned baseline at verification), detection where prevention used to be. An explicit rule, distinct from is_edit_intent, so the edit-intent phase bootstrap stays edit-kinds-only and investigate’s phase flow is unchanged. Args: task_kind: The task’s kind; only investigate rides this rule. tool: The resolved tool definition. Returns: True when tool is the mutating tier (1) and the task is an investigation.

is_edit_intent(task_kind: str, tool: ToolDefinition) -> bool

Whether tool is the model’s edit intent: the mutating tier on an edit-shaped task. Deliberately edit-kinds-only: an investigate task’s transient edits (ADR-0005) are admitted by admits_transient_edit instead, so they never ride this bootstrap and never advance the phase. Args: task_kind: The task’s kind (only edit/test_only permit mutation, §7). tool: The resolved tool definition. Returns: True when tool is the mutating tool (tier 1) and the task kind permits edits.

phase_admits_tool(phase: str, task_kind: str, tool: ToolDefinition) -> bool

Whether tool may run and be advertised in phase for task_kind (§2.6). The single source of truth shared by the runner’s gate (what may execute) and the ContextBuilder (what the model is told it may call) — keeping them in lockstep so the model never loops blind on a tool the runner would have admitted. True when the tool is active in the phase, or it is the edit-intent tool reachable from investigating via the bootstrap exception, or it is a transient edit in an investigate task (ADR-0005). Args: phase: The current control phase. task_kind: The task’s kind, gating the edit-intent bootstrap and the transient-edit rule. tool: The resolved tool definition. Returns: True if phase is in the tool’s phases, or tool is an edit-intent tool on an edit-shaped task (the bootstrap that surfaces str_replace from investigating), or tool is tier-1 on an investigate task (transient instrumentation, ADR-0005). The escalation tool is the one narrowing rule: investigate-only (ADR-0048).