{"record":{"id":"70f27d60e25b2170","repo":"conductor-oss/conductor","slug":"plan-execute-strategy-requires-planner-agent","errorCode":null,"errorMessage":"PLAN_EXECUTE strategy requires ``planner=<Agent>`` on the parent agent. The legacy ``agents=[planner, fallback]`` positional shape is no longer accepted — set the named slots ``planner=`` (required) and ``fallback=`` (optional) instead.","messagePattern":"PLAN_EXECUTE strategy requires ``planner=<Agent>`` on the parent agent\\. The legacy ``agents=\\[planner, fallback\\]`` positional shape is no longer accepted — set the named slots ``planner=`` \\(required\\) and ``fallback=`` \\(optional\\) instead\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/compiler/MultiAgentCompiler.java","lineNumber":2544,"sourceCode":"    // run fallback agent (agentic LLM, bounded turns).\n    //\n    // The JSON plan describes a DAG of operations.  Each operation is either\n    // \"static\" (tool call with known args) or \"generated\" (LLM produces args).\n    // Static ops compile to SIMPLE tasks.  Generated ops compile to\n    // LLM_CHAT_COMPLETE → INLINE(parse) → SIMPLE(apply) chains running in\n    // parallel within each step.\n\n    private WorkflowDef compilePlanExecute(AgentConfig config) {\n        // Named-slot resolution. PLAN_EXECUTE requires ``planner=``;\n        // ``fallback=`` is optional. The Python SDK rejects the legacy\n        // ``agents=[planner, fallback]`` positional shape at construction\n        // time (see Agent.__init__); we mirror that hard cut here so the\n        // Java SDK and any HTTP caller crafting JSON by hand fail with the\n        // same migration message instead of silently quasi-working.\n        AgentConfig plannerConfig = config.getPlanner();\n        AgentConfig fallbackConfig = config.getFallback();\n        if (plannerConfig == null) {\n            throw new IllegalArgumentException(\n                    \"PLAN_EXECUTE strategy requires ``planner=<Agent>`` on the parent agent. \"\n                            + \"The legacy ``agents=[planner, fallback]`` positional shape is no \"\n                            + \"longer accepted — set the named slots ``planner=`` (required) and \"\n                            + \"``fallback=`` (optional) instead.\");\n        }\n\n        // Parent-level ``tools`` is the canonical plan-executable set. The\n        // planner is told which tools are available (so it can't hallucinate\n        // names), PAC validates ``op.tool`` names against this set, and PAC\n        // wraps each emitted SIMPLE task with the tool's input guardrails\n        // (if any). Empty/null degrades gracefully — no allowlist check, no\n        // guardrail wrapping; the recommended shape always sets tools.\n        List<ToolConfig> parentTools = config.getTools() != null ? config.getTools() : List.of();\n\n        // Warn when a tool's guardrail uses a non-RAISE on_fail and there's\n        // no fallback agent to recover. In plan mode, RETRY/FIX/HUMAN all\n        // collapse to TERMINATE on the dynamic plan SUB_WORKFLOW; without a\n        // configured fallback, the whole pipeline just fails — the user","sourceCodeStart":2526,"sourceCodeEnd":2562,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/compiler/MultiAgentCompiler.java#L2526-L2562","documentation":"Thrown when a PLAN_EXECUTE-strategy agent is compiled without a 'planner' sub-agent configured. The compiler requires config.getPlanner() to be non-null — this replaces the old positional agents=[planner, fallback] shape that the Python SDK already rejected at construction time. The Java compiler mirrors that hard cut so both SDK and hand-crafted JSON callers get the same migration error.","triggerScenarios":"An AgentConfig with strategy=PLAN_EXECUTE where config.getPlanner() returns null. This happens when the planner slot was never set, or when the caller used the deprecated positional agents list instead of the named planner= field.","commonSituations":"Upgrading from an older API version that accepted agents=[planner, fallback] positionally, or writing PLAN_EXECUTE config by hand in JSON without knowing about the named planner= field. Also common when migrating from the Python SDK's older API.","solutions":["Set the named 'planner' field on the parent AgentConfig to the agent that produces the JSON plan, e.g. planner=<AgentConfig>.","If you also need a fallback agent, set the named 'fallback' field (optional) instead of relying on positional agents=[...].","Remove the legacy positional agents=[planner, fallback] list and migrate to named slots."],"exampleFix":"// before (legacy positional shape)\nAgentConfig.builder()\n    .strategy(Strategy.PLAN_EXECUTE)\n    .agents(List.of(planner, fallback))\n    .build();\n// after (named slots)\nAgentConfig.builder()\n    .strategy(Strategy.PLAN_EXECUTE)\n    .planner(planner)\n    .fallback(fallback)  // optional\n    .build();","handlingStrategy":"validation","validationCode":"void validatePlanExecute(AgentConfig config) {\n    if (config.getStrategy() == AgentConfig.Strategy.PLAN_EXECUTE) {\n        if (config.getPlanner() == null) {\n            throw new IllegalArgumentException(\n                \"PLAN_EXECUTE requires planner=<Agent> on the parent agent. \"\n                + \"Set the named 'planner' field (required) and optionally 'fallback'.\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    compiler.compile(agentConfig);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"PLAN_EXECUTE strategy requires\")) {\n        // migrate from agents=[...] positional to named planner=/fallback= slots\n    }\n    throw e;\n}","preventionTips":["Use named slots (planner=, fallback=) for PLAN_EXECUTE — the positional agents=[...] shape is deprecated.","After upgrading the SDK, audit all PLAN_EXECUTE agent definitions for the planner field."],"tags":["plan-execute","planner","migration","config-validation","agentspan"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}