# How Agents Are Managed and Executed Within the OpenHuman Rust Core

> Discover how OpenHuman Rust core manages and executes agents. Learn about data-driven sub-processes, TOML specs, a global registry, and the spawn_subagent tool for isolated turn loops.

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

---

**The OpenHuman Rust core implements agents as data-driven sub-processes defined by TOML specifications, indexed in a global singleton registry, and executed through the `spawn_subagent` meta-tool which creates isolated turn loops that collapse their interaction history into singular tool results.**

In the OpenHuman framework, agents are not monolithic external services but composable, sandboxed sub-processes governed by declarative definitions. Understanding how agents are managed and executed within the OpenHuman Rust core reveals a lightweight architecture that enables dynamic tool filtering, prompt customization, and secure resource inheritance without spawning separate OS processes. The system leverages the `AgentDefinitionRegistry` and a dedicated sub-agent runner to orchestrate these workflows using the same Tokio-based turn machinery that powers parent agents.

## Agent Definitions and the Global Registry

At the heart of the system lies the **AgentDefinition** struct located in [`src/openhuman/agent/harness/definition.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/definition.rs). This structure encapsulates everything required to configure a sub-agent: its identifier, system prompt, target model, tool whitelist, runtime limits, and flags that control which parts of the parent prompt are omitted.

Built-in agent definitions are stored as TOML files within `src/openhuman/agent/registry/agents/…/agent.toml` and loaded at startup by the `definition_loader` in [`src/openhuman/agent/registry/agents/loader.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/registry/agents/loader.rs). Users can extend the system by placing custom definitions under `$OPENHUMAN_WORKSPACE/agents/*.toml`, which the loader discovers and ingests during initialization.

All definitions are indexed in the **AgentDefinitionRegistry**, a singleton accessible via `AgentDefinitionRegistry::global()`. This registry populates at core startup through `AgentDefinitionRegistry::init()` and enables runtime validation of `agent_id` requests across the entire system.

```rust
// Load a custom agent definition at runtime
let registry = AgentDefinitionRegistry::global().unwrap();
let my_def = registry
    .list()
    .iter()
    .find(|d| d.id == "researcher")
    .expect("definition missing");

```

## The spawn_subagent Meta-Tool

The harness constructs the parent agent’s tool list from the core tool catalog in [`src/openhuman/tools/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/mod.rs). Among these tools, the meta-tool **SpawnSubagentTool** (defined in [`src/openhuman/agent/orchestration/tools/spawn_subagent.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/orchestration/tools/spawn_subagent.rs)) serves as the entry point for agent delegation.

When a parent turn invokes this tool, the implementation performs several critical operations:

1. **Registry Lookup**: Validates the requested `agent_id` against the global registry.
2. **Tool Filtering**: Intersects the parent’s available tools with the sub-agent’s `tools` whitelist, excluding any listed in `disallowed_tools`.
3. **Prompt Construction**: Generates a narrow system prompt for the child based on the `AgentDefinition` configuration.

```rust
// Invoke a sub-agent from a parent turn
let tool = SpawnSubagentTool::new();
let args = json!({
    "agent_id": "researcher",
    "prompt": "Summarise the latest research papers on Rust async patterns.",
    "blocking": true
});
let result = tool.execute(args).await?;
println!("Sub-agent answer: {}", result.output());

```

## Sub-Agent Execution Flow

Execution is handled by the **sub-agent runner** located in `src/openhuman/agent/harness/subagent_runner/`. The entry point `run_subagent` receives the definition, prompt, optional context, and the parent’s provider, then determines the execution mode.

**Inline Execution**: Runs on the same Tokio task, suitable for simple, blocking operations.

**Async Worker Execution**: Creates a reusable worker (default) that persists beyond the initial call, enabling stateful interactions addressed via a `task_key`.

The dispatch flow follows this explicit path through the codebase:

- [`src/openhuman/agent/harness/session/turn/core.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/session/turn/core.rs) collects the tool call
- `SpawnSubagentTool::execute` initiates the request
- `run_subagent` delegates to [`subagent_runner/ops/runner.rs`](https://github.com/tinyhumansai/openhuman/blob/main/subagent_runner/ops/runner.rs)
- [`subagent_runner/ops/graph.rs`](https://github.com/tinyhumansai/openhuman/blob/main/subagent_runner/ops/graph.rs) builds the sub-agent’s turn graph
- [`subagent_runner/ops/runner.rs`](https://github.com/tinyhumansai/openhuman/blob/main/subagent_runner/ops/runner.rs) executes the graph
- Results are packaged into a `ToolResult` and returned to the parent

The sub-agent’s entire interaction loop—model calls, tool invocations, and policy checks—runs exactly like a normal turn, but its history collapses into a single result object.

```rust
// Create a reusable async worker addressable by task_key
let args = json!({
    "agent_id": "code_executor",
    "prompt": "Write a function that computes Fibonacci numbers.",
    "task_key": "fib_generator",
    "fresh": false   // reuse existing worker if present
});
let _ = tool.execute(args).await?;

```

## Security and Resource Boundaries

Sub-agents inherit the parent’s **security gate** ([`src/openhuman/agent/tinyagents/host/security_gate.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/tinyagents/host/security_gate.rs)) and **budget gate**, ensuring that sandboxing policies propagate downstream. However, sub-agents also respect their own specific limits defined in `AgentDefinition`:

- `max_iterations`: Caps the number of reasoning steps
- `timeout_secs`: Hard limit on execution duration
- `max_result_chars`: Restricts output payload size

The `iteration_policy` field, including `iteration_policy::Extended`, allows longer workflows when the default constraints prove too restrictive for complex tasks.

## Lifecycle and Persistence Management

The registry populates during core initialization and remains immutable during runtime. Sub-agent lifecycle management depends on the invocation mode:

- **Blocking calls**: State exists only for the duration of the turn; in-memory history is discarded immediately after result delivery.
- **Reusable workers**: When invoked with a `task_key` and `fresh: false`, the worker persists in memory and can be addressed later via [`src/openhuman/agent/orchestration/tools/spawn_worker_thread.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/orchestration/tools/spawn_worker_thread.rs).

This architecture ensures that agents remain **pure data objects**—composable, observable, and subject to the same logging and policy layers that protect the parent turn.

## Summary

- **AgentDefinition** structs in [`src/openhuman/agent/harness/definition.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/definition.rs) store complete sub-agent specifications as TOML-driven data objects.
- The **AgentDefinitionRegistry** singleton provides global access to agent definitions at runtime via `AgentDefinitionRegistry::global()`.
- **SpawnSubagentTool** in [`src/openhuman/agent/orchestration/tools/spawn_subagent.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/orchestration/tools/spawn_subagent.rs) filters parent tools and initiates sub-agent execution.
- The **sub-agent runner** reuses the core turn machinery in `src/openhuman/agent/harness/subagent_runner/` while isolating execution contexts.
- Sub-agents inherit parent security gates but respect their own `max_iterations`, `timeout_secs`, and `max_result_chars` limits.
- **Reusable async workers** persist via `task_key` references, while blocking executions clean up immediately after result return.

## Frequently Asked Questions

### How do I register a custom agent definition in OpenHuman?

Place a TOML file following the `AgentDefinition` schema in `$OPENHUMAN_WORKSPACE/agents/*.toml`. The `definition_loader` in [`src/openhuman/agent/registry/agents/loader.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/registry/agents/loader.rs) automatically discovers and registers these files during core startup, making them available through `AgentDefinitionRegistry::global()`.

### What is the difference between blocking and reusable sub-agent execution?

**Blocking execution** runs the sub-agent inline on the same Tokio task and discards its state immediately after returning the result. **Reusable execution** creates an async worker that persists in memory, allowing subsequent calls to reference the same state via a `task_key`, as implemented in [`src/openhuman/agent/orchestration/tools/spawn_worker_thread.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/orchestration/tools/spawn_worker_thread.rs).

### How does the parent agent's tool set get filtered for sub-agents?

The `SpawnSubagentTool::execute` method intersects the parent’s available tools from [`src/openhuman/tools/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/mod.rs) with the sub-agent’s `tools` whitelist, then removes any tools specified in `disallowed_tools`. This ensures sub-agents operate with the minimal necessary capability surface.

### Where are sub-agent execution limits enforced?

Limits defined in `AgentDefinition`—including `max_iterations`, `timeout_secs`, and `max_result_chars`—are enforced by the sub-agent runner in [`src/openhuman/agent/harness/subagent_runner/ops/runner.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/subagent_runner/ops/runner.rs). Additionally, the parent’s security and budget gates from [`src/openhuman/agent/tinyagents/host/security_gate.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/tinyagents/host/security_gate.rs) wrap the sub-agent execution context.