Skip to content

Multi-Agent Orchestrator

This example demonstrates Heartbit’s orchestrator pattern. An orchestrator coordinates multiple specialized sub-agents — a researcher and a writer — that collaborate through delegation to produce a polished result.

  • ANTHROPIC_API_KEY environment variable set with a valid API key
Terminal window
export ANTHROPIC_API_KEY="sk-..."
cargo run -p heartbit --example multi_agent
use std::sync::Arc;
use heartbit::{AnthropicProvider, Orchestrator};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key =
std::env::var("ANTHROPIC_API_KEY").expect("set ANTHROPIC_API_KEY environment variable");
let provider = Arc::new(AnthropicProvider::new(api_key, "claude-sonnet-4-20250514"));
let mut orchestrator = Orchestrator::builder(provider)
.sub_agent(
"researcher",
"Finds facts and data on a topic",
"You are a research assistant. Find key facts and return them as bullet points.",
)
.sub_agent(
"writer",
"Writes polished prose from notes",
"You are a writer. Turn bullet-point notes into a short, polished paragraph.",
)
.max_turns(5)
.max_tokens(4096)
.build()?;
let output = orchestrator
.run("Write a short paragraph about the Rust programming language.")
.await?;
println!("{}", output.result);
eprintln!(
"[total tokens: {} in / {} out]",
output.tokens_used.input_tokens, output.tokens_used.output_tokens
);
Ok(())
}

Orchestrator builderOrchestrator::builder(provider) creates a builder that accepts sub-agent definitions. Each sub_agent() call takes three arguments:

  1. A name (used for delegation and logging)
  2. A description (tells the orchestrator what this agent is good at)
  3. A system prompt (shapes the sub-agent’s behavior)

Sub-agent roles — The orchestrator has a built-in delegate_task tool. When it receives a task, it decides which sub-agent to delegate to based on the descriptions:

  • researcher — finds facts and returns structured data
  • writer — transforms raw notes into polished prose

Execution floworchestrator.run("...") kicks off the orchestration loop:

  1. The orchestrator reads the user request
  2. It delegates to the researcher to gather facts
  3. It delegates to the writer with the researcher’s output
  4. It returns the final polished result

Token trackingoutput.tokens_used accumulates tokens across all sub-agent calls, giving you total cost visibility.

Flat hierarchy — Heartbit enforces a flat agent hierarchy: the orchestrator spawns sub-agents, but sub-agents never spawn further agents. This keeps execution predictable and debuggable.

The orchestrator coordinates both agents and returns a polished paragraph about Rust, followed by aggregate token usage:

Rust is a systems programming language focused on safety, speed, and concurrency...
[total tokens: 1250 in / 380 out]