pub trait AgentTool:
Send
+ Sync
+ 'static {
Show 14 methods
// Required methods
fn name(&self) -> &str;
fn description(&self) -> &str;
fn parameters_schema(&self) -> Value;
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
call_id: &'life1 str,
args: Value,
signal: CancellationToken,
update: ToolUpdateSink,
) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Provided methods
fn requires_exclusive_sandbox(&self) -> bool { ... }
fn max_result_chars(&self) -> Option<usize> { ... }
fn history_policy(&self) -> ToolHistoryPolicy { ... }
fn identity_policy(&self) -> ToolIdentityPolicy { ... }
fn aborts_siblings_on_error(&self) -> bool { ... }
fn counts_toward_tool_call_limit(&self) -> bool { ... }
fn parallel_safe_per_turn(&self) -> bool { ... }
fn counts_toward_termination_vote(&self) -> bool { ... }
fn prepare_arguments(&self, args: Value) -> Value { ... }
fn validate(&self, _args: &Value) -> Result<(), ToolValidationError> { ... }
}Expand description
A tool the agent can call.
Implementations supply: name, description, JSON schema for arguments,
optional argument prep + validation, and an async execute.
Required Methods§
fn name(&self) -> &str
fn description(&self) -> &str
Sourcefn parameters_schema(&self) -> Value
fn parameters_schema(&self) -> Value
JSON Schema for the tool’s arguments. The loop hands this verbatim to the LLM provider.
Sourcefn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
call_id: &'life1 str,
args: Value,
signal: CancellationToken,
update: ToolUpdateSink,
) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
call_id: &'life1 str,
args: Value,
signal: CancellationToken,
update: ToolUpdateSink,
) -> Pin<Box<dyn Future<Output = Result<ToolResult, ToolError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Execute the tool. Returns the final result.
update may be used to publish partial progress while running.
Honor signal for cancellation.
Provided Methods§
Sourcefn requires_exclusive_sandbox(&self) -> bool
fn requires_exclusive_sandbox(&self) -> bool
Whether this tool needs exclusive access to the shared sandbox state — a single browser/desktop session, a persistent terminal, the workspace cwd, etc. When ANY tool in a batch declares this, the entire batch runs sequentially.
The canonical (and currently only) per-tool knob for forcing sequential dispatch. If a future use case needs sequential for a non-sandbox reason (rate-limited external API, host-process state, etc.), introduce a more specific signal then — keep this trait surface narrow until the case actually appears.
For loop-wide sequential mode (e.g. deterministic eval), use
crate::config::AgentBuilder::default_execution_mode instead.
Default: false (stateless / read-only tools).
Sourcefn max_result_chars(&self) -> Option<usize>
fn max_result_chars(&self) -> Option<usize>
Maximum size of this tool’s result content (in chars) that
ToolResultBudget allows through to the model on subsequent
turns. None means “use the global default”; Some(usize::MAX)
means “this tool’s output is too important to clip — keep
verbatim”. Some(n) declares a tool-specific cap that overrides
the global default.
Tools that produce large structured output the model needs to
inspect in full (publish results, full-page snapshots) should
return Some(usize::MAX). Tools that produce voluminous and
re-fetchable content (shell, file_read, browser body) should
usually leave this at the default.
Has no effect when ToolResultBudget isn’t installed in the
loop’s ContextTransform chain.
Sourcefn history_policy(&self) -> ToolHistoryPolicy
fn history_policy(&self) -> ToolHistoryPolicy
Tool-owned hints for history transforms. Defaults to no special handling; tools that emit re-fetchable or summary-worthy results opt in where their argument contract is defined.
Sourcefn identity_policy(&self) -> ToolIdentityPolicy
fn identity_policy(&self) -> ToolIdentityPolicy
Tool-owned identity declaration for loop-detection plugins. A
tool that dispatches on action / mode / similar declares
the discriminator here so the runtime never has to re-encode
the same fact in a separate allowlist. See
clark_agent::tool_identity for the contract; defaults to
“single opaque operation” which preserves the historical
fall-through behavior for tools that opt out.
Sourcefn aborts_siblings_on_error(&self) -> bool
fn aborts_siblings_on_error(&self) -> bool
Whether a non-fatal failure of this tool in a parallel batch
should cancel its still-running sibling tools. Default false
— failures are isolated and siblings run to completion. Tools
where one failure makes parallel work meaningless (a shell
step that gates npm test, a delegated build whose result the
siblings depend on) opt in by overriding this to true.
Cancelled siblings produce a ToolResult with
is_error: true, content: "aborted because sibling 'X' failed"
— they remain context events the next turn can react to, never
LoopErrors. Sibling-abort therefore never ends the run on its
own; the unanimous-vote termination rule is preserved.
Cancellation is cooperative: tools must check
signal.is_cancelled() (or wrap blocking work in select!) to
honor the cancel promptly. Subprocess-based tools should rely
on Drop killing the child when the future is dropped.
Sourcefn counts_toward_tool_call_limit(&self) -> bool
fn counts_toward_tool_call_limit(&self) -> bool
Whether this tool consumes a slot from
LoopConfig::max_tool_calls_per_turn.
Default true: tools do work, ask/answer, mutate state, or otherwise
participate in the loop’s bounded execution budget. Lightweight
progress-only signals can opt out so they do not starve the next real
action when a provider emits a status note and a work tool in the same
assistant turn.
Sourcefn parallel_safe_per_turn(&self) -> bool
fn parallel_safe_per_turn(&self) -> bool
Whether this tool is safe to invoke multiple times in a single assistant turn alongside other tool calls.
Default false: tools serialize at the configured cap so writes
and stateful operations stay sequenced. Read-only / idempotent
tools (web search, file read, grep, glob, snapshots) override to
true so a provider that batches several independent lookups in
one turn does not get N-1 of them rejected with a “only the first
call can run” error. Parallel-safe tools still execute one at a
time on the runtime side; they just do not contend for the
per-turn cap.
Sourcefn counts_toward_termination_vote(&self) -> bool
fn counts_toward_termination_vote(&self) -> bool
Whether this tool’s terminate vote is included in the
unanimous-vote tally that decides whether the batch ends the
run.
Default true: every tool’s vote counts. The batch terminates
only when every tool that opts in voted terminate: true.
Lightweight status-only tools (progress notes, hidden journals)
override to false. The runtime then ignores their vote
entirely — they are neither a “yes” nor a “no” — so a model that
emits a terminating delivery call alongside an advisory status
call in the same batch can still terminate. An all-advisory batch
(no tool with this flag set to true voted yes) does NOT
terminate, preserving the contract that progress notes never end
a run on their own.
Sourcefn prepare_arguments(&self, args: Value) -> Value
fn prepare_arguments(&self, args: Value) -> Value
Optional argument normalization before validation. Pure function. Default: identity.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
impl<T: TypedAgentTool> AgentTool for T
Blanket impl: every TypedAgentTool is automatically an AgentTool.
The schema is built with inline_subschemas = true because some
strict tool-schema validators (Azure, certain OpenAI-compatible
proxies) reject $ref chains in tool schemas. Inlining keeps the
generated JSON Schema flat and provider-portable.