alibaba/spring-ai-alibaba · error · IllegalArgumentException

Either 'instruction' or 'includeContents' must be set for Ag

Error message

Either 'instruction' or 'includeContents' must be set for Agent.

What it means

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.

Source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/node/AgentLlmNode.java:169

		// Check and manage iteration counter
		final AtomicInteger iterations;
		if (!config.context().containsKey(MODEL_ITERATION_KEY)) {
			iterations = new AtomicInteger(0);
			config.context().put(MODEL_ITERATION_KEY, iterations);
		} else {
			iterations = (AtomicInteger) config.context().get(MODEL_ITERATION_KEY);
			iterations.incrementAndGet();
		}

		// Check and manage messages
		List<Message> messages = new ArrayList<>();
		if (state.value("messages").isEmpty()) {
			// try with "input" key, which is more commonly used in graph input when agent is used as a node.
			if (state.value("input").isPresent()) {
				messages.add(new UserMessage(state.value("input").get().toString()));
			} else {
				throw new IllegalArgumentException("Either 'instruction' or 'includeContents' must be set for Agent.");
			}
		} else {
			messages = (List<Message>) state.value("messages").get();
		}

		augmentUserMessage(messages, outputSchema);
		renderTemplatedUserMessage(messages, state.data(), config.metadata());

		// Create ModelRequest; include state in context so interceptors (e.g. handoffs step-config) can read it
		Map<String, Object> contextMap = new HashMap<>(state.data());
		Map<String, Object> metadata = config.metadata().orElse(new HashMap<>());
		if (!metadata.isEmpty()) {
			contextMap.putAll(metadata);
		}
		ModelRequest.Builder requestBuilder = ModelRequest.builder()
				.messages(messages)
				.options(this.chatOptions != null ? this.chatOptions.copy() : null)
				.context(contextMap);

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Set an instruction on the Agent builder so the node has a prompt
  2. Include contents / seed the state with at least one Message
  3. Pass input under the "input" key when using the agent as a plain graph node
  4. Pass input as {"messages": [new UserMessage("...")]} to match the expected state key

Example fix

// before
OverAllState input = new OverAllState(Map.of("query", "hello")); // no 'messages'/'input'
// after
OverAllState input = new OverAllState(Map.of("input", "hello"));
// or: Map.of("messages", List.of(new UserMessage("hello")))
Defensive patterns

Strategy: try-catch

Validate before calling

boolean agentInputValid(Map<String,Object> state) { return state.containsKey("messages") || state.containsKey("input"); }

Type guard

boolean hasMessages(OverAllState s) { return s.value("messages").isPresent() || s.value("input").isPresent(); }

Try / catch

try { node.apply(state); } catch (IllegalArgumentException e) { log.error("Agent received no messages/input: {}", state.data()); throw e; }

Prevention

When it happens

Trigger: 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".

Common situations: 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.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/ab703a836952e426. Report an issue: GitHub.