Skip to main content

basis/
tools.rs

1//! The tool contract's bindings that live in basis.
2//!
3//! ADR-0012 names three ways to reach one contract, mentra's `ExecutableTool`.
4//! Two of them are here:
5//!
6//! - [`spawn`] — basis's own tool, the **native** binding's only instance. ADR-0016
7//!   made it the model's only route to a command and to a subagent. It is
8//!   registered on every runtime [`RuntimeBuilder`](crate::RuntimeBuilder)
9//!   builds, and the two doors it replaces — mentra's `shell` and `task` —
10//!   leave the model's roster at the same time.
11//! - [`declared`] — the **subprocess** binding: `.basis/tools.json` declares a
12//!   name, a description, a JSON schema and a command, and basis wraps that
13//!   command as a tool speaking JSON over stdio. Registered per workspace, at
14//!   [`WorkspaceBuilder::open`](crate::WorkspaceBuilder::open), since a
15//!   manifest is a repository's data rather than a process's.
16//!
17//! The third is MCP (`crate::mcp`), which is mentra's client behind a cargo
18//! feature and registers nothing of basis's own.
19//!
20//! # The fourth: a host's own native tool
21//!
22//! [`RuntimeBuilder::with_tool`](crate::RuntimeBuilder::with_tool) registers a
23//! type the *embedding program* implements, in its own process — for a tool
24//! that needs context [`declared`]'s subprocesses cannot have: a client
25//! handle, a connection, which caller or conversation this call belongs to.
26//! Unlike [`declared`], nothing about the tool is data a repository reviews;
27//! the host's compiled code is the whole of what it does.
28//!
29//! What `with_tool` stores is a `Box<dyn ExecutableTool>`, handed whole to
30//! mentra's own by-value `RuntimeBuilder::with_tool` at
31//! [`build`](crate::RuntimeBuilder::build) time.
32//! [oops-rs/mentra#22](https://github.com/oops-rs/mentra/issues/22) closed
33//! the gap that once made that impossible: mentra implements `ToolDefinition`
34//! and `ToolExecutor` for `Box<T>` and `Arc<T>` (`T: ?Sized`) at the traits'
35//! owner, forwarding every method explicitly — `authorization_preview`
36//! included, the method a hand-written shim could silently drop and thereby
37//! present a host's tool to the approver as its static descriptor.
38//!
39//! Registered on the runtime, like `spawn` (ADR-0018's host scope): visible to
40//! every workspace and subagent that runtime opens, not to one session.
41//!
42//! Building one needs mentra's own tool-authoring types, re-exported below
43//! rather than left for a host to reach through basis to a `mentra`
44//! dependency it would otherwise have no reason to declare directly. The set
45//! mirrors exactly what [`spawn`]'s own `ExecutableTool` impl uses — proof
46//! it is complete enough to write a real tool against, not a guess at what
47//! one might need.
48
49pub mod declared;
50pub mod spawn;
51
52pub use mentra::tool::{
53    ExecutableTool, ParallelToolContext, RuntimeToolDescriptor, ToolApprovalCategory,
54    ToolAuthorizationPreview, ToolCapability, ToolContext, ToolDefinition, ToolDurability,
55    ToolExecutionCategory, ToolExecutor, ToolResult, ToolSideEffectLevel,
56};
57pub use spawn::{ChildContext, ChildSpec, DEFAULT_DELEGATION_DEPTH, SPAWN, SpawnTool};