use async_trait::async_trait;
use recursive::agent::Agent;
use recursive::llm::{Completion, MockProvider, ToolCall, ToolSpec};
use recursive::tools::{Tool, ToolRegistry};
use serde_json::{json, Value};
use std::sync::Arc;
struct Greeter;
#[async_trait]
impl Tool for Greeter {
fn spec(&self) -> ToolSpec {
ToolSpec {
name: "greet".into(),
description: "Greet a person by name".into(),
parameters: json!({
"type": "object",
"properties": {
"name": { "type": "string", "description": "The name to greet" }
},
"required": ["name"]
}),
}
}
async fn execute(&self, args: Value) -> recursive::Result<String> {
let name = args["name"].as_str().unwrap_or("world");
Ok(format!("Hello, {name}!"))
}
}
#[tokio::main]
async fn main() {
let tools = ToolRegistry::local().register(Arc::new(Greeter));
let provider = Arc::new(MockProvider::new(vec![
Completion {
content: "Let me greet you.".into(),
tool_calls: vec![ToolCall {
id: "call-1".into(),
name: "greet".into(),
arguments: json!({"name": "Alice"}),
}],
finish_reason: Some("tool_calls".into()),
usage: None,
},
Completion {
content: "I greeted Alice.".into(),
tool_calls: vec![],
finish_reason: Some("stop".into()),
usage: None,
},
]));
let mut agent = Agent::builder()
.llm(provider)
.tools(tools)
.system_prompt("You are a friendly assistant.")
.max_steps(5)
.build()
.expect("failed to build agent");
let outcome = agent.run("Greet Alice").await.expect("agent run failed");
println!("Final message: {:?}", outcome.final_message);
println!("Steps taken: {}", outcome.steps);
println!("Finish reason: {:?}", outcome.finish);
for msg in &outcome.transcript {
if msg.role == recursive::message::Role::Tool {
println!("Tool result: {}", msg.content);
}
}
}