Custom Tool
Using the #[tool] macro
The simplest way to create a tool:
use synwire_derive::tool;
use synwire_core::error::SynwireError;
/// Reverses the input string.
#[tool]
async fn reverse(text: String) -> Result<String, SynwireError> {
Ok(text.chars().rev().collect())
}
// Use: let tool = reverse_tool()?;
Using StructuredToolBuilder
For dynamic tool creation:
use synwire_core::tools::{StructuredTool, ToolOutput};
let tool = StructuredTool::builder()
.name("word_count")
.description("Counts words in text")
.parameters(serde_json::json!({
"type": "object",
"properties": {
"text": {"type": "string", "description": "Text to count"}
},
"required": ["text"]
}))
.func(|input| Box::pin(async move {
let text = input["text"].as_str().unwrap_or("");
let count = text.split_whitespace().count();
Ok(ToolOutput {
content: format!("{count} words"),
artifact: None,
})
}))
.build()?;
Implementing the Tool trait
For full control:
use synwire_core::tools::{Tool, ToolOutput, ToolSchema};
use synwire_core::error::SynwireError;
use synwire_core::BoxFuture;
struct HttpFetcher {
schema: ToolSchema,
}
impl HttpFetcher {
fn new() -> Self {
Self {
schema: ToolSchema {
name: "http_fetch".into(),
description: "Fetches a URL".into(),
parameters: serde_json::json!({
"type": "object",
"properties": {
"url": {"type": "string"}
},
"required": ["url"]
}),
},
}
}
}
impl Tool for HttpFetcher {
fn name(&self) -> &str { &self.schema.name }
fn description(&self) -> &str { &self.schema.description }
fn schema(&self) -> &ToolSchema { &self.schema }
fn invoke(
&self,
input: serde_json::Value,
) -> BoxFuture<'_, Result<ToolOutput, SynwireError>> {
Box::pin(async move {
let url = input["url"].as_str().unwrap_or("");
// Fetch URL...
Ok(ToolOutput {
content: format!("Fetched: {url}"),
artifact: None,
})
})
}
}
Returning artifacts
Tools can return both text content and structured artifacts:
Ok(ToolOutput {
content: "Found 3 results".into(),
artifact: Some(serde_json::json!([
{"title": "Result 1", "url": "https://example.com/1"},
{"title": "Result 2", "url": "https://example.com/2"},
{"title": "Result 3", "url": "https://example.com/3"},
])),
})