use wasm_agent::native::{tool_results_anthropic, tool_results_openai};
use wasm_agent::types::ToolResult;
use wasm_agent::{Agent, AgentConfig, NativeStep, ToolSpec};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut agent = Agent::new(AgentConfig { recover_from_errors: true, ..Default::default() });
agent.tools_mut().register(
ToolSpec::new(
"get_weather",
"Current weather for a city",
r#"{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}"#,
),
Box::new(|args: &str| {
let city = serde_json::from_str::<serde_json::Value>(args).ok().and_then(|v| v["city"].as_str().map(str::to_string));
match city {
Some(c) => ToolResult { tool_name: "get_weather".into(), output: format!("{c}: 18 C, light rain"), success: true },
None => ToolResult { tool_name: "get_weather".into(), output: "missing city".into(), success: false },
}
}),
)?;
println!("OpenAI tools: {}", serde_json::to_string(&agent.tools().openai_tools()?)?);
let openai = r#"{"choices":[{"message":{"role":"assistant","content":null,"tool_calls":[
{"id":"call_1","type":"function","function":{"name":"get_weather","arguments":"{\"city\":\"Paris\"}"}},
{"id":"call_2","type":"function","function":{"name":"get_wether","arguments":"{\"city\":\"Lyon\"}"}}]}}]}"#;
if let NativeStep::ToolCalls(results) = agent.step_response(openai)? {
println!("send back to OpenAI: {}", serde_json::to_string(&tool_results_openai(&results))?);
}
let anthropic = r#"{"content":[{"type":"text","text":"Checking."},
{"type":"tool_use","id":"toolu_1","name":"get_weather","input":{"city":"Lyon"}}],"stop_reason":"tool_use"}"#;
if let NativeStep::ToolCalls(results) = agent.step_response(anthropic)? {
println!("send back to Anthropic: {}", serde_json::to_string(&tool_results_anthropic(&results))?);
}
let done = r#"{"content":[{"type":"text","text":"Paris and Lyon: 18 C with light rain."}],"stop_reason":"end_turn"}"#;
if let NativeStep::Final(text) = agent.step_response(done)? {
println!("answer: {text}");
}
Ok(())
}