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}