tinyhumansai/openhuman · error

agent_id '{}' not found

Error message

agent_id '{}' not found

What it means

Thrown by the spawn_worker_thread tool when the requested agent_id is not present in the global AgentDefinitionRegistry. The registry holds builtin agent definitions plus any loaded custom ones; the lookup happens after the depth guard and before the parent allowlist check, so an allowlisted-but-unregistered id fails here while a registered-but-unallowlisted id fails the next check instead.

Source

Thrown at src/openhuman/agent/orchestration/tools/spawn_worker_thread.rs:194

            if is_delegated_label || current_thread.parent_thread_id.is_some() {
                tracing::warn!(
                    agent_id = %agent_id,
                    current_thread_id = %current_thread_id,
                    is_delegated_label,
                    has_parent_thread_id = current_thread.parent_thread_id.is_some(),
                    elapsed_ms = started.elapsed().as_millis() as u64,
                    "[spawn_worker_thread] depth guard blocked spawn from worker thread"
                );
                return Ok(ToolResult::error("Worker threads cannot spawn other worker threads. Depth is capped at 1. Use spawn_subagent for inline delegation instead."));
            }
        }

        let registry = AgentDefinitionRegistry::global()
            .ok_or_else(|| anyhow::anyhow!("AgentDefinitionRegistry not initialised"))?;

        let definition = registry
            .get(&agent_id)
            .ok_or_else(|| anyhow::anyhow!("agent_id '{}' not found", agent_id))?;

        if !parent.allowed_subagent_ids.contains(&definition.id) {
            tracing::warn!(
                parent_agent = %parent.agent_definition_id,
                requested_agent = %definition.id,
                allowed = ?parent.allowed_subagent_ids,
                "[spawn_worker_thread] blocked subagent outside parent allowlist"
            );
            return Ok(ToolResult::error(format!(
                "spawn_worker_thread: agent '{}' is not in parent agent '{}' subagents.allowlist",
                definition.id, parent.agent_definition_id
            )));
        }

        tracing::debug!(
            parent_agent = %parent.agent_definition_id,
            requested_agent = %definition.id,
            "[spawn_worker_thread] subagent allowlist check passed"

View on GitHub (pinned to a221052e0d)

Solutions

  1. List available agent definitions (registry / subagents surface) and use an exact id
  2. If custom: verify the agent definition file loads (correct dir, valid TOML/frontmatter) and re-check after startup
  3. If a builtin is missing, confirm the binary was built with the feature that registers it (e.g. skills)

Example fix

// before
spawn_worker_thread(agent_id = "reseacher") // typo, not registered

// after — resolve from the registry before invoking the tool
let registry = AgentDefinitionRegistry::global()
    .ok_or_else(|| anyhow!("AgentDefinitionRegistry not initialised"))?;
let def = registry.get(&agent_id)
    .with_context(|| format!("agent_id '{agent_id}' not found; known: {:?}", registry.ids()))?;
// then spawn def.id
Defensive patterns

Strategy: validation

Validate before calling

let registry = AgentDefinitionRegistry::global()
    .ok_or_else(|| anyhow!("AgentDefinitionRegistry not initialised"))?;
if registry.get(&agent_id).is_none() {
    // list registered ids, surface them, and stop before invoking spawn_worker_thread
}

Type guard

fn agent_registered(agent_id: &str) -> bool {
    AgentDefinitionRegistry::global().map_or(false, |r| r.get(agent_id).is_some())
}

Try / catch

match spawn_worker_thread(args).await {
    Ok(res) => Ok(res),
    Err(e) if e.to_string().contains("not found") => {
        // surface available agent ids to the caller/model so it can pick a valid one
        list_available_agents_and_retry(args)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Invoking the spawn_worker_thread tool with an agent_id that is not registered: a typo, a custom agent TOML that was never loaded, a builtin that is compiled out by a feature gate (e.g. skill_setup/skill_executor without the skills feature), or a definition removed between listing and spawn.

Common situations: Agent definition file not in the scanned agents directory or failing to parse; running a slim build where the agent's feature gate is off; renaming an agent id without updating prompts/tools that reference it.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/c9539f989869a7e7. Report an issue: GitHub.