# Quick Start
## Basic Example with Anthropic
```rust
use yoagent::{Agent, AgentEvent, StreamDelta};
use yoagent::provider::AnthropicProvider;
use yoagent::tools::default_tools;
#[tokio::main]
async fn main() {
let mut agent = Agent::new(AnthropicProvider)
.with_system_prompt("You are a helpful coding assistant.")
.with_model("claude-sonnet-4-20250514")
.with_api_key(std::env::var("ANTHROPIC_API_KEY").unwrap())
.with_tools(default_tools());
let mut rx = agent.prompt("List the files in the current directory").await;
while let Some(event) = rx.recv().await {
match event {
AgentEvent::MessageUpdate { delta, .. } => match delta {
StreamDelta::Text { delta } => print!("{}", delta),
StreamDelta::Thinking { delta } => print!("[thinking] {}", delta),
_ => {}
},
AgentEvent::ToolExecutionStart { tool_name, .. } => {
println!("\nā Running tool: {}", tool_name);
}
AgentEvent::ToolExecutionEnd { tool_name, result, is_error, .. } => {
if is_error {
println!(" ā {} failed", tool_name);
} else {
println!(" ā {} done", tool_name);
}
}
AgentEvent::AgentEnd { .. } => {
println!("\n\nDone.");
}
_ => {}
}
}
}
```
## Example with OpenAI-Compatible Provider
For OpenAI, xAI, Groq, DeepSeek, Mistral, MiniMax, Z.ai, or any compatible API, use `OpenAiCompatProvider` with a `ModelConfig`:
```rust
use yoagent::{Agent, AgentEvent};
use yoagent::provider::OpenAiCompatProvider;
use yoagent::tools::default_tools;
#[tokio::main]
async fn main() {
let mut agent = Agent::new(OpenAiCompatProvider)
.with_system_prompt("You are a helpful assistant.")
.with_model("gpt-4o")
.with_api_key(std::env::var("OPENAI_API_KEY").unwrap())
.with_tools(default_tools());
let mut rx = agent.prompt("What is 2 + 2?").await;
while let Some(event) = rx.recv().await {
match event {
AgentEvent::MessageUpdate { delta, .. } => {
if let yoagent::StreamDelta::Text { delta } = delta {
print!("{}", delta);
}
}
AgentEvent::AgentEnd { .. } => println!(),
_ => {}
}
}
}
```
## Real-Time Streaming
`agent.prompt()` spawns the agent loop concurrently and returns a receiver immediately, so events stream in real-time as they're produced. For cases where you want to provide your own channel (e.g., to share a sender across tasks), use `prompt_with_sender()`:
```rust
use yoagent::{Agent, AgentEvent, StreamDelta};
use yoagent::provider::AnthropicProvider;
use yoagent::tools::default_tools;
#[tokio::main]
async fn main() {
let mut agent = Agent::new(AnthropicProvider)
.with_system_prompt("You are a helpful assistant.")
.with_model("claude-sonnet-4-20250514")
.with_api_key(std::env::var("ANTHROPIC_API_KEY").unwrap())
.with_tools(default_tools());
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
// Consume events in real-time on a separate task
tokio::spawn(async move {
while let Some(event) = rx.recv().await {
match event {
AgentEvent::MessageUpdate { delta, .. } => {
if let StreamDelta::Text { delta } = delta {
print!("{}", delta);
}
}
AgentEvent::AgentEnd { .. } => println!(),
_ => {}
}
}
});
// This blocks until the loop finishes; state is restored automatically
agent.prompt_with_sender("What is 2 + 2?", tx).await;
// Agent is ready for another prompt immediately
let _rx = agent.prompt("Follow up question").await;
}
```
## Using the Low-Level API
For more control, use `agent_loop()` directly:
```rust
use yoagent::agent_loop::{agent_loop, AgentLoopConfig};
use yoagent::provider::AnthropicProvider;
use yoagent::types::*;
use tokio::sync::mpsc;
use tokio_util::sync::CancellationToken;
#[tokio::main]
async fn main() {
let (tx, mut rx) = mpsc::unbounded_channel();
let cancel = CancellationToken::new();
let mut context = AgentContext {
system_prompt: "You are helpful.".into(),
messages: Vec::new(),
tools: yoagent::tools::default_tools(),
};
let config = AgentLoopConfig {
provider: std::sync::Arc::new(AnthropicProvider),
model: "claude-sonnet-4-20250514".into(),
api_key: std::env::var("ANTHROPIC_API_KEY").unwrap(),
thinking_level: ThinkingLevel::Off,
max_tokens: None,
temperature: None,
model_config: None,
convert_to_llm: None,
transform_context: None,
get_steering_messages: None,
get_follow_up_messages: None,
context_config: None,
compaction_strategy: None,
execution_limits: None,
cache_config: CacheConfig::default(),
tool_execution: ToolExecutionStrategy::default(),
retry_config: yoagent::RetryConfig::default(),
before_turn: None,
after_turn: None,
on_error: None,
input_filters: vec![],
};
let prompts = vec![AgentMessage::Llm(Message::user("Hello!"))];
let new_messages = agent_loop(prompts, &mut context, &config, tx, cancel).await;
// Drain events
while let Ok(event) = rx.try_recv() {
// handle events...
}
println!("Got {} new messages", new_messages.len());
}
```