tinyhumansai/openhuman · error
agent ` ` is a `worker` tier and must not list ` ` in its…
Error message
agent `{parent}` is a `worker` tier and must not list `{child}` in its subagents — workers are leaf executors. What it means
Tier-hierarchy validation in the builtin agent loader: an agent whose agent_tier is worker must not declare any AgentId subagents, because workers are leaf executors with no open-ended spawn surface. The check runs over all loaded definitions including builtins; Skills wildcard entries are exempt since they collapse into a single delegation tool, and unknown child ids are deliberately not masked as tier errors (that is a separate subagents integrity concern).
Solutions
- Remove the subagents list from the worker definition, or
- change its agent_tier to a tier that is allowed to delegate.
- Reload definitions afterwards to confirm the registry validates cleanly.
Example fix
# before id = "my-worker" agent_tier = "worker" [[subagents]] id = "integrations_agent" # after (option A: leaf worker) id = "my-worker" agent_tier = "worker" # (no subagents) # after (option B: delegating tier) id = "my-worker" agent_tier = "standard"
Defensive patterns
Strategy: validation
Validate before calling
fn workers_have_no_agent_subagents(defs: &[AgentDefinition]) -> anyhow::Result<()> {
for def in defs {
if def.agent_tier == AgentTier::Worker
&& def.subagents.iter().any(|s| matches!(s, SubagentEntry::AgentId(_)))
{
anyhow::bail!("worker `{}` lists subagents", def.id);
}
}
Ok(())
} Prevention
- Run the same tier-hierarchy lint over custom agent TOMLs at authoring time, not just at loader startup.
- When copying an orchestrator template, strip its subagents if you downgrade the tier to worker.
- Remember Skills wildcard entries are exempt - only explicit AgentId entries violate the leaf rule.
When it happens
Trigger: A custom agent TOML sets agent_tier = "worker" while also listing subagents entries; a builtin's TOML is edited locally to add delegation to a worker-tier agent.
Common situations: Copying an orchestrator-style definition and only changing the tier to worker; authors assuming any agent may delegate.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- : missing `system_prompt` — custom definitions must set an…
- Proxy is enabled but no proxy URL is configured. Set at…
- proxy.scope='services' requires a non-empty proxy.services…
- Unsupported proxy service selector
- Unsupported runtime kind
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/7a6c5b81b33e277e.
Report an issue: GitHub.
Appendix: source
Thrown at src/openhuman/agent/registry/agents/loader.rs:410
/// agents that violate the contract fail the boot rather than crashing
/// at spawn time.
pub fn validate_tier_hierarchy(defs: &[AgentDefinition]) -> Result<()> {
let tier_by_id: HashMap<&str, AgentTier> =
defs.iter().map(|d| (d.id.as_str(), d.agent_tier)).collect();
for def in defs {
for entry in &def.subagents {
let child_id = match entry {
SubagentEntry::AgentId(id) => id.as_str(),
// Workflow wildcards always route to `integrations_agent`
// (a Worker) via a single collapsed delegation tool —
// not subject to the tier-mismatch rule.
SubagentEntry::Skills(_) => continue,
};
// Worker leaves: no open-ended spawn surface.
if def.agent_tier == AgentTier::Worker {
anyhow::bail!(
"agent `{parent}` is a `worker` tier and must not list `{child}` in its \
subagents — workers are leaf executors.",
parent = def.id,
child = child_id,
);
}
let Some(child_tier) = tier_by_id.get(child_id).copied() else {
// Unknown id — that's a separate `subagents` integrity
// concern (covered by existing tests / runtime spawn
// resolution); don't mask it as a tier error.
continue;
};
// Same-tier delegation is forbidden for chat and reasoning.
// (Chat→Chat would defeat the whole point of the fast tier;
// Reasoning→Reasoning produces a depth-blowing recursion of
// slow models.) The pair-rule lives in `validate_tier_transition`View on GitHub (pinned to 7491200858)