rig_core/tool/portable.rs
1//! Context-free tool authoring contracts.
2//!
3//! Portable tools receive owned, deserialized arguments only. Runtime identity,
4//! authorization, mutable context, capability state, and lifecycle metadata
5//! remain outside the typed portable call boundary.
6//!
7//! ```
8//! use rig_core::tool::{PortableTool, tool_definition};
9//!
10//! struct Echo;
11//!
12//! impl PortableTool for Echo {
13//! const NAME: &'static str = "echo";
14//! type Args = serde_json::Value;
15//! type Output = serde_json::Value;
16//! type Error = std::convert::Infallible;
17//!
18//! fn description(&self) -> String {
19//! "Echo JSON".to_string()
20//! }
21//!
22//! fn parameters(&self) -> serde_json::Value {
23//! serde_json::json!({"type": "object"})
24//! }
25//!
26//! async fn call(&self, arguments: Self::Args) -> Result<Self::Output, Self::Error> {
27//! Ok(arguments)
28//! }
29//! }
30//!
31//! assert_eq!(tool_definition(&Echo).name, "echo");
32//! ```
33
34use serde::{Deserialize, Serialize};
35
36use crate::wasm_compat::{WasmCompatSend, WasmCompatSync};
37
38use super::{IntoToolOutput, ToolExecutionError};
39
40/// A context-free typed tool that can be executed by any Rig runtime.
41pub trait PortableTool: Sized + WasmCompatSend + WasmCompatSync {
42 /// Unique registration and provider-facing name.
43 const NAME: &'static str;
44 /// Owned JSON arguments.
45 type Args: for<'de> Deserialize<'de> + WasmCompatSend + WasmCompatSync;
46 /// Canonical model-visible output.
47 type Output: IntoToolOutput + WasmCompatSend;
48 /// Concrete author-facing failure.
49 type Error: std::error::Error + WasmCompatSend + WasmCompatSync + 'static;
50
51 /// Model-facing description.
52 fn description(&self) -> String;
53
54 /// JSON Schema for arguments.
55 fn parameters(&self) -> serde_json::Value;
56
57 /// Normalize a concrete failure at the runtime effect boundary.
58 fn map_error(&self, error: Self::Error) -> ToolExecutionError {
59 ToolExecutionError::from_error(error)
60 }
61
62 /// Execute one owned invocation without runtime access.
63 fn call(
64 &self,
65 arguments: Self::Args,
66 ) -> impl Future<Output = Result<Self::Output, Self::Error>> + WasmCompatSend;
67}
68
69/// A portable tool that can be embedded and reconstructed for discovery.
70pub trait PortableToolEmbedding: PortableTool {
71 /// Failure returned while reconstructing the typed implementation.
72 type InitError: std::error::Error + WasmCompatSend + WasmCompatSync + 'static;
73 /// Serializable reconstruction data.
74 type Context: for<'de> Deserialize<'de> + Serialize;
75 /// Runtime initialization state supplied by the authoring integration.
76 type State: WasmCompatSend;
77
78 /// Documents used by a discovery implementation.
79 fn embedding_docs(&self) -> Vec<String>;
80 /// Serializable reconstruction data.
81 fn context(&self) -> Self::Context;
82 /// Reconstruct the typed implementation.
83 fn init(state: Self::State, context: Self::Context) -> Result<Self, Self::InitError>;
84}
85
86#[cfg(test)]
87mod tests;