@statelyai/agent 2.0.0-alpha.14 → 2.0.0-alpha.16

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.
Files changed (35) hide show
  1. package/dist/ai-sdk.cjs +1 -1
  2. package/dist/ai-sdk.d.cts +2 -2
  3. package/dist/ai-sdk.d.mts +2 -2
  4. package/dist/ai-sdk.mjs +1 -1
  5. package/dist/{decision-C0cUKvNt.cjs → decision-Ba8qrT8r.cjs} +42 -28
  6. package/dist/{decision-D9Zi7Xi5.mjs → decision-Bt2HYYRo.mjs} +31 -23
  7. package/dist/{event-log-store-D7pWtIhb.mjs → event-log-store-B-1fcfkT.mjs} +149 -141
  8. package/dist/{event-log-store-BkUNtyOF.d.mts → event-log-store-BrC9Q1xW.d.mts} +14 -12
  9. package/dist/{event-log-store-CVd2eyRy.d.cts → event-log-store-CQJq8_v4.d.cts} +14 -12
  10. package/dist/{event-log-store-CNT_7F0V.cjs → event-log-store-yquOV1TX.cjs} +148 -140
  11. package/dist/index.cjs +520 -521
  12. package/dist/index.d.cts +128 -106
  13. package/dist/index.d.mts +128 -106
  14. package/dist/index.mjs +519 -520
  15. package/dist/machines.cjs +1 -1
  16. package/dist/machines.d.cts +1 -1
  17. package/dist/machines.d.mts +1 -1
  18. package/dist/machines.mjs +1 -1
  19. package/dist/otel.d.cts +1 -1
  20. package/dist/otel.d.mts +1 -1
  21. package/dist/{run-agent-BlqKwHIF.d.cts → run-agent-BxjGaVpL.d.cts} +72 -111
  22. package/dist/{run-agent-2MnlQTkB.d.mts → run-agent-COHoCgQd.d.mts} +72 -111
  23. package/dist/{setup-agent-CpK0ZRWV.cjs → setup-agent-BLU77gqr.cjs} +141 -172
  24. package/dist/{setup-agent-DeHRW-qX.mjs → setup-agent-SbiiSbAU.mjs} +136 -167
  25. package/dist/sqlite.cjs +1 -1
  26. package/dist/sqlite.d.cts +2 -2
  27. package/dist/sqlite.d.mts +2 -2
  28. package/dist/sqlite.mjs +1 -1
  29. package/dist/{text-logic-Jkilp1Ie.d.cts → text-logic-BFX5q7fM.d.cts} +26 -3
  30. package/dist/{text-logic-C5kbjaDz.d.mts → text-logic-DQW8_DWW.d.mts} +26 -3
  31. package/dist/{types-rMe7x6NR.d.cts → types-DYpK3QF4.d.mts} +35 -7
  32. package/dist/{types-9Bqg5rZB.d.mts → types-pJ5Hn8fv.d.cts} +35 -7
  33. package/package.json +28 -28
  34. package/readme.md +6 -19
  35. package/schemas/agent-workflow.json +1 -4
@@ -1,4 +1,4 @@
1
- import { _ as StandardSchemaV1, a as AgentToolChoice, c as AgentTools, d as ChosenEvent, h as InferOutput, l as AllowedEvents, n as AgentMessage } from "./types-9Bqg5rZB.mjs";
1
+ import { a as AgentToolChoice, c as AgentTools, d as ChosenEvent, g as InferOutput, l as AllowedEvents, n as AgentMessage, v as StandardSchemaV1 } from "./types-DYpK3QF4.mjs";
2
2
  import { t as AgentError } from "./errors-C9rxnWbX.mjs";
3
3
  import { AnyMachineSnapshot, AsyncActorLogic, EventObject, MachineSnapshot } from "xstate";
4
4
 
@@ -16,9 +16,11 @@ interface AgentEventDescriptor {
16
16
  toolName: string;
17
17
  inputSchema?: StandardSchemaV1;
18
18
  }
19
- /** Registered event payload schemas, as attached to a machine by `setupAgent`/`createAgentSchemas`. */
19
+ /** Registered schemas, as attached to a machine by `setupAgent`/`createAgentSchemas`. */
20
20
  interface AgentSchemas {
21
21
  events?: Record<string, StandardSchemaV1>;
22
+ /** Machine input schema; `runAgent` validates `options.input` against it. */
23
+ input?: StandardSchemaV1;
22
24
  }
23
25
  /** Shared options threaded through step discovery ({@link getAgentRequests}/{@link getAcceptedEvents}) — snapshot for event legality, event schemas for payload validation/tool schemas, and registered actor source logics. */
24
26
  interface AgentRequestOptions {
@@ -387,6 +389,27 @@ interface AgentUsage {
387
389
  }
388
390
  /** One model call's reported usage — {@link AgentUsage} without the run-level `modelCalls` count. What an executor puts on its result's `usage` field. */
389
391
  type AgentCallUsage = Omit<AgentUsage, "modelCalls">;
392
+ /**
393
+ * Reads a settled call's per-call {@link AgentCallUsage} off a RAW executor
394
+ * result's `usage` field, keeping only finite numbers — the same normalization
395
+ * `runAgent` applies before it delivers `'@agent.usage'`. Returns `undefined`
396
+ * when the result reports no usage at all. Works for our `{ output, usage }`
397
+ * envelope, for a raw Vercel AI SDK result (its `LanguageModelUsage` carries
398
+ * the same flat field names), and for any custom executor that follows the
399
+ * shape.
400
+ *
401
+ * The seam for the step-loop path, where the host holds the raw result itself:
402
+ *
403
+ * ```ts
404
+ * const { output, raw } = await executeAgentRequest(effect, executors);
405
+ * const usage = getCallUsage(raw);
406
+ * if (usage) append({ type: AGENT_USAGE_EVENT_TYPE, usage }); // journal + transition, like any event
407
+ * append(effect.toDoneEvent(output));
408
+ * ```
409
+ *
410
+ * See "Token usage on this path" in docs/steps.md for the full loop.
411
+ */
412
+ declare function getCallUsage(raw: unknown): AgentCallUsage | undefined;
390
413
  /**
391
414
  * Inline input for the `agent.userInput` builtin actor — a human-input request
392
415
  * (CLI prompt, chat reply, …) that resolves to the `string` the human typed.
@@ -702,4 +725,4 @@ declare function buildEnvelopeSchema(inner: StandardSchemaV1, options?: {
702
725
  */
703
726
  declare function parseStructuredEnvelope(request: Pick<AgentTextRequest, "outputSchema" | "reasoning">, value: unknown): StructuredOutputEnvelope;
704
727
  //#endregion
705
- export { AgentDecisionExhaustedError as A, AgentRequestOptions as B, buildEnvelopeSchema as C, parseOutput as D, parseModelRef as E, ResolveDecisionOptions as F, getAcceptedEvents as H, renderDecisionAttempts as I, resolveDecision as L, AgentDecisionRequest as M, DecisionAttempt as N, parseStructuredEnvelope as O, DecisionLogicConfig as P, AgentEventDescriptor as R, bindRequestExecutor as S, getAgentOutputMode as T, parseAgentEvent as U, AgentRequestSource as V, StructuredOutputEnvelope as _, AgentOutputMode as a, TextLogicExecuteArgs as b, AgentRequestExecutorResult as c, AgentTextRequest as d, AgentUsage as f, BuiltinAgentActors as g, AiSdkShapedTextResult as h, AgentModelRef as i, AgentDecisionInput as j, AgentDecisionExecutor as k, AgentRequestExecutors as l, AiSdkShapedStreamResult as m, AgentExecutorTextRequest as n, AgentRequestExecutor as o, AgentUserInput as p, AgentModelMap as r, AgentRequestExecutorInfo as s, AgentCallUsage as t, AgentRequestMode as u, TextLogic as v, createTextLogic as w, TextLogicExecutor as x, TextLogicConfig as y, AgentEventToolNameResolver as z };
728
+ export { AgentDecisionExecutor as A, AgentEventToolNameResolver as B, buildEnvelopeSchema as C, parseModelRef as D, getCallUsage as E, DecisionLogicConfig as F, AgentRequestSource as H, ResolveDecisionOptions as I, renderDecisionAttempts as L, AgentDecisionInput as M, AgentDecisionRequest as N, parseOutput as O, DecisionAttempt as P, resolveDecision as R, bindRequestExecutor as S, getAgentOutputMode as T, getAcceptedEvents as U, AgentRequestOptions as V, parseAgentEvent as W, StructuredOutputEnvelope as _, AgentOutputMode as a, TextLogicExecuteArgs as b, AgentRequestExecutorResult as c, AgentTextRequest as d, AgentUsage as f, BuiltinAgentActors as g, AiSdkShapedTextResult as h, AgentModelRef as i, AgentDecisionExhaustedError as j, parseStructuredEnvelope as k, AgentRequestExecutors as l, AiSdkShapedStreamResult as m, AgentExecutorTextRequest as n, AgentRequestExecutor as o, AgentUserInput as p, AgentModelMap as r, AgentRequestExecutorInfo as s, AgentCallUsage as t, AgentRequestMode as u, TextLogic as v, createTextLogic as w, TextLogicExecutor as x, TextLogicConfig as y, AgentEventDescriptor as z };
@@ -36,6 +36,33 @@ interface StandardSchemaV1<Input = unknown, Output = Input> {
36
36
  }
37
37
  /** The validated output type of a {@link StandardSchemaV1}. */
38
38
  type InferOutput<T> = T extends StandardSchemaV1<any, infer O> ? O : never;
39
+ /**
40
+ * The *pre*-validation input type of a {@link StandardSchemaV1}: what a caller
41
+ * passes in, before defaults are filled and transforms applied. Standard Schema
42
+ * carries both sides (`~standard.types.input` / `.output`), so a schema
43
+ * declaring a defaulted field makes that field optional here and required in
44
+ * {@link InferOutput} — which is exactly the split between what `runAgent`
45
+ * accepts as machine `input` and what the `context` factory then sees.
46
+ */
47
+ type InferInput<T> = T extends StandardSchemaV1<infer I, any> ? I : never;
48
+ /**
49
+ * Phantom brand carrying a machine's declared input schema on the machine type.
50
+ *
51
+ * XState resolves `schemas.input` to a single type and uses it for both
52
+ * `createActor`'s `input` option and the `context: ({ input })` factory, so the
53
+ * caller-facing and factory-facing sides cannot differ there. `setupAgent`'s
54
+ * `createMachine` brands the machine's input type with the schema itself, which
55
+ * lets `AgentInputFrom` recover the looser input side for `runAgent` while the
56
+ * `context` factory keeps the strict validated side.
57
+ *
58
+ * The key is a `~`-prefixed phantom property (the same convention Standard
59
+ * Schema uses for `~standard`) rather than a `unique symbol`: a symbol would
60
+ * have to be exported as a runtime value for declaration emit to name it in
61
+ * every machine type it touches.
62
+ */
63
+ type WithAgentInputSchema<TInputSchema> = {
64
+ readonly "~agent.inputSchema"?: TInputSchema;
65
+ };
39
66
  /** An event schema's output, widened to `unknown` when it validates an empty object (no payload fields). */
40
67
  type EventPayload<T> = T extends Record<string, never> ? unknown : T;
41
68
  /**
@@ -157,13 +184,14 @@ type ToolMessage = {
157
184
  */
158
185
  type AgentMessage = SystemMessage | UserMessage | AssistantMessage | ToolMessage;
159
186
  /**
160
- * A schema value on an {@link AgentToolDescriptor}. Core reads it as a
161
- * {@link StandardSchemaV1} (via `getJsonSchema`/`isStandardSchema`) when it can,
162
- * but the type is deliberately widened with `object` so an SDK-native tool —
163
- * whose `inputSchema` is the SDK's own union type (a Zod schema, the SDK's
164
- * `Schema`, a lazy thunk, …) assigns structurally with no cast.
187
+ * A schema value on an {@link AgentToolDescriptor}: deliberately just `object`,
188
+ * because an SDK-native tool's `inputSchema` is the SDK's own union type (a Zod
189
+ * schema, the SDK's `Schema`, a lazy thunk, ...) and must assign structurally
190
+ * with no cast. The contract is runtime, not static: core narrows with
191
+ * `isStandardSchema` and reads {@link StandardSchemaV1} schemas via
192
+ * `getJsonSchema`; anything else passes through to the executor untouched.
165
193
  */
166
- type AgentToolSchema = StandardSchemaV1 | object;
194
+ type AgentToolSchema = object;
167
195
  /**
168
196
  * A tool exposed to a text request, described for both the model and
169
197
  * (optionally) host execution. This is a **minimal structural contract**: any
@@ -216,4 +244,4 @@ type AllowedEvents<TEvent extends string = string, TInput = unknown> = AllowedEv
216
244
  input: TInput;
217
245
  }) => AllowedEventPattern<TEvent> | readonly AllowedEventPattern<TEvent>[]);
218
246
  //#endregion
219
- export { UserMessage as C, ToolResultPart as S, StandardSchemaV1 as _, AgentToolChoice as a, ToolCallPart as b, AgentTools as c, ChosenEvent as d, EventUnion as f, NormalizedEventSchemas as g, InferOutput as h, AgentTool as i, AllowedEvents as l, ImagePart as m, AgentMessage as n, AgentToolDescriptor as o, FilePart as p, AgentSnapshotStore as r, AgentToolExecute as s, AgentEventSchemaInputMap as t, AssistantMessage as u, SystemMessage as v, ToolMessage as x, TextPart as y };
247
+ export { ToolResultPart as C, ToolMessage as S, WithAgentInputSchema as T, NormalizedEventSchemas as _, AgentToolChoice as a, TextPart as b, AgentTools as c, ChosenEvent as d, EventUnion as f, InferOutput as g, InferInput as h, AgentTool as i, AllowedEvents as l, ImagePart as m, AgentMessage as n, AgentToolDescriptor as o, FilePart as p, AgentSnapshotStore as r, AgentToolExecute as s, AgentEventSchemaInputMap as t, AssistantMessage as u, StandardSchemaV1 as v, UserMessage as w, ToolCallPart as x, SystemMessage as y };
@@ -36,6 +36,33 @@ interface StandardSchemaV1<Input = unknown, Output = Input> {
36
36
  }
37
37
  /** The validated output type of a {@link StandardSchemaV1}. */
38
38
  type InferOutput<T> = T extends StandardSchemaV1<any, infer O> ? O : never;
39
+ /**
40
+ * The *pre*-validation input type of a {@link StandardSchemaV1}: what a caller
41
+ * passes in, before defaults are filled and transforms applied. Standard Schema
42
+ * carries both sides (`~standard.types.input` / `.output`), so a schema
43
+ * declaring a defaulted field makes that field optional here and required in
44
+ * {@link InferOutput} — which is exactly the split between what `runAgent`
45
+ * accepts as machine `input` and what the `context` factory then sees.
46
+ */
47
+ type InferInput<T> = T extends StandardSchemaV1<infer I, any> ? I : never;
48
+ /**
49
+ * Phantom brand carrying a machine's declared input schema on the machine type.
50
+ *
51
+ * XState resolves `schemas.input` to a single type and uses it for both
52
+ * `createActor`'s `input` option and the `context: ({ input })` factory, so the
53
+ * caller-facing and factory-facing sides cannot differ there. `setupAgent`'s
54
+ * `createMachine` brands the machine's input type with the schema itself, which
55
+ * lets `AgentInputFrom` recover the looser input side for `runAgent` while the
56
+ * `context` factory keeps the strict validated side.
57
+ *
58
+ * The key is a `~`-prefixed phantom property (the same convention Standard
59
+ * Schema uses for `~standard`) rather than a `unique symbol`: a symbol would
60
+ * have to be exported as a runtime value for declaration emit to name it in
61
+ * every machine type it touches.
62
+ */
63
+ type WithAgentInputSchema<TInputSchema> = {
64
+ readonly "~agent.inputSchema"?: TInputSchema;
65
+ };
39
66
  /** An event schema's output, widened to `unknown` when it validates an empty object (no payload fields). */
40
67
  type EventPayload<T> = T extends Record<string, never> ? unknown : T;
41
68
  /**
@@ -157,13 +184,14 @@ type ToolMessage = {
157
184
  */
158
185
  type AgentMessage = SystemMessage | UserMessage | AssistantMessage | ToolMessage;
159
186
  /**
160
- * A schema value on an {@link AgentToolDescriptor}. Core reads it as a
161
- * {@link StandardSchemaV1} (via `getJsonSchema`/`isStandardSchema`) when it can,
162
- * but the type is deliberately widened with `object` so an SDK-native tool —
163
- * whose `inputSchema` is the SDK's own union type (a Zod schema, the SDK's
164
- * `Schema`, a lazy thunk, …) assigns structurally with no cast.
187
+ * A schema value on an {@link AgentToolDescriptor}: deliberately just `object`,
188
+ * because an SDK-native tool's `inputSchema` is the SDK's own union type (a Zod
189
+ * schema, the SDK's `Schema`, a lazy thunk, ...) and must assign structurally
190
+ * with no cast. The contract is runtime, not static: core narrows with
191
+ * `isStandardSchema` and reads {@link StandardSchemaV1} schemas via
192
+ * `getJsonSchema`; anything else passes through to the executor untouched.
165
193
  */
166
- type AgentToolSchema = StandardSchemaV1 | object;
194
+ type AgentToolSchema = object;
167
195
  /**
168
196
  * A tool exposed to a text request, described for both the model and
169
197
  * (optionally) host execution. This is a **minimal structural contract**: any
@@ -216,4 +244,4 @@ type AllowedEvents<TEvent extends string = string, TInput = unknown> = AllowedEv
216
244
  input: TInput;
217
245
  }) => AllowedEventPattern<TEvent> | readonly AllowedEventPattern<TEvent>[]);
218
246
  //#endregion
219
- export { UserMessage as C, ToolResultPart as S, StandardSchemaV1 as _, AgentToolChoice as a, ToolCallPart as b, AgentTools as c, ChosenEvent as d, EventUnion as f, NormalizedEventSchemas as g, InferOutput as h, AgentTool as i, AllowedEvents as l, ImagePart as m, AgentMessage as n, AgentToolDescriptor as o, FilePart as p, AgentSnapshotStore as r, AgentToolExecute as s, AgentEventSchemaInputMap as t, AssistantMessage as u, SystemMessage as v, ToolMessage as x, TextPart as y };
247
+ export { ToolResultPart as C, ToolMessage as S, WithAgentInputSchema as T, NormalizedEventSchemas as _, AgentToolChoice as a, TextPart as b, AgentTools as c, ChosenEvent as d, EventUnion as f, InferOutput as g, InferInput as h, AgentTool as i, AllowedEvents as l, ImagePart as m, AgentMessage as n, AgentToolDescriptor as o, FilePart as p, AgentSnapshotStore as r, AgentToolExecute as s, AgentEventSchemaInputMap as t, AssistantMessage as u, StandardSchemaV1 as v, UserMessage as w, ToolCallPart as x, SystemMessage as y };
package/package.json CHANGED
@@ -1,7 +1,28 @@
1
1
  {
2
2
  "name": "@statelyai/agent",
3
- "version": "2.0.0-alpha.14",
3
+ "version": "2.0.0-alpha.16",
4
4
  "description": "Make invalid agent actions impossible. Agent logic as state machines: deterministic, inspectable, resumable, runs anywhere.",
5
+ "keywords": [
6
+ "agent",
7
+ "ai",
8
+ "state machine",
9
+ "statechart"
10
+ ],
11
+ "homepage": "https://github.com/statelyai/agent#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/statelyai/agent/issues"
14
+ },
15
+ "license": "MIT",
16
+ "author": "David Khourshid <david@stately.ai>",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/statelyai/agent.git"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "schemas",
24
+ "skills"
25
+ ],
5
26
  "type": "module",
6
27
  "main": "dist/index.cjs",
7
28
  "module": "dist/index.mjs",
@@ -59,29 +80,8 @@
59
80
  },
60
81
  "./agent-workflow.json": "./schemas/agent-workflow.json"
61
82
  },
62
- "files": [
63
- "dist",
64
- "schemas",
65
- "skills"
66
- ],
67
- "keywords": [
68
- "ai",
69
- "state machine",
70
- "agent",
71
- "statechart"
72
- ],
73
- "author": "David Khourshid <david@stately.ai>",
74
- "license": "MIT",
75
- "repository": {
76
- "type": "git",
77
- "url": "git+https://github.com/statelyai/agent.git"
78
- },
79
- "homepage": "https://github.com/statelyai/agent#readme",
80
- "bugs": {
81
- "url": "https://github.com/statelyai/agent/issues"
82
- },
83
- "engines": {
84
- "node": ">=22.18.0"
83
+ "publishConfig": {
84
+ "access": "public"
85
85
  },
86
86
  "devDependencies": {
87
87
  "@ai-sdk/openai": "^3.0.25",
@@ -124,9 +124,6 @@
124
124
  "xstate": "6.0.0-alpha.25",
125
125
  "zod": "^4.3.6"
126
126
  },
127
- "publishConfig": {
128
- "access": "public"
129
- },
130
127
  "peerDependencies": {
131
128
  "@opentelemetry/api": "^1",
132
129
  "ai": "^6.0.67",
@@ -140,6 +137,9 @@
140
137
  "optional": true
141
138
  }
142
139
  },
140
+ "engines": {
141
+ "node": ">=22.18.0"
142
+ },
143
143
  "scripts": {
144
144
  "build": "tsdown",
145
145
  "demo": "pnpm --filter @statelyai/agent-demo dev",
@@ -148,7 +148,7 @@
148
148
  "typecheck": "pnpm run typecheck:src && pnpm run typecheck:examples && pnpm run typecheck:example-packages",
149
149
  "typecheck:src": "tsc --noEmit",
150
150
  "typecheck:examples": "tsc -p examples/tsconfig.json --noEmit",
151
- "typecheck:example-packages": "tsc -p examples/next-host --noEmit && tsc -p examples/tanstack-start-host --noEmit && tsc -p examples/tanstack-ai-stream --noEmit && tsc -p examples/cloudflare-agent-host --noEmit && tsc -p examples/cloudflare-workers-ai-host --noEmit",
151
+ "typecheck:example-packages": "pnpm run build && tsc -p examples/next-host --noEmit && tsc -p examples/tanstack-start-host --noEmit && tsc -p examples/tanstack-ai-stream --noEmit && tsc -p examples/cloudflare-agent-host --noEmit && tsc -p examples/cloudflare-workers-ai-host --noEmit",
152
152
  "test:cloudflare": "pnpm --filter @statelyai/example-cloudflare-agent-host test && pnpm --filter @statelyai/example-cloudflare-workers-ai-host test",
153
153
  "lint": "oxlint",
154
154
  "format": "oxfmt src examples",
package/readme.md CHANGED
@@ -17,7 +17,7 @@ Stately Agent 2 is in alpha. APIs may change before the stable release.
17
17
  ## Three starting points
18
18
 
19
19
  - **Author a new agent.** Build a machine from states, decisions, and typed requests; run it locally with `runAgent`, test it with no API key, then use it in any framework or runtime with zero machine changes. See the [Quickstart](docs/quickstart.md) and [Use in any stack](docs/any-stack.md).
20
- - **Retrofit an existing agent.** Turn a `while` loop into a machine: your SDK calls, tools, and retry code become the executors; the machine replaces only the control flow. See [Migrating from a loop](docs/from-a-loop.md).
20
+ - **Retrofit an existing agent.** Turn a `while` loop into a machine: your SDK calls, tools, and retry code become the executors; the machine replaces only the control flow. See [Migrating from a hand-rolled loop](docs/from-a-loop.md).
21
21
  - **Copy a known pattern.** ReAct, reflection, plan-and-execute, RAG, supervisor, and more, each a single runnable file you lift in 60 seconds. See [Agent patterns](docs/patterns.md).
22
22
 
23
23
  ## Install
@@ -120,8 +120,6 @@ When the machine reaches `refunded`, the result is:
120
120
 
121
121
  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.
122
122
 
123
- `createScriptedExecutors` plays back canned answers through the same executor contract, so the machine above runs end to end before a model is involved. **No API key needed:**
124
-
125
123
  ```ts
126
124
  import { createScriptedExecutors } from "@statelyai/agent";
127
125
 
@@ -131,7 +129,7 @@ const result = await runAgent(refundMachine, {
131
129
  });
132
130
  ```
133
131
 
134
- Swap in `createAiSdkExecutors({ models })` when you want a real model. The scripted set is what your tests keep using.
132
+ Scripted executors run the machine above end to end with no API key; swap in `createAiSdkExecutors({ models })` for a real model. See [Hosts and executors](docs/hosts.md).
135
133
 
136
134
  ## Architecture
137
135
 
@@ -149,18 +147,7 @@ The machine never talks to a model directly, so swapping `createAiSdkExecutors`
149
147
 
150
148
  The example above has one model decision and two final outcomes. Real machines add approval states, retries, parallel work, child agents, and long-running waits without changing how control flow is represented.
151
149
 
152
- ## Core concepts
153
-
154
- <!-- core concepts derived from setupAgent, built-in agent actors, runAgent, and XState snapshots -->
155
-
156
- - **Machines own control flow.** States, events, transitions, and guards define what can happen.
157
- - **Models make bounded decisions.** `agent.decide` asks a model to choose one of the events accepted by the current state.
158
- - **Requests are typed.** Inputs, outputs, context, and events use Standard Schema. Zod works out of the box.
159
- - **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.
160
- - **Snapshots can be stored.** An agent can stop for human input, save its XState snapshot, and resume later in another process.
161
- - **Runs export verified replay entries.** Every `runAgent` result carries a JSON-safe `AgentLogEntry[]` with event identity, timestamp, machine version, and state/effect hashes; pass it to `replay` or `verifyReplay` without repeating model or tool calls.
162
- - **Machines can be checked without model calls.** Lint their structure, simulate scripted decisions, and explore paths without an API key.
163
- - **Agents are XState machines.** Guards, actors, parallel states, inspection, testing, and visualization work as usual.
150
+ The core concepts (machines owning control flow, bounded model decisions, typed requests, host-run executors, storable snapshots, verified replay entries) are in the [documentation overview](docs/index.md).
164
151
 
165
152
  ## Examples
166
153
 
@@ -174,7 +161,7 @@ The example above has one model decision and two final outcomes. Real machines a
174
161
 
175
162
  See [all examples](examples/README.md).
176
163
 
177
- ## Learn more
164
+ ## Related
178
165
 
179
166
  - [Machines](docs/machines.md)
180
167
  - [Text requests](docs/text-requests.md)
@@ -190,5 +177,5 @@ See [all examples](examples/README.md).
190
177
  - [Observability](docs/observability.md)
191
178
  - [Usage and budgets](docs/usage-and-budgets.md)
192
179
  - [Agent patterns](docs/patterns.md)
193
- - [Migrating from a loop](docs/from-a-loop.md)
194
- - [LangGraph vs agent machines](docs/langgraph-comparison.md)
180
+ - [Migrating from a hand-rolled loop](docs/from-a-loop.md)
181
+ - [Coming from LangGraph](docs/langgraph-comparison.md)
@@ -483,10 +483,7 @@
483
483
  },
484
484
  "guard": {
485
485
  "description": "Either a whole-string {{ }} expression evaluated as truthy/falsy, or a named guard reference resolved against the `guards` passed to setupAgent.fromConfig(config, { guards }). Object guards ({ type, params }) are rejected by the lowering.",
486
- "anyOf": [
487
- { "$ref": "#/$defs/ExpressionString" },
488
- { "$ref": "#/$defs/Identifier" }
489
- ]
486
+ "anyOf": [{ "$ref": "#/$defs/ExpressionString" }, { "$ref": "#/$defs/Identifier" }]
490
487
  },
491
488
  "assign": {
492
489
  "description": "Context assignments applied when this transition is taken.",