# How OpenHuman Sub-Agents (Planner, Researcher, Critic) Coordinate Task Execution

> Discover how OpenHuman's planner, researcher, and critic sub-agents collaborate using hierarchical delegation and isolated threads to efficiently execute tasks. Learn about dynamic tool generation and result aggregation.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: internals
- Published: 2026-05-12

---

**OpenHuman orchestrates planner, researcher, and critic sub-agents through a hierarchical delegation system where the orchestrator dynamically generates delegation tools, spawns isolated worker threads via `spawn_subagent`, and aggregates results through JSON-L session transcripts.**

The open-source OpenHuman framework implements a multi-agent architecture where specialized sub-agents collaborate under a central orchestrator. Understanding how these components coordinate reveals the engine behind OpenHuman's autonomous task execution pipeline according to the tinyhumansai/openhuman source code.

## The Orchestrator-Centric Coordination Model

OpenHuman treats the orchestrator as the primary routing and planning agent. Rather than hard-coding agent interactions, the system uses a declarative configuration combined with runtime tool generation to delegate tasks dynamically.

### Sub-Agent Declaration in TOML Configuration

The orchestrator's capabilities are defined statically in its configuration file. In [`src/openhuman/agent/agents/orchestrator/agent.toml`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/agents/orchestrator/agent.toml), a `subagents` array lists all child agents available for delegation:

```toml
subagents = ["planner", "researcher", "critic"]

```

Each entry maps to an `AgentDefinition` loaded from `src/openhuman/agent/agents/<name>/agent.toml`. This registry is parsed at startup to determine which delegation tools the orchestrator can invoke.

### Dynamic Tool Generation

The function `collect_orchestrator_tools` in [`src/openhuman/tools/orchestrator_tools.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/orchestrator_tools.rs) transforms the static TOML declarations into executable tools. For each sub-agent listed, it generates a tool named `delegate_<agent_id>` (e.g., `delegate_planner`, `delegate_researcher`, `delegate_critic`).

These generated tools are exposed to the orchestrator's LLM, allowing the model to invoke sub-agents using standard tool-calling syntax. The tool implementation routes requests through the unified `spawn_subagent` interface.

## Runtime Execution Flow

When the orchestrator decides to delegate a task, the coordination follows a strict three-phase pattern involving tool invocation, thread isolation, and session management.

### Phase 1: LLM Tool Invocation

The orchestrator's LLM constructs a tool call using the dynamically generated delegate tool. For example, to activate the planner, the LLM generates:

```json
{
  "name": "delegate_planner",
  "arguments": {
    "objective": "Create a research plan for quantum computing applications"
  }
}

```

This invocation is captured by the orchestrator's tool dispatcher and routed to the corresponding handler in [`src/openhuman/tools/impl/agent/spawn_subagent.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/agent/spawn_subagent.rs).

### Phase 2: Isolated Worker Thread Spawning

The `spawn_subagent` implementation creates a new OS worker thread via `spawn_worker_thread` (located in [`src/openhuman/tools/impl/agent/spawn_worker_thread.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/agent/spawn_worker_thread.rs)). This thread runs independently to prevent prompt contamination and allow agent-specific temperature or model configurations.

The function establishes a fresh session with a hierarchical key format: `{parent_key}__{child_key}`. If the orchestrator has session key `session_001`, the planner receives `session_001__planner`, ensuring deterministic lineage tracking.

### Phase 3: Session Hierarchy and Transcript Recording

During execution, the sub-agent writes to a JSON-L transcript file named according to the session hierarchy (e.g., `orchestrator__planner.jsonl`). The `SessionBuilder` and `SessionTranscript` modules in `src/openhuman/agent/harness/session/*.rs` manage these files, storing:

- Agent identification metadata
- Input parameters
- Generated outputs
- Completion timestamps

The parent orchestrator monitors the worker thread's return channel. Upon completion, the sub-agent returns a `ToolResult` containing the final output, which the orchestrator parses to determine subsequent steps, such as invoking the researcher or critic.

## Practical Coordination Example

The following Rust pseudo-code illustrates how the orchestrator sequentially coordinates the three sub-agents to process a complex query:

```rust
// Orchestrator receives user request
let user_input = "Analyze the latest climate research";

// Step 1: Delegate to planner
let plan = delegate_planner(json!({
    "task": user_input
})).await?;

// Step 2: For each research item in plan, spawn researcher
let findings = vec![];
for item in plan.subtasks {
    let data = delegate_researcher(json!({
        "query": item.topic
    })).await?;
    findings.push(data);
}

// Step 3: Validate findings with critic
let validation = delegate_critic(json!({
    "content": findings,
    "criteria": "accuracy_and_completeness"
})).await?;

// Final synthesis
if validation.score > 0.8 {
    return synthesize_response(findings);
}

```

Each `delegate_*` call internally triggers `spawn_subagent`, creating the hierarchical session chain: `orchestrator` → `planner` → `researcher` → `critic`.

## Summary

- **Declarative Registration**: Sub-agents are registered in [`src/openhuman/agent/agents/orchestrator/agent.toml`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/agents/orchestrator/agent.toml) and loaded as `AgentDefinition` structs at startup.
- **Dynamic Tool Fabrication**: `collect_orchestrator_tools` in [`src/openhuman/tools/orchestrator_tools.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/orchestrator_tools.rs) generates `delegate_<agent>` tools for runtime LLM invocation.
- **Thread Isolation**: `spawn_subagent` in [`src/openhuman/tools/impl/agent/spawn_subagent.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/agent/spawn_subagent.rs) launches each sub-agent in a dedicated worker thread to ensure execution isolation.
- **Hierarchical Auditing**: Session keys follow `{parent}__{child}` naming conventions, with JSON-L transcripts stored via `src/openhuman/agent/harness/session/*.rs` for full traceability.
- **Result Aggregation**: The orchestrator receives structured `ToolResult` objects from each sub-agent, enabling conditional routing between planner, researcher, and critic phases.

## Frequently Asked Questions

### How does the orchestrator decide which sub-agent to invoke?

The orchestrator relies on its system prompt and the dynamically generated `delegate_<agent>` tools exposed to its LLM. When processing a task, the LLM selects the appropriate tool based on the current objective—choosing `delegate_planner` for structuring work, `delegate_researcher` for information gathering, or `delegate_critic` for validation—according to the tool definitions generated in [`src/openhuman/tools/orchestrator_tools.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/orchestrator_tools.rs).

### What prevents sub-agents from interfering with each other's state?

Each sub-agent executes in a separate OS thread spawned by `spawn_worker_thread`, with independent memory spaces and session contexts. The session hierarchy enforces isolation through unique `SessionKey` identifiers (formatted as `parent__child`), ensuring that transcript writes and tool invocations remain namespace-separated across the planner, researcher, and critic agents.

### Can custom sub-agents be added to the coordination flow?

Yes. Adding a custom sub-agent requires creating a new directory under `src/openhuman/agent/agents/` with an [`agent.toml`](https://github.com/tinyhumansai/openhuman/blob/main/agent.toml) configuration and prompt implementation (e.g., [`prompt.rs`](https://github.com/tinyhumansai/openhuman/blob/main/prompt.rs)), then registering the agent name in the orchestrator's [`agent.toml`](https://github.com/tinyhumansai/openhuman/blob/main/agent.toml) `subagents` array. The `collect_orchestrator_tools` function automatically generates the corresponding `delegate_<custom_agent>` tool without requiring modifications to the core orchestration logic.

### Where are the conversation transcripts stored for debugging?

Transcripts are stored as JSON-L files in the session storage layer managed by `src/openhuman/agent/harness/session/*.rs`. Each sub-agent writes to a file named according to its hierarchical session key (e.g., `orchestrator__planner__researcher.jsonl`), providing a complete, replayable audit trail of the multi-agent coordination process.