PackagesAgent
Quickstart
Install core:
pnpm add @statelyai/agent@alpha xstate@alpha zodAdd ai and a provider only when using the optional AI SDK adapter.
Define and run one artifact
Save this as agent.mts. It uses a deterministic executor, so it needs no API
key or model SDK.
import { z } from "zod";
import { runAgent, setupAgent } from "@statelyai/agent";
const answerOutputSchema = z.object({ answer: z.string() });
const agent = setupAgent({
context: z.object({ prompt: z.string(), answer: z.string().nullable() }),
input: z.object({ prompt: z.string() }),
output: answerOutputSchema,
requests: {
answer: {
model: "fast",
schemas: { input: z.object({ prompt: z.string() }), output: z.string() },
prompt: ({ input }) => input.prompt,
},
},
});
const machine = agent.createMachine({
context: ({ input }) => ({ prompt: input.prompt, answer: null }),
initial: "answering",
states: {
answering: {
invoke: {
src: "answer",
input: ({ context }) => ({ prompt: context.prompt }),
onDone: ({ output }) => ({
target: "done",
context: { answer: output.result },
}),
},
},
done: {
type: "final",
output: ({ context }) => ({ answer: context.answer ?? "" }),
},
},
});
const result = await runAgent(machine, {
input: { prompt: "Why state machines?" },
executors: {
generateText: async () => ({ result: "Because transitions constrain behavior." }),
},
});
if (result.status !== "done") {
throw new Error(`Unexpected status: ${result.status}`);
}
console.log(result.output.answer);Run it:
npx tsx agent.mtsIt prints:
Because transitions constrain behavior.Requests have a semantic name, resolved input, model reference, schemas,
prompt/messages, and tools. The machine owns control flow; the executor owns
the provider call.
An executor is just a function, so the machine runs anywhere a function does.
When several requests each need their own canned answer, the executor routes on
request.name. See Evals.
Use a real model
Leave the machine unchanged and replace only the host executors:
import { openai } from "@ai-sdk/openai";
import { createAiSdkExecutors } from "@statelyai/agent/ai-sdk";
const executors = createAiSdkExecutors({
models: { fast: openai("gpt-5.4-mini") },
});
const liveResult = await runAgent(machine, {
input: { prompt: "Why state machines?" },
executors,
});
if (liveResult.status === "done") {
console.log(liveResult.output);
}Continue with Choosing a run mode, Messages, and Persistence.