{"record":{"id":"ab703a836952e426","repo":"alibaba/spring-ai-alibaba","slug":"either-instruction-or-includecontents-must-be","errorCode":null,"errorMessage":"Either 'instruction' or 'includeContents' must be set for Agent.","messagePattern":"Either 'instruction' or 'includeContents' must be set for Agent\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/node/AgentLlmNode.java","lineNumber":169,"sourceCode":"\n\t\t// Check and manage iteration counter\n\t\tfinal AtomicInteger iterations;\n\t\tif (!config.context().containsKey(MODEL_ITERATION_KEY)) {\n\t\t\titerations = new AtomicInteger(0);\n\t\t\tconfig.context().put(MODEL_ITERATION_KEY, iterations);\n\t\t} else {\n\t\t\titerations = (AtomicInteger) config.context().get(MODEL_ITERATION_KEY);\n\t\t\titerations.incrementAndGet();\n\t\t}\n\n\t\t// Check and manage messages\n\t\tList<Message> messages = new ArrayList<>();\n\t\tif (state.value(\"messages\").isEmpty()) {\n\t\t\t// try with \"input\" key, which is more commonly used in graph input when agent is used as a node.\n\t\t\tif (state.value(\"input\").isPresent()) {\n\t\t\t\tmessages.add(new UserMessage(state.value(\"input\").get().toString()));\n\t\t\t} else {\n\t\t\t\tthrow new IllegalArgumentException(\"Either 'instruction' or 'includeContents' must be set for Agent.\");\n\t\t\t}\n\t\t} else {\n\t\t\tmessages = (List<Message>) state.value(\"messages\").get();\n\t\t}\n\n\t\taugmentUserMessage(messages, outputSchema);\n\t\trenderTemplatedUserMessage(messages, state.data(), config.metadata());\n\n\t\t// Create ModelRequest; include state in context so interceptors (e.g. handoffs step-config) can read it\n\t\tMap<String, Object> contextMap = new HashMap<>(state.data());\n\t\tMap<String, Object> metadata = config.metadata().orElse(new HashMap<>());\n\t\tif (!metadata.isEmpty()) {\n\t\t\tcontextMap.putAll(metadata);\n\t\t}\n\t\tModelRequest.Builder requestBuilder = ModelRequest.builder()\n\t\t\t\t.messages(messages)\n\t\t\t\t.options(this.chatOptions != null ? this.chatOptions.copy() : null)\n\t\t\t\t.context(contextMap);","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/node/AgentLlmNode.java#L151-L187","documentation":"AgentLlmNode.apply() builds the message list for the LLM call. If the graph state has no \"messages\" key and also no \"input\" key, there is nothing to send to the model, so it throws IllegalArgumentException telling you to configure an instruction or include contents.","triggerScenarios":"Invoking an agent (or graph using AgentLlmNode as a node) whose input state contains neither \"messages\" nor \"input\", e.g. passing an empty map or only non-message keys like \"input_schema\".","commonSituations":"Feeding a graph with structured input (JSON fields) instead of chat messages; forgetting to set the agent's instruction/prompt in the builder; upstream node failed to produce \"messages\"; renaming the input key in a custom node.","solutions":["Set an instruction on the Agent builder so the node has a prompt","Include contents / seed the state with at least one Message","Pass input under the \"input\" key when using the agent as a plain graph node","Pass input as {\"messages\": [new UserMessage(\"...\")]} to match the expected state key"],"exampleFix":"// before\nOverAllState input = new OverAllState(Map.of(\"query\", \"hello\")); // no 'messages'/'input'\n// after\nOverAllState input = new OverAllState(Map.of(\"input\", \"hello\"));\n// or: Map.of(\"messages\", List.of(new UserMessage(\"hello\")))","handlingStrategy":"try-catch","validationCode":"boolean agentInputValid(Map<String,Object> state) { return state.containsKey(\"messages\") || state.containsKey(\"input\"); }","typeGuard":"boolean hasMessages(OverAllState s) { return s.value(\"messages\").isPresent() || s.value(\"input\").isPresent(); }","tryCatchPattern":"try { node.apply(state); } catch (IllegalArgumentException e) { log.error(\"Agent received no messages/input: {}\", state.data()); throw e; }","preventionTips":["Always set an instruction on the Agent builder","When using the agent as a graph node, pass input under the \"input\" or \"messages\" key","Normalize upstream node outputs to the \"messages\" key"],"tags":["java","state","agent","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}