Skip to main content

agent_engine/tools/
mod.rs

1//! Tool system — trait, registry, and built-in tool implementations.
2//!
3//! All tools implement the `Tool` trait and are registered in `ToolRegistry`.
4//! Subagents get `ToolRegistry::without_subagent()` to prevent recursion.
5use crate::Result;
6use serde_json::Value;
7use std::path::PathBuf;
8use std::sync::{Arc, Mutex};
9
10// ── Module declarations ──────────────────────────────────────────────────────────
11
12mod bash;
13mod edit;
14mod extension;
15mod find;
16mod grep;
17mod ls;
18mod read;
19mod secret_prompt;
20mod subagent;
21mod write;
22
23mod agent;
24mod registry;
25pub mod respond;
26pub mod send_channel;
27pub mod shell;
28pub(crate) mod util;
29pub mod watcher_exit;
30
31// ── Re-exports ──────────────────────────────────────────────────────────────────
32
33pub use crate::runtime::subagent::{
34    SubagentDisplayRow, SubagentHandle, SubagentRegistry, SubagentResult, SubagentState, SubagentStatus,
35};
36pub use agent::resolve_agent_prompt;
37pub use bash::BashTool;
38pub use edit::EditTool;
39pub use extension::ExtensionTool;
40pub use find::FindTool;
41pub use grep::GrepTool;
42pub use ls::LsTool;
43pub use read::ReadTool;
44pub use registry::ToolRegistry;
45pub use respond::RespondTool;
46pub use secret_prompt::SecretPromptQueue;
47pub use secret_prompt::{SecretPromptHandle, SecretPromptRequest};
48pub use send_channel::SendChannelTool;
49pub use shell::{ShellEndTool, ShellSendTool, ShellStartTool};
50pub use subagent::{
51    SubagentCollectTool, SubagentResumeTool, SubagentStartTool, SubagentStatusTool,
52    SubagentSteerTool, SubagentTool,
53};
54pub use watcher_exit::WatcherExitTool;
55pub use write::WriteTool;
56
57// Re-export util items used by sibling tool modules via `super::`
58pub(crate) use util::{expand_path, strip_ansi, NEXT_SUBAGENT_ID};
59
60// Facade: expose finalize internals for integration tests without making the
61// subagent module pub. Tests import `agent_engine::tools::{build_completion_event, finalize_subagent}`.
62#[doc(hidden)]
63pub use subagent::finalize::{build_completion_event, finalize_subagent};
64
65// ── Tool Trait ──────────────────────────────────────────────────────────────────
66
67/// Streaming channels — carry partial tool output and stream events.
68pub struct ToolChannels {
69    pub tx_delta: Option<tokio::sync::mpsc::UnboundedSender<String>>,
70    pub tx_events: Option<tokio::sync::mpsc::UnboundedSender<crate::StreamEvent>>,
71}
72
73/// Runtime capability handles — shared services a tool may require.
74pub struct ToolCapabilities {
75    pub watcher_exit_path: Option<PathBuf>,
76    pub tool_register_tx: Option<tokio::sync::mpsc::UnboundedSender<Vec<Arc<dyn Tool>>>>,
77    pub session_manager: Option<std::sync::Arc<crate::tools::shell::SessionManager>>,
78    pub subagent_registry: Option<Arc<Mutex<SubagentRegistry>>>,
79    pub event_queue: Option<Arc<crate::events::EventQueue>>,
80    pub secret_prompt: Option<SecretPromptHandle>,
81}
82
83/// Configuration limits and timeouts.
84pub struct ToolLimits {
85    /// Context-budget ceiling — final tool output entering history is truncated
86    /// to this. Applied AFTER the `after_tool_call` hook so compression
87    /// extensions see the FULL buffered output and can decide what to keep.
88    pub max_tool_output: usize,
89    /// Memory/pipe safety bound — the maximum bytes a tool may buffer
90    /// internally before truncating with a marker. Sized well above
91    /// `max_tool_output` so transform extensions are never starved.
92    pub max_tool_buffer: usize,
93    pub bash_timeout: u64,
94    pub bash_max_timeout: u64,
95    pub subagent_timeout: u64,
96}
97
98/// Context passed to tool execution — composition of channels, capabilities, and limits.
99pub struct ToolContext {
100    pub channels: ToolChannels,
101    pub capabilities: ToolCapabilities,
102    pub limits: ToolLimits,
103}
104
105/// The core trait for all tools. Implement this to add a new tool.
106#[async_trait::async_trait]
107pub trait Tool: Send + Sync {
108    /// Tool name as it appears in the API (e.g. "bash", "read").
109    fn name(&self) -> &str;
110
111    /// Human-readable description sent to the model.
112    fn description(&self) -> &str;
113
114    /// JSON Schema for the tool's parameters.
115    fn parameters(&self) -> Value;
116
117    /// Execute the tool with the given parameters.
118    async fn execute(&self, params: Value, ctx: ToolContext) -> Result<String>;
119
120    /// Owning extension id for tools registered by an extension. Built-in tools return `None`.
121    fn extension_id(&self) -> Option<&str> {
122        None
123    }
124}
125
126#[cfg(test)]
127mod test_helpers;