Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 26 additions & 4 deletions docs/content/docs/api-reference/workflow-ai/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,35 @@ related:

Helpers for integrating AI SDK for building AI-powered workflows.

## Classes
## Root Exports (`@workflow/ai`)

The root `@workflow/ai` entrypoint exports:

<Cards>
<Card title="DurableAgent" href="/docs/api-reference/workflow-ai/durable-agent">
A class for building durable AI agents that maintain state across workflow steps and handle tool execution with automatic retries.
</Card>
<Card title="WorkflowChatTransport" href="/docs/api-reference/workflow-ai/workflow-chat-transport">
A drop-in transport for the AI SDK for automatic reconnection in interrupted streams.
</Card>
</Cards>

It also re-exports the `ModelMessage` type from the AI SDK for convenience.

## Agent (`@workflow/ai/agent`)

The `@workflow/ai/agent` subpath exports the `DurableAgent` class and related types:

<Cards>
<Card title="DurableAgent" href="/docs/api-reference/workflow-ai/durable-agent">
A class for building durable AI agents that maintain state across workflow steps and handle tool execution with automatic retries.
</Card>
</Cards>

## Provider Subpaths

Model provider wrappers are available as separate subpath imports:

- `@workflow/ai/anthropic` — Anthropic provider
- `@workflow/ai/openai` — OpenAI provider
- `@workflow/ai/google` — Google provider
- `@workflow/ai/gateway` — Gateway provider
- `@workflow/ai/xai` — xAI provider
- `@workflow/ai/test` — Mock provider for testing
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
title: getHookByToken
description: Retrieve hook details and workflow run information by token.
description: Retrieve hook details, metadata, and associated run ID by token.
type: reference
summary: Use getHookByToken to look up a hook's metadata and associated workflow run before resuming it.
summary: Use getHookByToken to look up a hook's metadata and associated run ID before resuming it.
prerequisites:
- /docs/foundations/hooks
---

Retrieves a hook by its unique token, returning the associated workflow run information and any metadata that was set when the hook was created. This function is useful for inspecting hook details before deciding whether to resume a workflow.
Retrieves a hook by its unique token, returning hook details, the associated run ID, and any metadata that was set when the hook was created. Metadata is automatically hydrated (deserialized) before being returned, so you receive the original values rather than raw serialized data. This function is useful for inspecting hook details before deciding whether to resume a workflow.

<Callout type="warn">
`getHookByToken` is a runtime function that must be called from outside a workflow function.
Expand Down
16 changes: 8 additions & 8 deletions docs/content/docs/api-reference/workflow-api/index.mdx
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
---
title: "workflow/api"
description: Runtime functions to inspect runs, start workflows, and access world data.
description: Runtime functions for starting workflows, inspecting runs, resuming hooks, and accessing world data.
type: overview
summary: Explore runtime functions for starting workflows, inspecting runs, and managing hooks.
summary: Explore runtime functions across the workflow/api and workflow/runtime entrypoints.
---

API reference for runtime functions from the `workflow/api` package.
API reference for runtime functions from the `workflow/api` and `workflow/runtime` entrypoints.

## Functions

The API package is for access and introspection of workflow data to inspect runs, start new runs, or access anything else directly accessible by the world.
Most functions in this section are imported from `workflow/api`. `getWorld()` is imported from `workflow/runtime`.

<Cards>
<Card href="/docs/api-reference/workflow-api/start" title="start()">
Start/enqueue a new workflow run.
</Card>
<Card href="/docs/api-reference/workflow-api/resume-hook" title="resumeHook()">
Resume a workflow by sending a payload to a hook.
Resume a hook created with `createHook()` by sending an arbitrary payload.
</Card>
<Card href="/docs/api-reference/workflow-api/resume-webhook" title="resumeWebhook()">
Resume a workflow by sending a `Request` to a webhook.
Resume a webhook created with `createWebhook()` by forwarding an HTTP `Request`.
</Card>
<Card href="/docs/api-reference/workflow-api/get-hook-by-token" title="getHookByToken()">
Get hook details and metadata by its token.
Retrieve hook details, metadata, and run information by token.
</Card>
<Card href="/docs/api-reference/workflow-api/get-run" title="getRun()">
Get workflow run status and metadata without waiting for completion.
</Card>
<Card href="/docs/api-reference/workflow-api/get-world" title="getWorld()">
Async: resolve the World instance for storage, queuing, and streaming backends.
Get direct access to workflow storage, queuing, and streaming backends from `workflow/runtime`.
</Card>
<Card href="/docs/api-reference/workflow-api/world" title="World SDK">
Low-level API for inspecting runs, steps, events, hooks, streams, and queues.
Expand Down
109 changes: 79 additions & 30 deletions docs/content/docs/api-reference/workflow-api/resume-hook.mdx
Original file line number Diff line number Diff line change
@@ -1,35 +1,67 @@
---
title: resumeHook
description: Resume a paused workflow by sending a payload to a hook token.
description: Resume a paused workflow by sending a payload to a hook token or hook object.
type: reference
summary: Use resumeHook to send a payload to a hook token and resume a paused workflow.
summary: Use resumeHook to send a payload to a hook token or hook object and resume a paused workflow.
prerequisites:
- /docs/foundations/hooks
related:
- /docs/api-reference/workflow-api/resume-webhook
---

Resumes a workflow run by sending a payload to a hook identified by its token.
Resumes a workflow run by sending a payload to a hook identified by its token or an existing hook object.

It creates a `hook_received` event and re-triggers the workflow to continue execution.
`resumeHook()` returns the resumed hook entity, not the workflow's eventual return value. This is useful when you need the associated `runId`, `hookId`, or hook metadata immediately after resumption.

It creates a `hook_received` event and re-queues the workflow so execution can continue. Use `resumeHook()` for hooks created with [`createHook()`](/docs/api-reference/workflow/create-hook), whether the token was explicitly set or auto-generated. For hooks created with [`createWebhook()`](/docs/api-reference/workflow/create-webhook), use [`resumeWebhook()`](/docs/api-reference/workflow-api/resume-webhook) instead.

<Callout type="warn">
`resumeHook` is a runtime function that must be called from outside a workflow function.
</Callout>

```typescript lineNumbers
import { resumeHook } from "workflow/api";
import { HookNotFoundError } from "workflow/errors";

export async function POST(request: Request) {
const { token, data } = await request.json();

try {
const result = await resumeHook(token, data); // [!code highlight]
const hook = await resumeHook(token, data); // [!code highlight]

console.info(JSON.stringify({
event: "workflow.hook.resumed",
token: hook.token,
hookId: hook.hookId,
runId: hook.runId,
}));

return Response.json({
runId: result.runId
runId: hook.runId,
});
} catch (error) {
return new Response("Hook not found", { status: 404 });
if (HookNotFoundError.is(error)) {
console.warn(JSON.stringify({
event: "workflow.hook.not_found",
token,
}));

return Response.json(
{ error: "Hook not found", token },
{ status: 404 }
);
}

console.error(JSON.stringify({
event: "workflow.hook.resume_failed",
token,
error: error instanceof Error ? error.message : String(error),
}));

return Response.json(
{ error: "Failed to resume hook" },
{ status: 500 }
);
}
}
```
Expand All @@ -41,6 +73,7 @@ export async function POST(request: Request) {
<TSDoc
definition={`
import { resumeHook } from "workflow/api";
import { HookNotFoundError } from "workflow/errors";
export default resumeHook;`}
showSections={["parameters"]}
/>
Expand All @@ -56,6 +89,12 @@ export default Hook;`}
showSections={["returns"]}
/>

## Error Behavior

A missing hook token is only one failure mode. `resumeHook()` can also fail while dehydrating the payload, creating the `hook_received` event, or re-queueing the workflow. In HTTP handlers, map missing hooks to `404` and unexpected failures to `500` so operational failures stay visible.

`resumeHook()` resolves to the hook record that was resumed. Use `hook.runId` with [`getRun()`](/docs/api-reference/workflow-api/get-run) if you want to inspect the workflow after resumption; it does not wait for the workflow to finish.

## Examples

### Basic API Route
Expand All @@ -64,19 +103,23 @@ Using `resumeHook` in a basic API route to resume a hook:

```typescript lineNumbers
import { resumeHook } from "workflow/api";
import { HookNotFoundError } from "workflow/errors";

export async function POST(request: Request) {
const { token, data } = await request.json();

try {
const result = await resumeHook(token, data); // [!code highlight]
const hook = await resumeHook(token, data); // [!code highlight]

return Response.json({
success: true,
runId: result.runId
runId: hook.runId
});
} catch (error) {
return new Response("Hook not found", { status: 404 });
if (HookNotFoundError.is(error)) {
return Response.json({ error: "Hook not found" }, { status: 404 });
}
return Response.json({ error: "Failed to resume hook" }, { status: 500 });
}
}
```
Expand All @@ -87,6 +130,7 @@ Defining a payload type and using `resumeHook` to resume a hook with type safety

```typescript lineNumbers
import { resumeHook } from "workflow/api";
import { HookNotFoundError } from "workflow/errors";

type ApprovalPayload = {
approved: boolean;
Expand All @@ -97,14 +141,17 @@ export async function POST(request: Request) {
const { token, approved, comment } = await request.json();

try {
const result = await resumeHook<ApprovalPayload>(token, { // [!code highlight]
const hook = await resumeHook<ApprovalPayload>(token, { // [!code highlight]
approved, // [!code highlight]
comment, // [!code highlight]
}); // [!code highlight]

return Response.json({ runId: result.runId });
return Response.json({ runId: hook.runId });
} catch (error) {
return Response.json({ error: "Invalid token" }, { status: 404 });
if (HookNotFoundError.is(error)) {
return Response.json({ error: "Hook not found" }, { status: 404 });
}
return Response.json({ error: "Failed to resume hook" }, { status: 500 });
}
}
```
Expand All @@ -117,40 +164,42 @@ Using `resumeHook` in Next.js server actions to resume a hook:
"use server";

import { resumeHook } from "workflow/api";
import { HookNotFoundError } from "workflow/errors";

export async function approveRequest(token: string, approved: boolean) {
try {
const result = await resumeHook(token, { approved });
return result.runId;
const hook = await resumeHook(token, { approved });
return hook.runId;
} catch (error) {
throw new Error("Invalid approval token");
throw new Error("Failed to resume hook");
}
}
```

### Webhook Handler
### Passing a Hook Object

Using `resumeHook` in a generic webhook handler to resume a hook:
Instead of a token string, you can pass a `Hook` object directly (e.g. one returned by [`getHookByToken()`](/docs/api-reference/workflow-api/get-hook-by-token)):

```typescript lineNumbers
import { resumeHook } from "workflow/api";
import { getHookByToken, resumeHook } from "workflow/api";
import { HookNotFoundError } from "workflow/errors";

// Generic webhook handler that forwards data to a hook
export async function POST(request: Request) {
const url = new URL(request.url);
const token = url.searchParams.get("token");

if (!token) {
return Response.json({ error: "Missing token" }, { status: 400 });
}
const { token, data } = await request.json();

try {
const body = await request.json();
const result = await resumeHook(token, body);
const hook = await getHookByToken(token);

// Validate metadata before resuming
console.log("Hook metadata:", hook.metadata);

return Response.json({ success: true, runId: result.runId });
const resumedHook = await resumeHook(hook, data); // [!code highlight]
return Response.json({ success: true, runId: resumedHook.runId });
} catch (error) {
return Response.json({ error: "Hook not found" }, { status: 404 });
if (HookNotFoundError.is(error)) {
return Response.json({ error: "Hook not found" }, { status: 404 });
}
return Response.json({ error: "Failed to resume hook" }, { status: 500 });
}
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ showSections={['parameters']}

### Returns

Returns a `Promise<Response>` that resolves to:
Returns a `Promise<Response>` that resolves to one of three outcomes:

- `Response`: The HTTP response from the workflow's `respondWith()` call
- A `202 Accepted` response when the webhook was created with the default mode (no `respondWith` option)
- The exact `Response` object configured with `createWebhook({ respondWith: new Response(...) })`
- The workflow's manual `Response` when the webhook was created with `createWebhook({ respondWith: 'manual' })` and a step calls `request.respondWith(response)`

Throws an error if the webhook token is not found or invalid.

Expand Down Expand Up @@ -81,7 +83,7 @@ export async function POST(request: Request) {

try {
const response = await resumeWebhook(token, request); // [!code highlight]
return response; // Returns the workflow's custom response
return response; // May be 202 Accepted, a configured static Response, or a manual workflow response
} catch (error) {
return new Response("Webhook not found", { status: 404 });
}
Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/api-reference/workflow-api/start.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Learn more about [`WorkflowReadableStreamOptions`](/docs/api-reference/workflow-
* When `deploymentId` is provided, the argument types and return type become `unknown` since there is no guarantee the workflow function's types will be consistent across different deployments.

<Callout type="info">
If `start()` throws `'start' received an invalid workflow function. Ensure the Workflow Development Kit is configured correctly and the function includes a 'use workflow' directive.`, the passed function was not transformed as a workflow. The two most common causes are a missing `"use workflow"` directive or missing framework integration. See [start-invalid-workflow-function](/docs/errors/start-invalid-workflow-function).
If `start()` throws `'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.`, the passed function was not transformed as a workflow. The two most common causes are a missing `"use workflow"` directive or missing framework integration. See [start-invalid-workflow-function](/docs/errors/start-invalid-workflow-function).
</Callout>

## Examples
Expand Down
Loading
Loading