Orchestration
The Orchestrator<P> coordinates multiple specialized agents. It is itself an AgentRunner equipped with two delegation tools that dispatch work to sub-agents.
Flat Hierarchy
Section titled “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 avoids unbounded recursion.
Orchestrator / | \ Agent A Agent B Agent C <-- sub-agents (leaf nodes)Two Delegation Tools
Section titled “Two Delegation Tools”delegate_task
Section titled “delegate_task”Dispatches independent parallel subtasks to one or more sub-agents. Each sub-agent works on its own task with no shared state. Results are collected and returned to the orchestrator.
Use delegate_task when subtasks don’t need to coordinate with each other.
form_squad
Section titled “form_squad”Creates a collaborative squad of sub-agents that share a Blackboard — a key-value store for inter-agent communication. Sub-agents can read and write to the blackboard during execution.
Use form_squad when subtasks need to build on each other’s work. After each sub-agent completes, its result is automatically written to the blackboard under "agent:{name}".
Building an Orchestrator
Section titled “Building an Orchestrator”use std::sync::Arc;use heartbit::Orchestrator;
let mut orchestrator = Orchestrator::builder(provider.clone()) .sub_agent("researcher", "Research specialist", "You research topics thoroughly.") .sub_agent("writer", "Writing specialist", "You write clear, engaging content.") .on_text(Arc::new(|text| print!("{text}"))) .build()?;
let output = orchestrator.run("Write an article about Rust").await?;The orchestrator’s LLM decides which sub-agents to invoke, what tasks to give them, and whether to use delegate_task or form_squad.
Routing Modes
Section titled “Routing Modes”| Mode | Behavior |
|---|---|
| Auto | Orchestrator decides whether to delegate or handle directly |
| AlwaysOrchestrate | Always routes through sub-agents |
| SingleAgent | Bypasses orchestration, runs a single agent directly |
When the config contains only one agent, Heartbit automatically uses the single-agent fast path — it creates an AgentRunner directly, skipping orchestrator overhead entirely.
Per-Agent Providers
Section titled “Per-Agent Providers”Each sub-agent can use a different LLM model. This lets you assign expensive models to complex tasks and cheaper models to simpler ones:
[provider]name = "anthropic"model = "claude-sonnet-4-20250514"
[[agents]]name = "researcher"description = "Deep research"system_prompt = "You research thoroughly."
[[agents]]name = "summarizer"description = "Quick summaries"system_prompt = "You write concise summaries."provider = { name = "anthropic", model = "claude-haiku-4-5-20251001" }Blackboard
Section titled “Blackboard”The Blackboard is a shared Key -> Value store available to squad agents. It provides three tools:
| Tool | Description |
|---|---|
blackboard_read | Read a value by key |
blackboard_write | Write a value to a key |
blackboard_list | List all keys |
The default implementation (InMemoryBlackboard) uses a tokio::sync::RwLock<HashMap> for concurrent access.
OrchestratorBuilder Options
Section titled “OrchestratorBuilder Options”| Method | Description |
|---|---|
.sub_agent(name, desc, prompt) | Add a sub-agent with default provider |
.sub_agent_full(config) | Add a sub-agent with full configuration |
.on_text(cb) | Streaming text callback |
.on_event(cb) | Structured event callback |
.on_approval(cb) | Human-in-the-loop callback |
.blackboard(bb) | Provide a custom Blackboard implementation |
.shared_memory(m) | Enable shared memory for the orchestrator |
.allow_shared_write(bool) | Control institutional memory write access |
Configuration
Section titled “Configuration”[orchestrator]max_turns = 50routing = "auto" # auto | always_orchestrate | single_agent
[[agents]]name = "researcher"description = "Research specialist"system_prompt = "You are a research specialist."max_turns = 30
[[agents]]name = "writer"description = "Writing specialist"system_prompt = "You are a writing specialist."max_turns = 20