use llm_agent_runtime::agent::{AgentConfig, ReActLoop, ToolSpec};
use llm_agent_runtime::error::AgentRuntimeError;
use llm_agent_runtime::orchestrator::{CircuitBreaker, RetryPolicy};
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), AgentRuntimeError> {
let call_count = Arc::new(AtomicU32::new(0));
let call_count_clone = Arc::clone(&call_count);
let circuit_breaker = Arc::new(
CircuitBreaker::new("weather-api", 3, Duration::from_secs(1)).unwrap(),
);
let tool = ToolSpec::new_async(
"get_weather",
"Fetch current weather for a city. Required field: city",
move |args| {
let count = Arc::clone(&call_count_clone);
Box::pin(async move {
let n = count.fetch_add(1, Ordering::Relaxed);
if n < 2 {
serde_json::json!({ "error": "service temporarily unavailable" })
} else {
let city = args
.get("city")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
serde_json::json!({ "city": city, "temp_c": 22, "condition": "sunny" })
}
})
},
)
.with_required_fields(vec!["city".to_string()])
.with_circuit_breaker(circuit_breaker);
let config = AgentConfig::new(6, "my-model");
let mut loop_ = ReActLoop::new(config);
loop_.register_tool(tool);
let retry = RetryPolicy::exponential(4, 10).unwrap();
let mut attempt = 0u32;
let steps = loop {
attempt += 1;
let result = loop_
.run("What is the weather in London?", |_ctx: String| async {
if call_count.load(Ordering::Relaxed) < 2 {
"Thought: fetch weather\nAction: get_weather {\"city\":\"London\"}".to_string()
} else {
"Thought: got weather\nAction: FINAL_ANSWER It is sunny and 22°C in London.".to_string()
}
})
.await;
match result {
Ok(s) => break s,
Err(e) => {
if attempt >= retry.max_attempts {
return Err(e);
}
let delay = retry.delay_for(attempt);
println!("[attempt {attempt}] error: {e} — retrying after {delay:?}");
tokio::time::sleep(delay).await;
}
}
};
println!("Completed in {} steps ({attempt} attempt(s))", steps.len());
for (i, step) in steps.iter().enumerate() {
println!(
" Step {}: thought={:?} action={:?}",
i + 1,
step.thought,
step.action
);
}
Ok(())
}