#[non_exhaustive]pub struct ToolContext<'a> {Show 14 fields
pub cwd: &'a Path,
pub cancel: CancellationToken,
pub fs: Arc<dyn FsBackend>,
pub shell: Arc<dyn ShellBackend>,
pub http: Arc<dyn HttpClient>,
pub current_model: &'a str,
pub current_provider: &'a str,
pub background: Option<BackgroundTasks>,
pub subagent_bridge: Option<SubagentBridge>,
pub policy: Option<Arc<dyn SandboxPolicy>>,
pub goal: Option<Arc<GoalState>>,
pub subagent_depth: u32,
pub session_tools: Option<Arc<dyn ToolRegistry>>,
pub parent_turn_config: Option<Arc<TurnConfig>>,
}Expand description
The execution environment injected into Tool::execute.
An explicit struct rather than environment variables or thread-locals, making it easy
to construct in tests and avoiding implicit global state. Fields are marked
non_exhaustive to allow future additions (sandbox handles, ACP backchannels, etc.)
without breaking existing implementations.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.cwd: &'a PathThe default working directory for the tool (typically the ACP session’s cwd).
cancel: CancellationTokenCancellation token: triggered by upstream session/cancel, user Ctrl+C, timeout,
etc.
Tool implementations should check cancel.is_cancelled() at long loops or await
points and exit as soon as possible.
fs: Arc<dyn FsBackend>Filesystem backend. The fs tool family (read_file / write_file /
edit_file) reads and writes files through it. During assembly, defect-acp
selects either LocalFsBackend or AcpFsBackend based on the client-negotiated
FileSystemCapabilities; tool implementations are completely unaware of this.
Uses Arc instead of a borrow: Tool::execute returns a 'static future /
stream, and tools typically clone the fs into async tasks. A borrow cannot
survive across .await.
shell: Arc<dyn ShellBackend>Shell execution backend. The bash tool uses it to create a terminal and run
commands; during assembly, defect-acp selects either LocalShellBackend or
AcpShellBackend based on the client-negotiated ClientCapabilities::terminal,
and tool implementations are unaware of the choice.
Same Arc trade-off as fs — Tool::execute returns a 'static future.
http: Arc<dyn HttpClient>HTTP fetch backend. The fetch tool uses it to perform network reads; it is set
up at the CLI entry point (constructed from HttpClientConfig as a process-level
HttpClient instance and reused). Tool implementations receive an Arc
clone; Tool::execute is a 'static future, so borrowing cannot survive across
await points.
current_model: &'a strThe model id selected for the current turn. Most tools do not need this; the
spawn_agent sub-agent tool uses it to “fall back the model to the parent
session’s current selection” — ToolContext does not carry a provider registry,
but carrying this string is enough for spawn_agent to call entry_for_model on
its own captured registry to resolve the provider the parent is currently using.
Populated from config.model by TurnRunner when
constructing the context.
current_provider: &'a strThe provider vendor selected for the current turn. Together with
Self::current_model this forms a (vendor, model) selection pair — when a
spawn_agent sub-agent falls back to the parent’s choice, it uses this pair to
call entry_for on the registry for exact resolution (avoiding provider
mis-selection when multiple gateways serve the same model name). An empty string
means the value was not injected (legacy/test paths); in that case spawn_agent
falls back to looking up the first entry by bare model id. Populated by the turn
runner from config.provider when constructing the context.
background: Option<BackgroundTasks>Session-level background task handle. When Some, tools can fire-and-forget a
task that outlives the current turn (primarily for spawn_agent { run_in_background: true }); None means the context does not support background
execution (e.g., nested sub-agent turns or tests), and tools should fall back to
synchronous execution.
Uses an owned Arc-backed handle instead of a borrow: Tool::execute returns a
'static future, and a borrow cannot survive across await. Injected by the
top-level TurnRunner when constructing the
context; not injected for nested sub-agent turns (structurally prevents background
tasks from spawning themselves).
subagent_bridge: Option<SubagentBridge>Subagent event bridge: when Some, a tool can wrap internally spawned sub-turn
events as crate::event::AgentEvent::Subagent and forward them back to the
parent session’s event stream for nested observability display. Currently only
used by spawn_agent. Injected by the turn runner in session::turn for each
tool according to its ToolCallId — injected for both top-level and nested
sub-agent turns (recursive bridging), with the mount point expressed by
SubagentBridge::parent_tool_call_id.
policy: Option<Arc<dyn SandboxPolicy>>The active sandbox policy for this turn snapshot. spawn_agent uses it to pass
the parent’s current real policy to child agents — after a session/set_mode
switch, newly created turns propagate the new policy through this field, so child
agents never see a stale process-level default. When None, spawn_agent falls
back to the policy captured at construction time (testing / uninjected scenarios).
Most tools ignore this field.
goal: Option<Arc<GoalState>>Shared state for the --goal goal-driven loop. When Some, this session runs in
goal mode; the goal_done tool calls crate::session::GoalState::mark_reached
to set the flag, and the goal-gate hook uses it to decide whether to release or
extend a turn when it voluntarily stops. None means non-goal mode (the default);
the goal_done tool is not registered and this field is never read.
subagent_depth: u32How many more layers of subagent can be dispatched from the current layer. The
top-level turn starts at the configured initial limit; spawn_agent decrements it
by one when injecting a nested turn for a child agent. 0 means the child agent
cannot obtain the spawn_agent tool (depth exhausted, structurally preventing
further recursion) — replacing the old hard-coded “whitelist never contains
spawn_agent”. This is a functional gate, unrelated to observability, so it is
independent of the optional Self::subagent_bridge and also takes effect in
test / no-bridge scenarios. Defaults to 0 (most conservative: no explicit
injection means no dispatch; the top-level turn must explicitly use
Self::with_subagent_depth).
session_tools: Option<Arc<dyn ToolRegistry>>The current session’s fully assembled tool pool — the CompositeRegistry that
already merged built-in tools with the per-session MCP tools. spawn_agent uses
this (rather than a static, MCP-free tool set captured at construction) to build a
child agent’s tool subset, so a subagent profile may allow mcp__* tools. None
in legacy / test paths, where spawn_agent falls back to its captured static pool.
Injected by the TurnRunner when constructing the
context.
parent_turn_config: Option<Arc<TurnConfig>>The current turn’s TurnConfig. spawn_agent uses it
so a child agent inherits the parent’s turn settings (compaction thresholds,
retry/concurrency limits, sampling incl. reasoning_effort, request-limit default)
instead of silently falling back to TurnConfig::default(). A profile may still
override individual fields. None in legacy / test paths, where spawn_agent uses
defaults. Injected by the TurnRunner.
Implementations§
Source§impl<'a> ToolContext<'a>
impl<'a> ToolContext<'a>
Sourcepub fn new(
cwd: &'a Path,
cancel: CancellationToken,
fs: Arc<dyn FsBackend>,
shell: Arc<dyn ShellBackend>,
http: Arc<dyn HttpClient>,
current_model: &'a str,
) -> Self
pub fn new( cwd: &'a Path, cancel: CancellationToken, fs: Arc<dyn FsBackend>, shell: Arc<dyn ShellBackend>, http: Arc<dyn HttpClient>, current_model: &'a str, ) -> Self
Constructs a minimal ToolContext. The #[non_exhaustive] attribute prevents
external crates from constructing the struct directly with a literal — this
constructor is the only cross-crate entry point. When adding new fields, add
default values to the signature or provide a new constructor to avoid breaking
existing call sites.
Sourcepub fn with_parent_turn_config(self, config: Arc<TurnConfig>) -> Self
pub fn with_parent_turn_config(self, config: Arc<TurnConfig>) -> Self
Inject the current turn’s TurnConfig so spawn_agent
can build a child config that inherits the parent’s turn settings. If not called,
spawn_agent falls back to TurnConfig::default() for non-explicit fields.
Sourcepub fn with_session_tools(self, tools: Arc<dyn ToolRegistry>) -> Self
pub fn with_session_tools(self, tools: Arc<dyn ToolRegistry>) -> Self
Inject the current session’s fully assembled tool pool (built-in + MCP composite).
spawn_agent uses it to build a child agent’s tool subset so subagent profiles can
allow mcp__* tools. If not called, session_tools is None and spawn_agent
falls back to the static pool captured at construction.
Sourcepub fn with_current_provider(self, vendor: &'a str) -> Self
pub fn with_current_provider(self, vendor: &'a str) -> Self
Inject the provider vendor selected for the current turn, forming a selection pair
with current_model.
If not called, defaults to an empty string (spawn_agent falls back to picking
the first entry by bare model id).
Sourcepub fn with_subagent_depth(self, depth: u32) -> Self
pub fn with_subagent_depth(self, depth: u32) -> Self
Inject the remaining subagent dispatch depth from this layer onward. The tool
driver for the top-level turn calls with the configured initial cap; spawn_agent
injects the decremented value for nested child-agent turns. If not called,
defaults to 0 (most conservative: no subagent dispatch allowed).
Sourcepub fn with_policy(self, policy: Arc<dyn SandboxPolicy>) -> Self
pub fn with_policy(self, policy: Arc<dyn SandboxPolicy>) -> Self
Inject the active sandbox policy for this turn snapshot. The top-level turn’s tool
driver uses this to pass the parent turn’s policy to spawn_agent; if not called,
policy is None (child agent nesting / testing), and spawn_agent falls back
to the policy captured at construction time.
Sourcepub fn with_background(self, background: BackgroundTasks) -> Self
pub fn with_background(self, background: BackgroundTasks) -> Self
Inject a session-level background task handle. The top-level turn’s tool driver
uses this to enable run_in_background; if not called, background is None
(the default for sub-agents / tests), and tools fall back to synchronous
execution.
Sourcepub fn with_goal(self, goal: Arc<GoalState>) -> Self
pub fn with_goal(self, goal: Arc<GoalState>) -> Self
Inject shared state for the --goal goal-driven loop. The goal_done tool sets
reached based on this state; if not called, goal is None (non-goal mode, the
default).
Sourcepub fn with_subagent_bridge(self, bridge: SubagentBridge) -> Self
pub fn with_subagent_bridge(self, bridge: SubagentBridge) -> Self
Inject a subagent event bridge. The tool driver injects one per tool call in
session::turn, keyed by ToolCallId, so that spawn_agent can nest child
turn events back into the parent trace.