phi-core 0.8.0

Simple, effective agent loop with tool execution and event streaming
Documentation
//! Sub-agent example: a coordinator with two specialized sub-agents.
//!
//! Demonstrates:
//!   - Creating SubAgentTools with their own system prompts and tools
//!   - Registering sub-agents on a parent Agent via `with_sub_agent()`
//!   - The parent LLM decides when to delegate to sub-agents
//!
//! Run:
//!   ANTHROPIC_API_KEY=sk-... cargo run --example sub_agent

use phi_core::agents::SubAgentTool;
use phi_core::provider::ModelConfig;
use phi_core::tools;
use phi_core::BasicAgent;
use phi_core::*;

#[tokio::main]
async fn main() {
    let api_key = std::env::var("ANTHROPIC_API_KEY").expect("Set ANTHROPIC_API_KEY");
    let model = "claude-sonnet-4-20250514";

    // Sub-agent 1: a researcher with file reading tools
    let researcher = SubAgentTool::new(
        "researcher",
        ModelConfig::anthropic(model, "Claude Sonnet 4", &api_key),
    )
    .with_description(
        "Searches and reads files to gather information. Delegate research tasks here.",
    )
    .with_system_prompt(
        "You are a research assistant. Read files and summarize findings concisely.",
    )
    .with_tools(vec![
        std::sync::Arc::new(tools::ReadFileTool::new()),
        std::sync::Arc::new(tools::SearchTool::new()),
        std::sync::Arc::new(tools::ListFilesTool::new()),
    ])
    .with_max_turns(10);

    // Sub-agent 2: a coder with file editing tools
    let coder = SubAgentTool::new(
        "coder",
        ModelConfig::anthropic(model, "Claude Sonnet 4", &api_key),
    )
    .with_description("Writes and edits code files. Delegate coding tasks here.")
    .with_system_prompt("You are a coding assistant. Write clean, correct code. Be concise.")
    .with_tools(vec![
        std::sync::Arc::new(tools::ReadFileTool::new()),
        std::sync::Arc::new(tools::WriteFileTool::new()),
        std::sync::Arc::new(tools::EditFileTool::new()),
    ])
    .with_max_turns(15);

    // Parent agent: coordinates between sub-agents
    let mut agent = BasicAgent::new(ModelConfig::anthropic(model, "Claude Sonnet 4", &api_key))
        .with_system_prompt(
            "You are a coordinator agent. You have two sub-agents:\n\
             - 'researcher': for reading files and gathering information\n\
             - 'coder': for writing and editing code\n\n\
             Delegate tasks to the appropriate sub-agent. You can run both in parallel \
             when the tasks are independent.",
        )
        .with_sub_agent(researcher)
        .with_sub_agent(coder);

    println!("Coordinator agent with 2 sub-agents ready.");
    println!("Try: 'Read the README and then create a hello.py file'\n");

    let mut rx = agent
        .prompt("List the files in the current directory, then create a file called hello.txt with 'Hello from sub-agents!'")
        .await;

    while let Some(event) = rx.recv().await {
        match event {
            AgentEvent::MessageUpdate {
                delta: StreamDelta::Text { delta },
                ..
            } => {
                print!("{}", delta);
            }
            AgentEvent::ToolExecutionStart { tool_name, .. } => {
                eprintln!("\n  [calling: {}]", tool_name);
            }
            AgentEvent::ToolExecutionEnd { tool_name, .. } => {
                eprintln!("  [done: {}]", tool_name);
            }
            AgentEvent::AgentEnd { .. } => {
                println!("\n\n--- Done ---");
            }
            _ => {}
        }
    }
}