Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
4aa6eb2
feat(ai-orchestration): scaffold package
AlemTuzlak May 10, 2026
06e4f54
feat(ai-orchestration): add core public types
AlemTuzlak May 10, 2026
826920c
feat(ai-orchestration): add in-memory RunStore
AlemTuzlak May 10, 2026
8b39b2f
fix(ai-orchestration): align with repo lint conventions
AlemTuzlak May 10, 2026
03f95d8
feat(ai-orchestration): add approve, bindAgents, and retry primitives
AlemTuzlak May 10, 2026
fbb1114
feat(ai-orchestration): add state snapshot/diff and AG-UI event emit …
AlemTuzlak May 10, 2026
24702c6
feat(ai-orchestration): agent invocation with three return shapes
AlemTuzlak May 10, 2026
f2fcaaa
feat(ai-orchestration): workflow engine drive loop
AlemTuzlak May 10, 2026
916055a
fix(ai-orchestration): persist resumed state, share pendingEvents que…
AlemTuzlak May 10, 2026
2592f84
feat(ai-orchestration): public API helpers, SSE response, and index e…
AlemTuzlak May 10, 2026
8b3423a
feat(ai-client): WorkflowClient
AlemTuzlak May 10, 2026
018763d
feat(ai-react): useWorkflow + useOrchestration
AlemTuzlak May 10, 2026
c1334db
feat(ts-react-chat): article workflow demo
AlemTuzlak May 10, 2026
f8ce39d
feat(ts-react-chat): feature orchestrator demo
AlemTuzlak May 10, 2026
87d7129
feat(ts-react-chat): workflow & orchestration API routes
AlemTuzlak May 10, 2026
cf11d43
feat(ts-react-chat): workflow + orchestration demo pages
AlemTuzlak May 10, 2026
7b07432
test(ai-orchestration): engine smoke tests
AlemTuzlak May 10, 2026
de7f442
refactor(ai-orchestration): collapse runWorkflow/resumeWorkflow into …
AlemTuzlak May 10, 2026
2d273ac
refactor(ai-orchestration): drop toWorkflowSSEResponse wrapper
AlemTuzlak May 10, 2026
802548d
fix(ai-orchestration): make StepGenerator TNext=any so heterogeneous …
AlemTuzlak May 10, 2026
0c30b69
feat(ai-orchestration): pass agents map to orchestrator router for ty…
AlemTuzlak May 10, 2026
32a1987
refactor(ts-react-chat): simplify orchestrator router to be cast-free
AlemTuzlak May 10, 2026
a7bac73
chore(ts-react-chat): use toServerSentEventsResponse directly
AlemTuzlak May 10, 2026
5c2c310
feat(ai-orchestration): ok/fail result helpers
AlemTuzlak May 10, 2026
400dc3d
refactor(ai-orchestration): rename ok to succeed
AlemTuzlak May 10, 2026
58be487
feat(ai-orchestration): add defineRouter helper for extracted routers
AlemTuzlak May 10, 2026
aad5d98
refactor(ts-react-chat): drop redundant initialize and use defineRouter
AlemTuzlak May 10, 2026
95f095f
feat(ai-client): add endpoint shortcut for useWorkflow
AlemTuzlak May 10, 2026
247712b
refactor(ts-react-chat): use endpoint shortcut in demo pages
AlemTuzlak May 10, 2026
dd4bb66
feat(ai-orchestration): add handleWorkflowRequest server helper
AlemTuzlak May 10, 2026
5594a91
refactor(ts-react-chat): use handleWorkflowRequest in API routes
AlemTuzlak May 10, 2026
1473ace
refactor(ai-client): drop endpoint shortcut from WorkflowClient
AlemTuzlak May 10, 2026
474b73f
feat(ai-client): add fetchWorkflowEvents adapter helper
AlemTuzlak May 10, 2026
2e743ac
feat(ai-react): re-export fetchWorkflowEvents and FetchWorkflowEvents…
AlemTuzlak May 10, 2026
878dcfe
refactor(ai-orchestration): replace handleWorkflowRequest with parseW…
AlemTuzlak May 10, 2026
6253eee
refactor(ts-react-chat): use fetchWorkflowEvents + parseWorkflowRequest
AlemTuzlak May 10, 2026
9bbbc83
fix(ai-orchestration): default-import fast-json-patch for ESM/CJS int…
AlemTuzlak May 10, 2026
b7e7843
refactor(ai-orchestration): hand-roll JSON Patch differ, drop fast-js…
AlemTuzlak May 10, 2026
cefd387
fix(ai-react): stabilize useWorkflow client identity (mirror useChat …
AlemTuzlak May 10, 2026
6256f20
fix(ai-orchestration): share dispatch loop so resume handles full des…
AlemTuzlak May 10, 2026
37e31f3
feat(ts-react-chat): editorial-brutalist redesign of workflow + orche…
AlemTuzlak May 10, 2026
85224f3
feat(ai-orchestration,ai-client): stream workflow output through RUN_…
AlemTuzlak May 10, 2026
c0202ef
feat(ai-orchestration,ai-react): support free-text feedback on approv…
AlemTuzlak May 10, 2026
6db5d96
feat(ts-react-chat): article revision loop with editor feedback and 3…
AlemTuzlak May 10, 2026
f87140b
feat(ts-react-chat): live DraftPreview in workflow right column
AlemTuzlak May 10, 2026
9880c45
feat: finalize approval step on resume + modal preview of published a…
AlemTuzlak May 10, 2026
16354b7
ci: apply automated fixes
autofix-ci[bot] May 10, 2026
1db8896
Merge remote-tracking branch 'origin/main' into worktree-cryptic-sing…
AlemTuzlak May 15, 2026
af87834
feat(ai-orchestration): accept streaming structured output, surface l…
AlemTuzlak May 15, 2026
efe80c1
feat(ts-react-chat): streaming structured output demos + terminal orc…
AlemTuzlak May 15, 2026
f6c67ea
ci: apply automated fixes
autofix-ci[bot] May 15, 2026
40bb4ad
Merge remote-tracking branch 'origin/main' into worktree-cryptic-sing…
AlemTuzlak May 20, 2026
af0d484
chore: satisfy stricter lint + knip after merging main
AlemTuzlak May 20, 2026
a19e83d
docs(ai-orchestration): add Workflows & Orchestration section + agent…
AlemTuzlak May 20, 2026
0f66212
ci: apply automated fixes
autofix-ci[bot] May 20, 2026
5486c02
Feat/durable workflows (#589)
AlemTuzlak May 20, 2026
7322d91
chore(ai-orchestration): satisfy strict lint + override after #589
AlemTuzlak May 20, 2026
62bb9d6
test(ai-orchestration): apply test-hygiene to the engine tests
AlemTuzlak May 20, 2026
5c8d49c
chore: regenerate routeTree.gen.ts
AlemTuzlak May 20, 2026
73adcc1
chore(cr-loop): fix docs/packaging/configs/tests bucket (a) findings
AlemTuzlak May 20, 2026
b9d3fcd
fix(ts-react-chat): example-app bucket (a) findings from cr-loop
AlemTuzlak May 20, 2026
5abad6c
ci: apply automated fixes
autofix-ci[bot] May 20, 2026
ecc1431
chore(ai-orchestration): two low-risk engine fixes from cr-loop
AlemTuzlak May 20, 2026
e86b405
fix(ai-orchestration): land remaining bucket (a) engine + client fixe…
AlemTuzlak May 20, 2026
b6f1836
ci: apply automated fixes
autofix-ci[bot] May 20, 2026
04dcab8
fix(orchestration): address CodeRabbit review feedback
AlemTuzlak May 20, 2026
3288d6a
Merge branch 'main' into worktree-cryptic-singing-wadler
AlemTuzlak May 20, 2026
3a51d7b
ci: apply automated fixes
autofix-ci[bot] May 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .agent/self-learning/coupling.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"$schema": "./coupling.schema.json",
"couplings": [
{
"id": "ai-source-touches-agent-skills",
Expand All @@ -16,10 +15,11 @@
"packages/typescript/ai/skills/ai-core/ag-ui-protocol/SKILL.md",
"packages/typescript/ai/skills/ai-core/debug-logging/SKILL.md",
"packages/typescript/ai/skills/ai-core/custom-backend-integration/SKILL.md",
"packages/typescript/ai-code-mode/skills/ai-code-mode/SKILL.md"
"packages/typescript/ai-code-mode/skills/ai-code-mode/SKILL.md",
"packages/typescript/ai-orchestration/skills/ai-orchestration/SKILL.md"
],
"kind": "change-required",
"why": "Agent skills are a contract with downstream coding agents. When the source surface they cover changes (new public API, changed type, new pattern, removed pattern, deprecation), the skill must be updated in the same PR — otherwise agents reading the skill keep generating obsolete or wrong code targeting a surface that no longer exists. Use this list to decide which skill(s) cover the file you're touching: `activities/chat/**` → chat-experience / structured-outputs / tool-calling; `activities/generateImage|generateAudio|generateVideo|generateSpeech|generateTranscription|summarize/**` → media-generation; `middleware/**` → middleware; `protocol/**` → ag-ui-protocol; `adapters/**` or anything that affects the adapter contract → adapter-configuration. Skip only for pure refactors / perf / internal-only changes that don't surface a new pattern or change observable behavior."
"why": "Agent skills are a contract with downstream coding agents. When the source surface they cover changes (new public API, changed type, new pattern, removed pattern, deprecation), the skill must be updated in the same PR — otherwise agents reading the skill keep generating obsolete or wrong code targeting a surface that no longer exists. Use this list to decide which skill(s) cover the file you're touching: `activities/chat/**` → chat-experience / structured-outputs / tool-calling; `activities/generateImage|generateAudio|generateVideo|generateSpeech|generateTranscription|summarize/**` → media-generation; `middleware/**` → middleware; `protocol/**` → ag-ui-protocol; `adapters/**` or anything that affects the adapter contract → adapter-configuration; `packages/typescript/ai-orchestration/src/**` → ai-orchestration. Skip only for pure refactors / perf / internal-only changes that don't surface a new pattern or change observable behavior."
}
]
},
Expand All @@ -39,7 +39,8 @@
"docs/protocol/**/*.md",
"docs/media/**/*.md",
"docs/code-mode/**/*.md",
"docs/migration/**/*.md"
"docs/migration/**/*.md",
"docs/orchestration/**/*.md"
],
"kind": "change-required",
"why": "Public docs are the canonical source for users. When the source surface they describe changes — new capability, behavior change, deprecation — the docs must be updated in the same PR. Cases to watch for: (1) the new behavior contradicts existing doc advice (e.g. removing a hack the doc still recommends); (2) the new capability opens a use case no existing page covers (consider whether a new page is needed, plus nav config and cross-links); (3) a public type / function gains or loses generic parameters, optional fields, etc. Run `pnpm test:docs` after editing to catch cross-link rot. Skip only for pure refactors / perf / internal-only changes."
Expand Down
366 changes: 366 additions & 0 deletions docs/api/ai-orchestration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,366 @@
---
title: "@tanstack/ai-orchestration"
id: tanstack-ai-orchestration-api
order: 8
description: "API reference for @tanstack/ai-orchestration — defineAgent, defineWorkflow, defineOrchestrator, approve(), retry(), runWorkflow, inMemoryRunStore, and the workflow run types."
keywords:
- tanstack ai
- "@tanstack/ai-orchestration"
- defineAgent
- defineWorkflow
- defineOrchestrator
- approve
- retry
- runWorkflow
- RunStore
- api reference
---

Generator-based workflows and orchestrators for TanStack AI. Compose typed agents with `yield*`, route dynamically with a router generator, pause for approvals, and stream every step as AG-UI events.

For guided journeys see the [Workflows & Orchestration](../orchestration/overview) section.

## Installation

```bash
npm install @tanstack/ai-orchestration
```

Peer dependency: `@tanstack/ai`.

## `defineAgent(config)`

Wrap a function or `chat()` call as a typed agent.

```typescript
import { defineAgent } from "@tanstack/ai-orchestration";
import { chat } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";
import { z } from "zod";

const translate = defineAgent({
name: "translate",
input: z.object({ text: z.string(), target: z.string() }),
output: z.object({ translated: z.string() }),
run: ({ input }) =>
chat({
adapter: openaiText("gpt-5.2"),
outputSchema: z.object({ translated: z.string() }),
stream: true,
messages: [
{ role: "user", content: `Translate to ${input.target}: ${input.text}` },
],
}),
});
```

### Config

| Field | Type | Description |
|---|---|---|
| `name` | `string` | Unique step name used in events |
| `description` | `string?` | Optional, surfaced in observability |
| `input` | `StandardSchemaV1?` | Validated before `run` is called. `SchemaValidationError` thrown on failure. |
| `output` | `StandardSchemaV1?` | Validated after `run` produces a value. `SchemaValidationError` thrown on failure. |
| `run` | `(args) => AgentRunResult<TOutput>` | The agent body. See return shapes below. |

### `run` argument

`{ input, emit, signal }` — `input` is the typed, validated input. `emit(name, value)` pushes a `CUSTOM` event to the client. `signal` is an `AbortSignal` you can pass to anything that accepts one natively (e.g. `fetch`). For forwarding into `chat()`, bridge to an `AbortController` — see [Retries & Errors](../orchestration/retries-and-errors#3-honor-abort-signals).

### `run` return shapes

| Shape | When |
|---|---|
| `Promise<TOutput>` | Non-LLM agents (DB fetch, computation). |
| `StructuredOutputStream<TOutput>` | `chat({ outputSchema, stream: true })`. The runtime drains and parses. |
| `AsyncIterable<StreamChunk>` | A raw `chat()` stream (no `outputSchema`). Final output parsed from accumulated text. |
| `{ stream, output }` | Manual split — your own stream and a separately-resolved typed value. |

## `defineWorkflow(config)`

Compose agents into a linear generator-based workflow.

```typescript
import { defineWorkflow } from "@tanstack/ai-orchestration";
import { z } from "zod";

const pipeline = defineWorkflow({
name: "pipeline",
input: z.object({ text: z.string() }),
output: z.object({ summary: z.string() }),
agents: { translate, summarize },
run: async function* ({ input, agents }) {
const t = yield* agents.translate({ text: input.text, target: "english" });
const s = yield* agents.summarize({ text: t.translated });
return { summary: s.summary };
},
});
```

### Config

| Field | Type | Description |
|---|---|---|
| `name` | `string` | |
| `description` | `string?` | |
| `version` | `string?` | Caller-supplied version label (e.g. `'v1'`). Used by `selectWorkflowVersion` / `createWorkflowRegistry` to route resumes to the right version when running multiple versions side-by-side. |
| `patches` | `ReadonlyArray<string>?` | Opt into patch-versioned fingerprint mode. Workflows declaring `patches` use a lighter fingerprint (name + sorted patches) so code-body changes don't trigger `workflow_version_mismatch` on resume; compatibility is enforced by the `startingPatches ⊆ current patches` check. |
| `defaultStepRetry` | `StepRetryOptions?` | Fallback retry policy applied to `step()` calls that don't carry their own `{ retry }`. |
| `input` | `StandardSchemaV1?` | |
| `output` | `StandardSchemaV1?` | |
| `state` | `StandardSchemaV1?` | Shape of mutable state available to the generator. |
| `agents` | `AgentMap` | Record of `defineAgent(...)` or `defineWorkflow(...)` instances. |
| `initialize` | `(args) => Partial<TState>` (optional field) | Seed initial state from input. The function itself is optional; when present it returns `Partial<TState>`. |
| `run` | `(args) => AsyncGenerator<StepDescriptor, TOutput, unknown>` | Generator body. `yield*` agents to compose. |

`run` argument: `{ input, state, agents, emit, signal }`. `state` is mutable. `agents` is the typed bound map — call `agents.someAgent({...})` and `yield*` the result.

## `defineOrchestrator(config)`

A workflow whose `run` body is a routing loop. You write a `router` generator that picks the next agent each turn.

```typescript
import { defineOrchestrator } from "@tanstack/ai-orchestration";

const orchestrator = defineOrchestrator({
...sharedConfig,
name: "feature-orchestrator",
maxTurns: 20,
router: function* ({ agents, state, lastResult }) {
const triage = yield* agents.triage({ /* ... */ });
if (triage.next === "done") return { done: true, output: { /* ... */ } };
return { agent: triage.next, input: { /* ... */ } };
},
});
```

### Config

Inherits all fields from `defineWorkflow`, plus:

| Field | Type | Description |
|---|---|---|
| `router` | `(args) => StepGenerator<RouterDecision>` | Routing generator. |
| `maxTurns` | `number?` | Max router iterations before throwing. Default `12`. |

### `router` argument

`{ input, state, agents, turn, lastResult }`. `turn` is the 0-indexed iteration count. `lastResult` is the typed output of the agent dispatched on the previous turn (`undefined` on turn 0).

### `RouterDecision`

```typescript
type RouterDecision =
| { done: true; output: TOutput }
| { done?: false; agent: keyof TAgents; input: unknown };
```

## `defineRouter(config, router)`

Phantom-config helper for pulling the router out of the `defineOrchestrator` call while preserving inference.

```typescript
const config = { agents, input, output, state };
const myRouter = defineRouter(config, function* ({ agents, state }) {
// `agents` and `state` are typed here.
return { done: true, output: { /* ... */ } };
});
defineOrchestrator({ ...config, name: "...", router: myRouter });
```

The first argument is ignored at runtime — it exists only so TypeScript can infer the router's `agents` / `input` / `output` / `state` types.

## `approve(options)`

Yieldable approval primitive. Pauses the run, emits `approval-requested`, closes the SSE, resumes on the next client request.

```typescript
const decision = yield* approve({
title: "Implement?",
description: "5 files to patch",
});
if (!decision.approved) throw new Error(decision.feedback ?? "Declined");
```

| Option | Type | |
|---|---|---|
| `title` | `string` | Required. Shown by the client. |
| `description` | `string?` | Optional detail. |

Returns `ApprovalResult`:

```typescript
interface ApprovalResult {
approved: boolean;
approvalId: string;
feedback?: string;
}
```

## `retry(fn, options)`

Retry a yieldable step on failure.

```typescript
const draft = yield* retry(
() => agents.writer({ topic }),
{ attempts: 3, backoff: "exponential", baseDelayMs: 200 },
);
```

| Option | Default | |
|---|---|---|
| `attempts` | — | Total attempts. Required. |
| `backoff` | `'none'` | `'none' \| 'linear' \| 'exponential'` |
| `baseDelayMs` | `100` | Base delay. |
| `maxDelayMs` | `5000` | Max delay cap. |
| `retryOn` | retry any | `(err, attempt) => boolean`. Return `false` to surface the error. |

## `runWorkflow(options)`

Server-side: run a workflow (or orchestrator) and stream AG-UI events.

```typescript
import { toServerSentEventsResponse } from "@tanstack/ai";
import {
inMemoryRunStore,
parseWorkflowRequest,
runWorkflow,
} from "@tanstack/ai-orchestration";

const runStore = inMemoryRunStore({ ttl: 60 * 60 * 1000 });

export async function POST(request: Request) {
const params = await parseWorkflowRequest(request);
if (params.abort && params.runId) {
runStore.getLive(params.runId)?.abortController.abort();
return new Response(null, { status: 204 });
}
const stream = runWorkflow({ workflow, runStore, ...params });
return toServerSentEventsResponse(stream);
}
```

| Option | Type | |
|---|---|---|
| `workflow` | `WorkflowDefinition` | Required. The workflow or orchestrator. |
| `runStore` | `InMemoryRunStore` | Required. (Engine accepts the in-memory shape today; widening to the general `RunStore` interface is on the roadmap.) |
| `input` | `unknown?` | Provide on the *first* call to start a run. |
| `runId` | `string?` | Provide alongside `approval` or `signalDelivery` to resume a paused run. Also accepted on a fresh start to opt into client-supplied IDs (idempotent retry then becomes possible). |
| `approval` | `ApprovalResult?` | Provide alongside `runId` to resume a run paused on `approve()`. |
| `signalDelivery` | `SignalResult?` | Provide alongside `runId` to resume a run paused on `waitForSignal()` / `sleep()`. Carries a `signalId` for idempotent retry. |
| `attach` | `boolean?` | Read-only attach to an existing run (read snapshot + steps; do not drive). |
| `signal` | `AbortSignal?` | Optional external abort. |
| `threadId` | `string?` | Optional correlation ID surfaced in events. |
| `outputSink` | `(output) => void?` | Called with the final output before the store entry is deleted. |
| `publish` | `(runId, event) => Promise<void>?` | Multi-node publisher hook. Errors thrown by the hook are swallowed so a misbehaving publisher can't break the run. |

Returns `AsyncIterable<StreamChunk>` — pipe directly to `toServerSentEventsResponse`.

## `parseWorkflowRequest(request)`

Parse a POST body into `runWorkflow` params.

```typescript
const params = await parseWorkflowRequest(request);
// { input?, runId?, approval?, signalDelivery?, abort? }
```

The HTTP body field name for `signalDelivery` is `signal` — the parser renames it on the way through.

## `inMemoryRunStore(options)`

Single-process run store. Holds `RunState`, the append-only step log, and the live generator handle so the engine can resume in-process.

```typescript
const runStore = inMemoryRunStore({ ttl: 60 * 60 * 1000 });
```

| Option | Default | |
|---|---|---|
| `ttl` | `60 * 60 * 1000` | TTL in ms. Resets on every `setRunState` / `appendStep`. After expiry the run state, live handle, and step log are dropped. |

Returns `InMemoryRunStore` which extends `RunStore` with `setLive` / `getLive` for the engine-internal live generator handle.

For durable persistence options see [Run Persistence](../orchestration/run-persistence).

## `fail(...)` / `succeed(...)`

Result helpers exported for use in agent / workflow bodies that prefer a Result-typed return over throw/return.

```typescript
import { fail, succeed } from "@tanstack/ai-orchestration";

return succeed({ patches });
// or
return fail("Spec didn't validate");
```

## `SchemaValidationError`

Thrown when input or output validation fails inside an agent.

```typescript
import { SchemaValidationError } from "@tanstack/ai-orchestration";

try {
// ...
} catch (err) {
if (err instanceof SchemaValidationError) {
console.error(err.message, err.issues);
}
}
```

`issues` is a `ReadonlyArray<unknown>` containing the Standard Schema validation issues.

## Types

| Type | Description |
|---|---|
| `AgentDefinition` | The return type of `defineAgent`. |
| `WorkflowDefinition` | The return type of `defineWorkflow` and `defineOrchestrator`. |
| `AgentMap` | `Record<string, AgentDefinition \| WorkflowDefinition>` |
| `AgentRunArgs<TInput>` | `{ input, emit, signal }` |
| `AgentRunResult<TOutput>` | Union of the four allowable agent return shapes |
| `WorkflowRunArgs<TInput, TState, TAgents>` | `{ input, state, agents, emit, signal }` |
| `BoundAgents<TAgents>` | Typed callable map injected into workflow / router bodies |
| `StepDescriptor` | What the engine sees on `yield`. Tagged `'agent' \| 'nested-workflow' \| 'approval' \| 'step' \| 'signal' \| 'now' \| 'uuid' \| 'patched'`. |
| `StepGenerator<T>` | `Generator<StepDescriptor, T, any>` — what `agents.*(...)` and the durable primitives return. |
| `StepRecord` | Persisted record for a single step in the log. Tagged by `kind: StepKind`. |
| `StepKind` | Union of step record kinds; matches the descriptor tag set. |
| `StepRetryOptions` | `{ maxAttempts, backoff?, baseMs?, maxMs?, shouldRetry? }` — the `step({ retry })` policy shape. |
| `ApprovalResult` | `{ approved, approvalId, feedback? }` |
| `SignalResult<TPayload>` | `{ signalId, payload }` — delivered to `waitForSignal()` pauses. |
| `RouterDecision` | `{ done: true, output } \| { done?: false, agent, input }` |
| `RunState` | Serializable snapshot of a run. Includes `workflowVersion`, `fingerprint`, `startingPatches`, `waitingFor` for durable resume. |
| `RunStatus` | `'running' \| 'paused' \| 'finished' \| 'error' \| 'aborted'` |
| `RunStore` | Persistence interface: `getRunState` / `setRunState` / `deleteRun` / `appendStep` / `getSteps`. |
| `InMemoryRunStore` | Extends `RunStore` with `setLive` / `getLive` for the in-process live generator handle. |
| `LogConflictError` | Thrown by `appendStep` when another writer has already committed at `expectedNextIndex`. Carries `runId`, `attemptedIndex`, and optionally `existing` (the conflicting record). |
| `StepTimeoutError` | Thrown when a `step({ timeout })` exceeds its wall-clock budget on a given attempt. |
| `DeleteReason` | `'finished' \| 'error' \| 'aborted'` |
| `EmitFn` | `(name, value) => void` |
| `LiveRun` | Engine-internal live handle (live generator, abort controller, etc). |

## Client-side hooks

The companion client hooks live in framework packages:

- `useWorkflow` — `@tanstack/ai-react` (and other framework packages as they land)
- `useOrchestration` — same hook, re-exported under a routing-friendly name
- `WorkflowClient` — `@tanstack/ai-client` for vanilla / non-React clients
- `fetchWorkflowEvents(url, options?)` — connection adapter, exported from `@tanstack/ai-client` and `@tanstack/ai-react`

The hook exposes the following actions on the returned object:

| Action | Signature | Purpose |
|---|---|---|
| `start` | `(input, options?: { runId? }) => Promise<void>` | Kick off a new run. Pass `runId` to opt into client-supplied IDs for idempotent retry. |
| `approve` | `(approved, feedback?) => Promise<void>` | Resolve a pending approval. |
| `signal` | `(name, payload, { signalId? }?) => Promise<void>` | Deliver a `waitForSignal()` payload. |
| `attach` | `(runId) => Promise<void>` | Read-only attach to an existing run (browser refresh, second tab). |
| `stop` | `() => void` | Abort the run. |

See the framework-specific [`@tanstack/ai-react` reference](./ai-react) for hook signatures.
Loading
Loading