ds_api/tool_trait.rs
1use crate::raw::request::tool::Tool as RawTool;
2use async_trait::async_trait;
3use serde_json::Value;
4
5/// The core trait that all agent tools must implement.
6///
7/// You should not implement this trait manually. Instead, annotate your `impl` block
8/// with the [`#[tool]`][ds_api_macros::tool] macro and write plain `async fn` methods —
9/// the macro generates the `raw_tools` and `call` implementations for you.
10///
11/// # What the macro generates
12///
13/// For each `async fn` in the annotated `impl`:
14/// - A [`RawTool`] entry (name, description from doc comment, JSON Schema from parameter types)
15/// is added to the `raw_tools()` vec.
16/// - A `match` arm in `call()` that deserialises each argument from the incoming `args` JSON,
17/// invokes the method, and serialises the return value via `serde_json::to_value`.
18///
19/// Any return type that implements `serde::Serialize` is accepted — `serde_json::Value`,
20/// plain structs with `#[derive(Serialize)]`, primitives, `Option<T>`, `Vec<T>`, etc.
21///
22/// # Example
23///
24/// ```no_run
25/// use ds_api::{DeepseekAgent, tool};
26/// use serde_json::{Value, json};
27///
28/// struct Calc;
29///
30/// #[tool]
31/// impl ds_api::Tool for Calc {
32/// /// Add two integers together.
33/// /// a: first operand
34/// /// b: second operand
35/// async fn add(&self, a: i64, b: i64) -> i64 {
36/// a + b
37/// }
38/// }
39///
40/// # #[tokio::main] async fn main() {
41/// let agent = DeepseekAgent::new("sk-...").add_tool(Calc);
42/// # }
43/// ```
44#[async_trait]
45pub trait Tool: Send + Sync {
46 /// Return the list of raw tool definitions to send to the API.
47 fn raw_tools(&self) -> Vec<RawTool>;
48
49 /// Invoke the named tool with the given arguments and return the result as a JSON value.
50 ///
51 /// When using the `#[tool]` macro you do not implement this method yourself —
52 /// the macro generates it. The generated implementation accepts any return type
53 /// that implements `serde::Serialize` (including `serde_json::Value`, plain
54 /// structs with `#[derive(Serialize)]`, primitives, etc.) and converts the
55 /// value to `serde_json::Value` automatically.
56 async fn call(&self, name: &str, args: Value) -> Value;
57}