Skip to main content

agent_bridle_core/
tool.rs

1//! The [`Tool`] trait: a leashable capability.
2
3use async_trait::async_trait;
4
5use crate::{Caveats, ToolContext, ToolResult};
6
7/// A capability the agent can invoke, governed by the leash.
8///
9/// A tool declares the authority it needs via [`Tool::required`]; the
10/// [`crate::Gate`] confines the grant to `granted.meet(required)` and hands the
11/// tool a [`ToolContext`] minted from that meet. The tool can only act through
12/// the context's `check_*` methods, so it can never exceed what it declared or
13/// what the session was granted.
14#[async_trait]
15pub trait Tool: Send + Sync {
16    /// The dispatch name (the key in `tools/list` and in
17    /// [`crate::Registry::dispatch`]).
18    fn name(&self) -> &str;
19
20    /// The MCP `inputSchema` (JSON Schema) for this tool's arguments.
21    fn schema(&self) -> serde_json::Value;
22
23    /// The authority ceiling this tool promises to stay under.
24    ///
25    /// Defaults to [`Caveats::top`] — i.e. "I declare nothing special; confine
26    /// me entirely by the session grant." Because the gate hands the tool the
27    /// *meet* of granted-and-required, a `top` default means the tool runs under
28    /// exactly the granted caveats, while a narrower declaration tightens the
29    /// effective authority (and any future Landlock ruleset) even further. It is
30    /// a *ceiling*, not a demand: declaring authority the grant lacks is not an
31    /// error — the meet simply intersects it away, and per-operation
32    /// [`ToolContext`](crate::ToolContext) `check_*` calls deny at use.
33    fn required(&self) -> Caveats {
34        Caveats::top()
35    }
36
37    /// Run the tool. The `cx` proves the leash was passed; the tool enforces
38    /// per-operation policy by calling `cx.check_exec`, `cx.check_path_*`, etc.
39    async fn invoke(
40        &self,
41        args: serde_json::Value,
42        cx: &ToolContext,
43    ) -> ToolResult<serde_json::Value>;
44}