Skip to main content

AgentTool

Trait AgentTool 

Source
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§

Source

fn name(&self) -> &str

Source

fn description(&self) -> &str

Source

fn parameters_schema(&self) -> Value

JSON Schema for the tool’s arguments. The loop hands this verbatim to the LLM provider.

Source

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§

Source

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).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

fn prepare_arguments(&self, args: Value) -> Value

Optional argument normalization before validation. Pure function. Default: identity.

Source

fn validate(&self, _args: &Value) -> Result<(), ToolValidationError>

Validate prepared arguments. Default: succeed. Implement for tools that have action-specific required fields not expressible in pure JSON Schema.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

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.