@statelyai/agent@2.0.0-alpha.21
Pre-releaseMinor Changes
-
#109
19298f4Thanks @davidkpiano! - AI SDK v7. Theaipeer dependency is now^7, paired with@ai-sdk/openai@^4.The structured-output envelope opt-in is now
includeReasoning, oncreateTextLogic, onAgentTextRequest, and inagent-workflow.json. AI SDK v7 repurposedreasoningas a reasoning-effort setting, and a boolean under that name both collided with it and broke the invariant that anAgentTextRequestis spread-compatible with the SDK's call options — which is what lets the rawaigenerateText/streamTextfunctions work as executors with no adapter.export const triageTicket = createTextLogic({ schemas: { input: z.object({ ticket: z.string() }), output: triageSchema }, model: "careful", includeReasoning: true, // was `reasoning: true` prompt: ({ input }) => input.ticket, });
Reasoning effort itself is not a core field. What it means differs per provider — an enum for one, a thinking-token budget for another, nothing for a third — so a machine that named a level would stop being portable. It belongs to the host, alongside the API key, and a
modelsentry can now carry it:const models = defineModels({ quick: openai("gpt-5.4-mini"), deep: { model: openai("gpt-5.4"), settings: { reasoning: "xhigh" } }, }); // the machine picks a persona by name, as it already did requests: { finalReview: { model: "deep", schemas, prompt: … } }
The ref is the unit a machine already names and already has typed, so this gives per-request effort without putting a provider's vocabulary in the machine. Swap in a host whose map defines
deepdifferently and every request follows, unedited.createAiSdkExecutorsalso gains a top-levelsettingsfor a default across every call, or a function of the request for knobs that do not generalize into a persona. Settings accept anything the AI SDK's call options accept, typed against the installedaiversion, and apply togenerateText,streamText, anddecide. They resolve least-specific first: the host'ssettings, then the ref's own, then what the request declared.model, the prompt fields,tools, andtoolChoiceare not settable in either place.The rest of the migration is inside
createAiSdkExecutors:- v7 rejects
role: 'system'insidemessagesunless the caller opts in. The adapter opts in, because an agent's messages are machine-authored server-side content, sosystemMessage()keeps working. - v7 moved
reasoningTokensunderusage.outputTokenDetailsand the cached-input count underusage.inputTokenDetails.cacheReadTokens. The adapter folds both onto the flat fieldsAgentUsageaggregates, and passes the SDK's own shape (includingraw) through untouched. AgentToolDescriptor.descriptionnow also accepts a function, matching a v7 tool whose description is computed per call.
- v7 rejects
Patch Changes
-
#109
19298f4Thanks @davidkpiano! - Works with XState 6.0.0-alpha.47 and later. Two type regressions surfaced by alpha.47, both in this package's own plumbing rather than in a machine you write.setupAgent({ guards, delays })typed both slots through XState's fully genericAnySetupConfig, so a source sawMachineContextinstead of the agent's own context. alpha.47 tightened those source types, which rejected the parameter annotations that were previously the only way to type them. Both slots are now typed from the agent's own context and event schemas, so an inline source is contextually typed and no annotation is needed.- alpha.47 resolves a machine's input type to
<input> | undefined.AgentInputFrommatched that union against the input-schema brand,undefinednever matched an object type, and the brand was dropped — so a field declared with a schema default read as required at therunAgent({ input })call site. The brand is now unwrapped through the optional union.
The
xstatepeer range is unchanged (>=6.0.0-alpha.46 <6.0.0); both fixes hold on alpha.46 as well.