{"record":{"id":"f0fbb5edb5784cfb","repo":"conductor-oss/conductor","slug":"sub-agent-name-a-getname-in-config-getna","errorCode":null,"errorMessage":"Sub-agent name '${a.getName()}' in '${config.getName()}' is reserved: the coordinator uses DONE as its completion signal. Rename the agent.","messagePattern":"Sub-agent name '(.+?)' in '(.+?)' is reserved: the coordinator uses DONE as its completion signal\\. Rename the agent\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/compiler/MultiAgentCompiler.java","lineNumber":2276,"sourceCode":"        setInputs.put(\"is_transfer\", ref(subRef + \".output.is_transfer\"));\n        setInputs.put(\"transfer_to\", ref(subRef + \".output.transfer_to\"));\n        setInputs.put(\"_last_tool_results\", ref(subRef + \".output.tool_results\"));\n        setInputs.put(\"_agent_state\", \"${\" + sCtxMergeRef + \".output.result}\");\n        setVar.setInputParameters(setInputs);\n        caseTasks.add(setVar);\n\n        return caseTasks;\n    }\n\n    /**\n     * Reject sub-agent names that collide with the coordinator's reserved {@code DONE} decision. An\n     * agent named \"done\" (any case) would clobber the DONE switch case and make the coordinator's\n     * completion signal unreachable by construction.\n     */\n    private void rejectReservedAgentNames(AgentConfig config, List<AgentConfig> agents) {\n        for (AgentConfig a : agents) {\n            if (\"done\".equalsIgnoreCase(a.getName())) {\n                throw new IllegalArgumentException(\n                        \"Sub-agent name '\"\n                                + a.getName()\n                                + \"' in '\"\n                                + config.getName()\n                                + \"' is reserved: the coordinator uses DONE as its completion \"\n                                + \"signal. Rename the agent.\");\n            }\n        }\n    }\n\n    /**\n     * Build the coordinator routing system prompt shared by the handoff and router strategies.\n     *\n     * <p>Scope-awareness matters when the team is nested (e.g. a handoff team inside a swarm): the\n     * conversation seeded into the team contains the FULL original request, but the team may have\n     * been delegated only a slice of it (recorded as a {@code [<sender> -> <teamName>]: <note>}\n     * line by the swarm/handoff concat scripts). Without the scope rules below, a part of the\n     * request that no team member can handle makes DONE unreachable — the coordinator is forced to","sourceCodeStart":2258,"sourceCodeEnd":2294,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/compiler/MultiAgentCompiler.java#L2258-L2294","documentation":"Thrown when a sub-agent in a multi-agent config has the name 'done' (case-insensitive). The coordinator workflow uses the literal string 'DONE' as its completion signal in a switch/decision node — a sub-agent named 'done' would clobber that switch case and make the completion signal unreachable, causing the workflow to loop forever or fail at runtime.","triggerScenarios":"Any AgentConfig whose getAgents() list contains an AgentConfig whose name, when compared case-insensitively to 'done', matches. For example names 'Done', 'DONE', 'done', or 'DoNe' all trigger this error.","commonSituations":"Naming an agent 'done' to indicate it handles completion or finalization tasks, without realizing the coordinator reserves that name. Also happens when agent names are auto-generated from task descriptions and one happens to produce 'done'.","solutions":["Rename the sub-agent to anything other than 'done' (case-insensitive), e.g. 'finalizer', 'completer', or a domain-specific name.","If the agent's role is to finalize output, use a descriptive name like 'summary_writer' or 'result_formatter' instead.","Avoid any name that equals 'done' regardless of case."],"exampleFix":"// before\nagents=[{name: \"done\", description: \"Finalizes the response\"}]\n// after\nagents=[{name: \"finalizer\", description: \"Finalizes the response\"}]","handlingStrategy":"validation","validationCode":"void checkReservedNames(AgentConfig config) {\n    if (config.getAgents() != null) {\n        for (AgentConfig a : config.getAgents()) {\n            if (\"done\".equalsIgnoreCase(a.getName())) {\n                throw new IllegalArgumentException(\n                    \"Sub-agent name '\" + a.getName() + \"' is reserved (DONE signal). Rename it.\");\n            }\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    compiler.compile(agentConfig);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"reserved\")) {\n        // rename the offending agent from 'done' to something else\n    }\n    throw e;\n}","preventionTips":["Never name any agent 'done' in any casing — it is a reserved coordinator keyword.","Add a CI check that rejects agent definitions with reserved names."],"tags":["swarm","reserved-name","coordinator","config-validation","agentspan"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}