{"record":{"id":"8196658072eee684","repo":"tinyhumansai/openhuman","slug":"agent-registry-rejected-after-merging-workspace-ov","errorCode":null,"errorMessage":"agent registry rejected after merging workspace overrides from {}: {}","messagePattern":"agent registry rejected after merging workspace overrides from (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/agent/harness/definition.rs","lineNumber":763,"sourceCode":"        let custom = super::definition_loader::load_from_workspace(workspace)?;\n        for def in custom {\n            tracing::info!(\n                id = %def.id,\n                source = ?def.source,\n                \"[agent_defs] loaded custom definition (overrides any built-in with the same id)\"\n            );\n            reg.insert(def);\n        }\n\n        // Re-validate the tier hierarchy after custom overrides are\n        // merged in — a workspace TOML can legally replace a built-in\n        // (same id) and is held to the same spawn-hierarchy contract\n        // as the bundled set. See\n        // [`crate::openhuman::agent::registry::agents::loader::validate_tier_hierarchy`].\n        let snapshot: Vec<AgentDefinition> = reg.list().into_iter().cloned().collect();\n        crate::openhuman::agent::registry::agents::validate_tier_hierarchy(&snapshot).map_err(\n            |e| {\n                anyhow::anyhow!(\n                    \"agent registry rejected after merging workspace overrides from {}: {}\",\n                    workspace.display(),\n                    e\n                )\n            },\n        )?;\n\n        Ok(reg)\n    }\n\n    /// Convenience: resolve the default workspace via\n    /// [`crate::openhuman::config::Config::load_or_init`] and load from\n    /// it. Built for sync CLI call sites (`openhuman agent list`,\n    /// future inspection tools) so they don't re-implement the Config\n    /// → workspace resolution dance. Must NOT be called from an\n    /// existing tokio runtime — construct a runtime and `block_on`.\n    pub async fn load_for_default_workspace() -> Result<Self> {\n        let config = crate::openhuman::config::Config::load_or_init().await?;","sourceCodeStart":745,"sourceCodeEnd":781,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/src/openhuman/agent/harness/definition.rs#L745-L781","documentation":"AgentDefinitionRegistry::load re-runs `validate_tier_hierarchy` after merging workspace-local TOML overrides (src/openhuman/agent/harness/definition.rs:763) because a workspace file may legally replace a built-in by id but is held to the same spawn contract. The inner error comes from loader.rs:394: either a `worker`-tier agent listing subagents (workers are leaf executors) or a forbidden same-tier delegation via validate_tier_transition (e.g. Chat→Chat or Reasoning→Reasoning in subagents).","triggerScenarios":"A workspace override defines an agent with `agent_tier = \"worker\"` plus a `[[subagents]]` entry; or a custom agent at chat tier lists another chat-tier agent as a subagent (reasoning→reasoning equally). Any of these in `<workspace>` agent TOMLs fails the whole registry load at boot/dump time.","commonSituations":"Users authoring custom agents without knowing the tier contract; upgrading after tier rules tightened, making previously-loading overrides invalid; copying an orchestrator-style TOML for a worker-tier agent.","solutions":["Read the inner message — it names parent id, parent tier, child id, child tier, and the violated rule.","Remove subagents from worker-tier agents (workers are leaves) or change the parent's tier.","For same-tier delegation, point the subagent entry at a different tier (e.g. a worker) instead of chat→chat / reasoning→reasoning.","Re-run; the registry loads only when the merged set validates."],"exampleFix":"# before: <workspace>/agents/custom.toml\nid = \"fast_helper\"\nagent_tier = \"worker\"\n[[subagents]]\nid = \"docs_worker\"        # worker listing subagents -> rejected\n# after: drop the subagents block (workers are leaf executors)\nid = \"fast_helper\"\nagent_tier = \"worker\"","handlingStrategy":"validation","validationCode":"// Dry-run the exact validation the registry performs, before booting with new overrides:\nuse crate::openhuman::agent::registry::agents::validate_tier_hierarchy;\n\nlet defs = load_definitions_with_overrides(&workspace)?; // your load path\nvalidate_tier_hierarchy(&defs)?; // fails here with the parent/child/tier detail, pre-boot","typeGuard":null,"tryCatchPattern":"match AgentDefinitionRegistry::load(&workspace).await {\n    Ok(reg) => Ok(reg),\n    Err(e) if e.to_string().contains(\"rejected after merging workspace overrides\") => {\n        // The inner {e} names parent id+tier and child id+tier.\n        // Fix the offending [[subagents]]/tier in the named override file, then reload.\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Workers are leaf executors — never give a worker-tier agent subagents.","Avoid same-tier (chat→chat, reasoning→reasoning) subagent edges in override TOMLs.","Validate overrides with validate_tier_hierarchy before deploying them to a workspace."],"tags":["rust","registry","agent-definitions","workspace-overrides","validation","toml"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}