use molo::agent::{Agent, MessageChunk};
use molo::provider::{FakeProvider, FakeReply};
use molo::tool::{ToolError, ToolRegistry};
use molo::{ToolCall, Usage, react_agent};
use futures::StreamExt;
use schemars::JsonSchema;
use serde::Deserialize;
use tracing_subscriber::EnvFilter;
use tracing_subscriber::fmt::format::FmtSpan;
#[derive(Debug, Deserialize, JsonSchema)]
struct AddArgs {
a: i32,
b: i32,
}
#[molo::tool(description = "Adds two integers")]
async fn add(args: AddArgs) -> Result<String, ToolError> {
Ok((args.a + args.b).to_string())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::new("molo=debug"))
.with_span_events(FmtSpan::FULL)
.init();
let mut registry = ToolRegistry::new();
registry.register(Add);
let fake = FakeProvider::new([
FakeReply::WithUsage {
reply: Box::new(FakeReply::ToolCalls {
content: "".into(),
calls: vec![ToolCall {
id: "c1".into(),
name: "add".into(),
arguments: r#"{"a":1,"b":2}"#.into(),
}],
}),
usage: Usage::new(10, 2),
},
FakeReply::text_with_usage("the answer is 3", Usage::new(20, 5)),
FakeReply::text_with_usage("calculated again", Usage::new(5, 3)),
FakeReply::text_with_usage("anything else", Usage::new(2, 1)),
]);
let mut agent = react_agent!(fake, registry, "You are a math assistant");
println!("== non-streaming run ==");
agent.run("what is 1+2?").await?;
println!("== streaming run ==");
let mut stream = agent.run_stream("calculate again").await?;
while let Some(event) = stream.next().await {
if let MessageChunk::Delta(text) = event? {
print!("{text}");
}
}
println!();
drop(stream);
println!("== third run ==");
agent.run("anything else?").await?;
Ok(())
}