Bug description
When calling callModel with a plain string input while reusing an existing StateAccessor, the SDK builds a responsesRequest.input array that contains the raw string as the last element instead of normalizing it into a user message object. The OpenRouter SDK then rejects the request with a SDKValidationError.
This contradicts the documented "Multi-Run Conversations" example, which explicitly passes a plain string for subsequent turns. Input formats docs section also suggests that all input formats are accepted.
Reproduction
- Start a conversation with
callModel using a state accessor. Use a model that returns reasoning/output items (e.g. minimax/minimax-m2.7).
import { OpenRouter } from "@openrouter/agent";
const openrouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });
const state = createStateAccessor("conv-123");
const r1 = openrouter.callModel({
model: "minimax/minimax-m2.7",
input: "hello world",
state,
});
console.log(await r1.getText());
- Resume the same conversation with a new plain string message.
const r2 = openrouter.callModel({
model: "minimax/minimax-m2.7",
input: "what was my first message",
state,
});
console.log(await r2.getText());
Expected behavior
The second call should succeed, with the SDK normalizing the plain string into a user message and merging it with the persisted history, as shown in the docs:
https://openrouter.ai/docs/agent-sdk/call-model/tool-approval-state#multi-run-conversations
Actual behavior
The second call throws:
SDKValidationError: Input validation failed
path: ["responsesRequest", "input"]
invalid_union: expected string, received array
at path [3]: expected object, received string
The SDK merges the new plain string directly into the history array, producing something like:
[
{ role: "user", content: "hello world" },
{ type: "reasoning", content: [...] },
{ role: "assistant", type: "message", content: [...] },
"what was my first message", // <-- raw string, invalid
]
Environment
@openrouter/agent: 0.7.2
@openrouter/sdk: 0.13.21
- Node.js:
26.3.1
- Model:
minimax/minimax-m2.7
Workaround
Pass the new turn as an array of user message objects instead of a plain string:
const r2 = openrouter.callModel({
model: "minimax/minimax-m2.7",
input: [{ role: "user", content: "what was my first message" }],
state,
});
Additional context
Looking at the installed package source, the issue appears to be in @openrouter/agent/esm/lib/model-result.js. When state is present and newInput is not an array, the SDK does:
freshItems = Array.isArray(newInput) ? newInput : [newInput];
baseRequest.input = appendToMessages(historicalMessages, hookedFresh);
This appends the raw string to the history array without converting it into a valid EasyInputMessage object. The docs imply the SDK should normalize a plain string into a user message before merging.
Bug description
When calling
callModelwith a plain stringinputwhile reusing an existingStateAccessor, the SDK builds aresponsesRequest.inputarray that contains the raw string as the last element instead of normalizing it into a user message object. The OpenRouter SDK then rejects the request with aSDKValidationError.This contradicts the documented "Multi-Run Conversations" example, which explicitly passes a plain string for subsequent turns. Input formats docs section also suggests that all input formats are accepted.
Reproduction
callModelusing a state accessor. Use a model that returns reasoning/output items (e.g.minimax/minimax-m2.7).Expected behavior
The second call should succeed, with the SDK normalizing the plain string into a user message and merging it with the persisted history, as shown in the docs:
https://openrouter.ai/docs/agent-sdk/call-model/tool-approval-state#multi-run-conversations
Actual behavior
The second call throws:
The SDK merges the new plain string directly into the history array, producing something like:
Environment
@openrouter/agent:0.7.2@openrouter/sdk:0.13.2126.3.1minimax/minimax-m2.7Workaround
Pass the new turn as an array of user message objects instead of a plain string:
Additional context
Looking at the installed package source, the issue appears to be in
@openrouter/agent/esm/lib/model-result.js. Whenstateis present andnewInputis not an array, the SDK does:This appends the raw string to the history array without converting it into a valid
EasyInputMessageobject. The docs imply the SDK should normalize a plain string into a user message before merging.