@statelyai/agent 1.1.6 → 2.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/ai-sdk.cjs +342 -0
- package/dist/ai-sdk.d.cts +206 -0
- package/dist/ai-sdk.d.mts +206 -0
- package/dist/ai-sdk.mjs +331 -0
- package/dist/cli.cjs +64 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +65 -0
- package/dist/decision-CQdrKc8k.mjs +978 -0
- package/dist/decision-b-lkcs4L.cjs +1295 -0
- package/dist/index.cjs +59 -0
- package/dist/index.d.cts +212 -0
- package/dist/index.d.mts +201 -417
- package/dist/index.mjs +4 -588
- package/dist/openai-compat.cjs +319 -0
- package/dist/openai-compat.d.cts +98 -0
- package/dist/openai-compat.d.mts +98 -0
- package/dist/openai-compat.mjs +312 -0
- package/dist/run-agent-BFMkuI1F.cjs +1599 -0
- package/dist/run-agent-BVMd--1l.d.cts +1103 -0
- package/dist/run-agent-BoAOq_0Z.mjs +1540 -0
- package/dist/run-agent-DzYJb3CK.d.mts +1103 -0
- package/dist/src-D-77Ha5p.cjs +1087 -0
- package/dist/src-DUeIFjv-.mjs +1016 -0
- package/dist/text-logic-C7WJpCIc.d.mts +710 -0
- package/dist/text-logic-CZjyACzQ.d.cts +710 -0
- package/dist/types-C9QiMjre.d.cts +219 -0
- package/dist/types-qm00QF91.d.mts +219 -0
- package/dist/utils-Dri7aeEG.d.cts +108 -0
- package/dist/utils-Y6GDRGGE.d.mts +108 -0
- package/dist/zod.cjs +31 -0
- package/dist/zod.d.cts +30 -0
- package/dist/zod.d.mts +30 -0
- package/dist/zod.mjs +30 -0
- package/package.json +109 -28
- package/readme.md +143 -6
- package/schemas/agent-workflow.json +527 -0
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.env.template +0 -3
- package/.github/actions/ci-setup/action.yml +0 -24
- package/.github/workflows/release.yml +0 -46
- package/.vscode/launch.json +0 -28
- package/CHANGELOG.md +0 -222
- package/dist/index.d.ts +0 -428
- package/dist/index.js +0 -621
- package/examples/chatbot.ts +0 -71
- package/examples/cot.ts +0 -89
- package/examples/email.ts +0 -118
- package/examples/example.ts +0 -81
- package/examples/goal.ts +0 -94
- package/examples/helpers/helpers.ts +0 -17
- package/examples/helpers/loader.ts +0 -32
- package/examples/helpers/runner.ts +0 -27
- package/examples/joke.ts +0 -225
- package/examples/multi.ts +0 -103
- package/examples/newspaper.ts +0 -324
- package/examples/number.ts +0 -102
- package/examples/raffle.ts +0 -105
- package/examples/sandbox.ts +0 -28
- package/examples/simple.ts +0 -39
- package/examples/support.ts +0 -147
- package/examples/ticTacToe.ts +0 -224
- package/examples/todo.ts +0 -137
- package/examples/tutor.ts +0 -100
- package/examples/verify.ts +0 -120
- package/examples/weather.ts +0 -178
- package/examples/wiki.ts +0 -30
- package/examples/word.ts +0 -171
- package/src/adapters/vercel.ts +0 -7
- package/src/agent-experimental.ts +0 -221
- package/src/agent.test.ts +0 -506
- package/src/agent.ts +0 -300
- package/src/decision.test.ts +0 -179
- package/src/decision.ts +0 -84
- package/src/index.ts +0 -4
- package/src/memory.ts +0 -25
- package/src/planners/shortestPathPlanner.ts +0 -22
- package/src/planners/simplePlanner.ts +0 -139
- package/src/schemas.ts +0 -11
- package/src/strategies/chain-of-note.ts +0 -155
- package/src/templates/defaultText.ts +0 -18
- package/src/text.ts +0 -241
- package/src/types.ts +0 -499
- package/src/utils.ts +0 -72
- package/tsconfig.json +0 -109
- package/vitest.config.ts +0 -9
package/dist/zod.cjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let zod = require("zod");
|
|
3
|
+
//#region src/zod/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* A zod schema for an `AgentMessage[]` context/input field — the typed,
|
|
6
|
+
* dependency-light replacement for the hand-rolled
|
|
7
|
+
* `z.custom<AgentMessage[]>((value) => Array.isArray(value))` recipe repeated
|
|
8
|
+
* across machines that carry a message transcript in context.
|
|
9
|
+
*
|
|
10
|
+
* `AgentMessage` is a structural union (see `src/types.ts`), not something to
|
|
11
|
+
* re-declare as a zod object, so this stays a `z.custom` under the hood while
|
|
12
|
+
* exposing the precise `z.ZodType<AgentMessage[]>` type. Validation checks that
|
|
13
|
+
* the value is an array; element shape is trusted (the library's own message
|
|
14
|
+
* builders and adapters produce well-formed `AgentMessage`s).
|
|
15
|
+
*
|
|
16
|
+
* `zod` is an optional peer of `@statelyai/agent` — this subpath is the only
|
|
17
|
+
* place it's imported, mirroring how `./ai-sdk` gates on `ai`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { z } from 'zod';
|
|
22
|
+
* import { zodAgentMessages } from '@statelyai/agent/zod';
|
|
23
|
+
*
|
|
24
|
+
* const context = z.object({ messages: zodAgentMessages() });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
function zodAgentMessages() {
|
|
28
|
+
return zod.z.custom((value) => Array.isArray(value));
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
exports.zodAgentMessages = zodAgentMessages;
|
package/dist/zod.d.cts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { r as AgentMessage } from "./types-C9QiMjre.cjs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/zod/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* A zod schema for an `AgentMessage[]` context/input field — the typed,
|
|
7
|
+
* dependency-light replacement for the hand-rolled
|
|
8
|
+
* `z.custom<AgentMessage[]>((value) => Array.isArray(value))` recipe repeated
|
|
9
|
+
* across machines that carry a message transcript in context.
|
|
10
|
+
*
|
|
11
|
+
* `AgentMessage` is a structural union (see `src/types.ts`), not something to
|
|
12
|
+
* re-declare as a zod object, so this stays a `z.custom` under the hood while
|
|
13
|
+
* exposing the precise `z.ZodType<AgentMessage[]>` type. Validation checks that
|
|
14
|
+
* the value is an array; element shape is trusted (the library's own message
|
|
15
|
+
* builders and adapters produce well-formed `AgentMessage`s).
|
|
16
|
+
*
|
|
17
|
+
* `zod` is an optional peer of `@statelyai/agent` — this subpath is the only
|
|
18
|
+
* place it's imported, mirroring how `./ai-sdk` gates on `ai`.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { z } from 'zod';
|
|
23
|
+
* import { zodAgentMessages } from '@statelyai/agent/zod';
|
|
24
|
+
*
|
|
25
|
+
* const context = z.object({ messages: zodAgentMessages() });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
declare function zodAgentMessages(): z.ZodType<AgentMessage[]>;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { zodAgentMessages };
|
package/dist/zod.d.mts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { r as AgentMessage } from "./types-qm00QF91.mjs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/zod/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* A zod schema for an `AgentMessage[]` context/input field — the typed,
|
|
7
|
+
* dependency-light replacement for the hand-rolled
|
|
8
|
+
* `z.custom<AgentMessage[]>((value) => Array.isArray(value))` recipe repeated
|
|
9
|
+
* across machines that carry a message transcript in context.
|
|
10
|
+
*
|
|
11
|
+
* `AgentMessage` is a structural union (see `src/types.ts`), not something to
|
|
12
|
+
* re-declare as a zod object, so this stays a `z.custom` under the hood while
|
|
13
|
+
* exposing the precise `z.ZodType<AgentMessage[]>` type. Validation checks that
|
|
14
|
+
* the value is an array; element shape is trusted (the library's own message
|
|
15
|
+
* builders and adapters produce well-formed `AgentMessage`s).
|
|
16
|
+
*
|
|
17
|
+
* `zod` is an optional peer of `@statelyai/agent` — this subpath is the only
|
|
18
|
+
* place it's imported, mirroring how `./ai-sdk` gates on `ai`.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { z } from 'zod';
|
|
23
|
+
* import { zodAgentMessages } from '@statelyai/agent/zod';
|
|
24
|
+
*
|
|
25
|
+
* const context = z.object({ messages: zodAgentMessages() });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
declare function zodAgentMessages(): z.ZodType<AgentMessage[]>;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { zodAgentMessages };
|
package/dist/zod.mjs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region src/zod/index.ts
|
|
3
|
+
/**
|
|
4
|
+
* A zod schema for an `AgentMessage[]` context/input field — the typed,
|
|
5
|
+
* dependency-light replacement for the hand-rolled
|
|
6
|
+
* `z.custom<AgentMessage[]>((value) => Array.isArray(value))` recipe repeated
|
|
7
|
+
* across machines that carry a message transcript in context.
|
|
8
|
+
*
|
|
9
|
+
* `AgentMessage` is a structural union (see `src/types.ts`), not something to
|
|
10
|
+
* re-declare as a zod object, so this stays a `z.custom` under the hood while
|
|
11
|
+
* exposing the precise `z.ZodType<AgentMessage[]>` type. Validation checks that
|
|
12
|
+
* the value is an array; element shape is trusted (the library's own message
|
|
13
|
+
* builders and adapters produce well-formed `AgentMessage`s).
|
|
14
|
+
*
|
|
15
|
+
* `zod` is an optional peer of `@statelyai/agent` — this subpath is the only
|
|
16
|
+
* place it's imported, mirroring how `./ai-sdk` gates on `ai`.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { z } from 'zod';
|
|
21
|
+
* import { zodAgentMessages } from '@statelyai/agent/zod';
|
|
22
|
+
*
|
|
23
|
+
* const context = z.object({ messages: zodAgentMessages() });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
function zodAgentMessages() {
|
|
27
|
+
return z.custom((value) => Array.isArray(value));
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { zodAgentMessages };
|
package/package.json
CHANGED
|
@@ -1,52 +1,133 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statelyai/agent",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
3
|
+
"version": "2.0.0-alpha.10",
|
|
4
|
+
"description": "State-machine authoring layer for AI agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
6
7
|
"module": "dist/index.mjs",
|
|
7
|
-
"types": "dist/index.d.
|
|
8
|
+
"types": "dist/index.d.mts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"statelyai-agent": "dist/cli.mjs"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/index.d.mts",
|
|
16
|
+
"default": "./dist/index.mjs"
|
|
17
|
+
},
|
|
18
|
+
"require": {
|
|
19
|
+
"types": "./dist/index.d.cts",
|
|
20
|
+
"default": "./dist/index.cjs"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"./ai-sdk": {
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./dist/ai-sdk.d.mts",
|
|
26
|
+
"default": "./dist/ai-sdk.mjs"
|
|
27
|
+
},
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./dist/ai-sdk.d.cts",
|
|
30
|
+
"default": "./dist/ai-sdk.cjs"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"./openai-compat": {
|
|
34
|
+
"import": {
|
|
35
|
+
"types": "./dist/openai-compat.d.mts",
|
|
36
|
+
"default": "./dist/openai-compat.mjs"
|
|
37
|
+
},
|
|
38
|
+
"require": {
|
|
39
|
+
"types": "./dist/openai-compat.d.cts",
|
|
40
|
+
"default": "./dist/openai-compat.cjs"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"./zod": {
|
|
44
|
+
"import": {
|
|
45
|
+
"types": "./dist/zod.d.mts",
|
|
46
|
+
"default": "./dist/zod.mjs"
|
|
47
|
+
},
|
|
48
|
+
"require": {
|
|
49
|
+
"types": "./dist/zod.d.cts",
|
|
50
|
+
"default": "./dist/zod.cjs"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"./agent-workflow.json": "./schemas/agent-workflow.json"
|
|
54
|
+
},
|
|
55
|
+
"files": [
|
|
56
|
+
"dist",
|
|
57
|
+
"schemas"
|
|
58
|
+
],
|
|
8
59
|
"keywords": [
|
|
9
60
|
"ai",
|
|
10
61
|
"state machine",
|
|
11
62
|
"agent",
|
|
12
|
-
"
|
|
13
|
-
"reinforcement learning"
|
|
63
|
+
"statechart"
|
|
14
64
|
],
|
|
15
|
-
"author": "",
|
|
65
|
+
"author": "David Khourshid <david@stately.ai>",
|
|
16
66
|
"license": "MIT",
|
|
67
|
+
"repository": {
|
|
68
|
+
"type": "git",
|
|
69
|
+
"url": "git+https://github.com/statelyai/agent.git"
|
|
70
|
+
},
|
|
71
|
+
"homepage": "https://github.com/statelyai/agent#readme",
|
|
72
|
+
"bugs": {
|
|
73
|
+
"url": "https://github.com/statelyai/agent/issues"
|
|
74
|
+
},
|
|
75
|
+
"engines": {
|
|
76
|
+
"node": ">=22.18.0"
|
|
77
|
+
},
|
|
17
78
|
"devDependencies": {
|
|
79
|
+
"@ai-sdk/openai": "^3.0.25",
|
|
80
|
+
"@anthropic-ai/sdk": "^0.109.1",
|
|
18
81
|
"@changesets/changelog-github": "^0.5.0",
|
|
19
|
-
"@changesets/cli": "^2.27.
|
|
20
|
-
"@
|
|
21
|
-
"@
|
|
22
|
-
"@
|
|
23
|
-
"@types/node": "^20.16.
|
|
24
|
-
"
|
|
82
|
+
"@changesets/cli": "^2.27.9",
|
|
83
|
+
"@cloudflare/workers-types": "^4.20260702.1",
|
|
84
|
+
"@inquirer/prompts": "^8.5.2",
|
|
85
|
+
"@statelyai/inspect": "^0.7.2",
|
|
86
|
+
"@types/node": "^20.16.10",
|
|
87
|
+
"agents": "0.11.5",
|
|
88
|
+
"ai": "^6.0.67",
|
|
89
|
+
"ajv": "^8.20.0",
|
|
25
90
|
"dotenv": "^16.4.5",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
91
|
+
"knip": "6.24.0",
|
|
92
|
+
"openai": "^6.45.0",
|
|
93
|
+
"oxfmt": "0.57.0",
|
|
94
|
+
"oxlint": "1.72.0",
|
|
95
|
+
"tsdown": "^0.21.7",
|
|
96
|
+
"tsx": "^4.21.0",
|
|
29
97
|
"typescript": "^5.6.2",
|
|
30
|
-
"vitest": "^2.1.
|
|
31
|
-
"
|
|
32
|
-
"zod": "^3.
|
|
98
|
+
"vitest": "^2.1.2",
|
|
99
|
+
"xstate": "6.0.0-alpha.21",
|
|
100
|
+
"zod": "^4.3.6"
|
|
33
101
|
},
|
|
34
102
|
"publishConfig": {
|
|
35
103
|
"access": "public"
|
|
36
104
|
},
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
105
|
+
"peerDependencies": {
|
|
106
|
+
"ai": "^6.0.67",
|
|
107
|
+
"xstate": ">=6.0.0-alpha.16 <6.0.0",
|
|
108
|
+
"zod": "^3.25.0 || ^4.0.0"
|
|
109
|
+
},
|
|
110
|
+
"peerDependenciesMeta": {
|
|
111
|
+
"ai": {
|
|
112
|
+
"optional": true
|
|
113
|
+
},
|
|
114
|
+
"zod": {
|
|
115
|
+
"optional": true
|
|
116
|
+
}
|
|
43
117
|
},
|
|
44
118
|
"scripts": {
|
|
45
|
-
"build": "
|
|
46
|
-
"
|
|
119
|
+
"build": "tsdown",
|
|
120
|
+
"proto:prefabs": "tsx .scratch/prefabs/demo.ts",
|
|
121
|
+
"typecheck": "pnpm run typecheck:src && pnpm run typecheck:examples",
|
|
122
|
+
"typecheck:src": "tsc --noEmit",
|
|
123
|
+
"typecheck:examples": "tsc -p examples/tsconfig.json --noEmit",
|
|
124
|
+
"lint": "oxlint",
|
|
125
|
+
"format": "oxfmt src examples",
|
|
126
|
+
"format:check": "oxfmt --check src examples",
|
|
127
|
+
"knip": "knip",
|
|
128
|
+
"check": "pnpm run typecheck && pnpm run lint && pnpm run format:check && pnpm run knip",
|
|
47
129
|
"test": "vitest",
|
|
48
130
|
"test:ci": "vitest --run",
|
|
49
|
-
"example": "ts-node examples/helpers/runner.ts",
|
|
50
131
|
"changeset": "changeset",
|
|
51
132
|
"release": "changeset publish",
|
|
52
133
|
"version": "changeset version"
|
package/readme.md
CHANGED
|
@@ -1,10 +1,147 @@
|
|
|
1
1
|
# Stately Agent
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**The logic layer for AI agents.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- Incorporating **observations**, **message history**, and **feedback** to the agent decision-making and text-generation processes, as needed
|
|
7
|
-
- Enabling custom **planning** abilities for agents to achieve specific goals based on state machine logic, observations, and feedback
|
|
8
|
-
- Wrapping the [Vercel AI SDK](https://sdk.vercel.ai/) to easily support multiple model providers, such as OpenAI, Anthropic, Google, Mistral, Groq, Perplexity, and more
|
|
5
|
+
Build agents as state machines, with explicit control flow you can inspect, test, visualize, and run anywhere.
|
|
9
6
|
|
|
10
|
-
|
|
7
|
+
Stately Agent adds model requests and decisions to XState. The state machine defines what the agent can do. Your application chooses the model, runs the requests, and stores the state.
|
|
8
|
+
|
|
9
|
+
Any agent workflow or loop can be modeled as a state machine. Model calls and tools run as effects inside it. The model proposes an event. The machine decides whether it is allowed and what happens next.
|
|
10
|
+
|
|
11
|
+
Stately Agent 2 is in alpha. APIs may change before the stable release.
|
|
12
|
+
|
|
13
|
+
[Documentation](https://stately.ai/docs/agents) · [Examples](examples/README.md) · [XState](https://github.com/statelyai/xstate)
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
<!-- install command matching the package prerelease channel and package.json peers -->
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
pnpm add @statelyai/agent@alpha xstate@alpha zod ai @ai-sdk/openai
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Node 22.18 or newer is required.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
<!-- refund decision example using setupAgent, agent.decide, a machine guard, and the AI SDK runAgent host -->
|
|
28
|
+
|
|
29
|
+
This agent reviews refund requests. The model may propose an automatic refund, but the state machine owns the $100 limit.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { openai } from "@ai-sdk/openai";
|
|
33
|
+
import { defineModels, runAgent } from "@statelyai/agent/ai-sdk";
|
|
34
|
+
import { setupAgent } from "@statelyai/agent";
|
|
35
|
+
import { z } from "zod";
|
|
36
|
+
|
|
37
|
+
const models = defineModels({
|
|
38
|
+
fast: openai("gpt-5.4-mini"),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const agent = setupAgent({
|
|
42
|
+
models,
|
|
43
|
+
context: z.object({
|
|
44
|
+
request: z.string(),
|
|
45
|
+
amount: z.number(),
|
|
46
|
+
}),
|
|
47
|
+
input: z.object({
|
|
48
|
+
request: z.string(),
|
|
49
|
+
amount: z.number(),
|
|
50
|
+
}),
|
|
51
|
+
output: z.object({
|
|
52
|
+
outcome: z.enum(["refunded", "review"]),
|
|
53
|
+
}),
|
|
54
|
+
events: {
|
|
55
|
+
AUTO_REFUND: {},
|
|
56
|
+
REVIEW: z.object({ reason: z.string() }),
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const refundMachine = agent.createMachine({
|
|
61
|
+
context: ({ input }) => input,
|
|
62
|
+
initial: "deciding",
|
|
63
|
+
states: {
|
|
64
|
+
deciding: {
|
|
65
|
+
invoke: {
|
|
66
|
+
src: "agent.decide",
|
|
67
|
+
input: ({ context }) => ({
|
|
68
|
+
model: "fast",
|
|
69
|
+
system: "Choose AUTO_REFUND for eligible requests. Otherwise choose REVIEW.",
|
|
70
|
+
prompt: `${context.request}\nAmount: $${context.amount}`,
|
|
71
|
+
allowedEvents: ["AUTO_REFUND", "REVIEW"],
|
|
72
|
+
}),
|
|
73
|
+
},
|
|
74
|
+
on: {
|
|
75
|
+
AUTO_REFUND: ({ context }) => (context.amount <= 100 ? { target: "refunded" } : undefined),
|
|
76
|
+
REVIEW: { target: "review" },
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
refunded: {
|
|
80
|
+
type: "final",
|
|
81
|
+
output: () => ({ outcome: "refunded" }),
|
|
82
|
+
},
|
|
83
|
+
review: {
|
|
84
|
+
type: "final",
|
|
85
|
+
output: () => ({ outcome: "review" }),
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const result = await runAgent(refundMachine, {
|
|
91
|
+
input: {
|
|
92
|
+
request: "I was charged twice for the same order.",
|
|
93
|
+
amount: 75,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
if (result.status === "done") {
|
|
98
|
+
console.log(result.output);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
When the machine reaches `refunded`, the result is:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
{ outcome: 'refunded' }
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The model chooses between the events allowed in `deciding`. The `AUTO_REFUND` transition only works when the amount is at most $100. If the model chooses it for a larger amount, the guard rejects the choice and the decision is tried again.
|
|
109
|
+
|
|
110
|
+
## The state machine
|
|
111
|
+
|
|
112
|
+
<!-- Add the state machine illustration here. -->
|
|
113
|
+
|
|
114
|
+
The example has one model decision and two final outcomes. Real machines can add approval states, retries, parallel work, child agents, and long-running waits without changing how the control flow is represented.
|
|
115
|
+
|
|
116
|
+
## Core concepts
|
|
117
|
+
|
|
118
|
+
<!-- core concepts derived from setupAgent, built-in agent actors, runAgent, and XState snapshots -->
|
|
119
|
+
|
|
120
|
+
- **Machines own control flow.** States, events, transitions, and guards define what can happen.
|
|
121
|
+
- **Models make bounded decisions.** `agent.decide` asks a model to choose one of the events accepted by the current state.
|
|
122
|
+
- **Requests are typed.** Inputs, outputs, context, and events use Standard Schema. Zod works out of the box.
|
|
123
|
+
- **Your code runs the model.** `runAgent` accepts executor functions. The example uses the Vercel AI SDK adapter, but the machine does not depend on a provider.
|
|
124
|
+
- **Snapshots can be stored.** An agent can stop for human input, save its XState snapshot, and resume later in another process.
|
|
125
|
+
- **Machines can be checked without model calls.** Lint their structure, simulate scripted decisions, and explore paths without an API key.
|
|
126
|
+
- **Agents are XState machines.** Guards, actors, parallel states, inspection, testing, and visualization work as usual.
|
|
127
|
+
|
|
128
|
+
## Examples
|
|
129
|
+
|
|
130
|
+
<!-- starter examples derived from examples/*/metadata.json and examples/index.ts -->
|
|
131
|
+
|
|
132
|
+
- [Twenty Questions](examples/twenty-questions) shows a model choosing legal events in a loop.
|
|
133
|
+
- [Go Fish](examples/go-fish) pits a model against a human while the machine enforces hidden-information game rules.
|
|
134
|
+
- [Human in the loop](examples/human-in-the-loop) pauses, stores a snapshot, and resumes after review.
|
|
135
|
+
- [Ticket triage](examples/triage) returns structured data from a model request.
|
|
136
|
+
- [JSON agent](examples/json-agent) runs a machine defined as data.
|
|
137
|
+
|
|
138
|
+
See [all examples](examples/README.md).
|
|
139
|
+
|
|
140
|
+
## Learn more
|
|
141
|
+
|
|
142
|
+
- [Machines](docs/machines.md)
|
|
143
|
+
- [Text requests](docs/text-requests.md)
|
|
144
|
+
- [Decisions](docs/decisions.md)
|
|
145
|
+
- [Human in the loop](docs/human-in-the-loop.md)
|
|
146
|
+
- [Testing and verification](docs/verify.md)
|
|
147
|
+
- [Running on different hosts](docs/hosts.md)
|