pub struct ToolCtx {
pub workspace: PathBuf,
pub shell_timeout: Duration,
pub security: SecurityConfig,
pub output_budget_bytes: usize,
pub spill_dir: Option<PathBuf>,
pub events: Option<UnboundedSender<AgentEvent>>,
pub cancel: Option<CancellationToken>,
pub phase: Phase,
pub call_id: Option<String>,
pub taint: Option<Taint>,
}Expand description
What a tool is allowed to touch.
Fields§
§workspace: PathBufFilesystem tools refuse paths outside this root.
shell_timeout: Duration§security: SecurityConfig§output_budget_bytes: usizeThe byte budget one turn’s tool results share, divided equally across the calls in the batch so one runaway tool cannot starve its siblings (mecha executes a turn’s calls concurrently, so they land together). The old per-tool cap was 200 KB — ~50k tokens, 1.5× the whole local context window, which is not a cap so much as a promise to overflow.
spill_dir: Option<PathBuf>Where an oversized result is saved in full before its transcript copy
is cut. None disables spilling — the cut then names what was lost
instead of where to find it. Per-context on purpose: two eval cases
sharing one spill directory could read each other’s output through it.
events: Option<UnboundedSender<AgentEvent>>The run’s event channel, so a tool that contains a run — a subagent — can surface its progress instead of going dark until it returns.
Display-only, and treat it that way: any tool (including a third-party
MCP server’s) can send fabricated events down this channel, so nothing
that matters may key off it. Conversation state, taint, and run
completion all come from the loop and the caller’s join handle, never
from events. Stamped by Agent::run_in per run; None everywhere
nobody is watching (batch, eval).
cancel: Option<CancellationToken>The run’s cancellation token. A tool that contains a run passes it on,
so cancelling the parent actually cancels the child instead of politely
waiting out its entire run. Stamped by Agent::run_in, like events.
phase: PhaseThe run’s phase. A tool that contains a run passes it on, so delegation
is not the way to get a write executed from a planning run. Stamped by
Agent::run_in, like events.
call_id: Option<String>The tool_use id of the call this context was built for. Stamped per
dispatch (only when events is watched), so a tool that contains a
run can tag its forwarded events with the call that spawned it — two
subagents running in parallel are otherwise indistinguishable to a
renderer.
taint: Option<Taint>The conversation’s taint as of this turn, stamped per dispatch when a
mailbox is attached. The conservative pre-gate value — it includes
what the batch can return, so a read and a message_send in one
turn cannot stamp a clean label on the outgoing message. None means
nobody stamped it, and a consumer must fail closed (treat it as fully
tainted): a subagent’s context, or any run wired outside the loop,
must never pass as a clean sender by omission.
Implementations§
Source§impl ToolCtx
impl ToolCtx
Sourcepub fn with_workspace(&self, workspace: impl Into<PathBuf>) -> Self
pub fn with_workspace(&self, workspace: impl Into<PathBuf>) -> Self
The same policy pointed at a different root. Used to give one run — an eval case, a batch item — its own isolated copy of a workspace without rebuilding the agent around it. The spill directory is re-derived too: a re-rooted context is a new isolation domain, and inheriting the old one would let its runs read each other’s spilled output.