Skip to content
Closed
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
4 changes: 2 additions & 2 deletions docs/content/docs/ai/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Our tools are mostly mocked out for the sake of the example. We use AI SDK's `to
import { tool } from "ai";
import { z } from "zod";

export const tools = {
export const flightBookingTools = {
searchFlights: tool({
description: "Search for flights",
inputSchema: z.object({ query: z.string() }),
Expand Down Expand Up @@ -256,7 +256,7 @@ Move the agent logic into a separate function, which will serve as our workflow
```typescript title="workflows/chat/workflow.ts" lineNumbers
import { DurableAgent } from "@workflow/ai/agent"; // [!code highlight]
import { getWritable } from "workflow"; // [!code highlight]
import { tools } from "@/ai/tools";
import { flightBookingTools } from "@/ai/tools";
import { openai } from "@workflow/ai/openai";
import type { ModelMessage, UIMessageChunk } from "ai";

Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/ai/resumable-streams.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export async function POST(req: Request) {

return createUIMessageStreamResponse({
stream: run.readable,
headers: { // [!code highlight
headers: { // [!code highlight]
"x-workflow-run-id": run.runId, // [!code highlight]
}, // [!code highlight]
});
Expand Down
6 changes: 4 additions & 2 deletions docs/content/docs/ai/sleep-and-delays.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Sleep is a built-in function in Workflow DevKit, so exposing it as a tool is as
Add a new "sleep" tool to the `tools` defined in `workflows/chat/steps/tools.ts`:

```typescript title="workflows/chat/steps/tools.ts" lineNumbers
import { getWritable, sleep } from "workflow"; // [!code highlight]
import { sleep } from "workflow"; // [!code highlight]

// ... existing imports ...

Expand Down Expand Up @@ -110,7 +110,7 @@ export default function ChatPage() {
part.type === "tool-checkFlightStatus" ||
part.type === "tool-getAirportInfo" ||
part.type === "tool-bookFlight" ||
part.type === "tool-checkBaggageAllowance"
part.type === "tool-checkBaggageAllowance" ||
part.type === "tool-sleep" // [!code highlight]
) {
// ...
Expand Down Expand Up @@ -162,6 +162,8 @@ Aside from providing `sleep()` as a tool, there are other use cases for Agents t
When hitting API rate limits, use `RetryableError` with a delay:

```typescript lineNumbers
import { RetryableError } from "workflow";

async function callRateLimitedAPI(endpoint: string) {
"use step";

Expand Down
6 changes: 3 additions & 3 deletions docs/content/docs/api-reference/workflow-api/get-world.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export async function GET(req: Request) {
Cancel a running workflow:

```typescript lineNumbers
import { getWorld } from "workflow/runtime";
import { getWorld, cancelRun } from "@workflow/core/runtime";
Copy link
Copy Markdown
Contributor

@pranaygp pranaygp Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nah the correct way to programmatically cancel a run is await getRun(runId).cancel() - not cancelRun from world. We don't adequately document it though so good call on making this. We should include an example in getRun api reference for cancelling a run so that it's searchable by AI. right now it's not well documented

Also users should almost never be importing from @workflow/core for normal usage. workflow/api should be what people use for normal behavior. using getWorld is an advanced/low level features that will break often as we change things around and not meant to be relied on

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using getWorld is an advanced/low level features that will break often as we change things around and not meant to be relied on

At least once we actually have a different way of querying the same data, which we won't for a while? In which case it wouldn't hurt to document. Users could already be relying on it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should document it and then have to support it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also like I said, for now the fix is simple. we have run.cancel(). let's document that instead of telling people to use @workflow/core/runtime which is never meant to be user facing

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As pranaygp noted in the earlier thread, this should use the public API:

import { getRun } from "workflow/runtime";

export async function POST(req: Request) {
  const { runId } = await req.json();
  // ...
  const run = getRun(runId);
  await run.cancel();
  return Response.json({ status: "cancelled" });
}

cancelRun from @workflow/core/runtime is an internal function — users should never import from @workflow/core directly. getRun(runId).cancel() is the supported public API for this (exported from workflow/runtime).


export async function POST(req: Request) {
const { runId } = await req.json();
Expand All @@ -79,9 +79,9 @@ export async function POST(req: Request) {

try {
const world = getWorld(); // [!code highlight]
const run = await world.runs.cancel(runId); // [!code highlight]
await cancelRun(world, runId); // [!code highlight]

return Response.json({ status: run.status });
return Response.json({ status: "cancelled" });
} catch (error) {
return Response.json(
{ error: "Failed to cancel workflow run" },
Expand Down
22 changes: 16 additions & 6 deletions docs/content/docs/deploying/building-a-world.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@ A World connects workflows to the infrastructure that powers them. The World int
```typescript
interface World extends Storage, Queue, Streamer {
start?(): Promise<void>;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified: the close?() and getEncryptionKeyForRun?() additions match the actual World interface in packages/world/src/interfaces.ts exactly. 👍

close?(): Promise<void>;
getEncryptionKeyForRun?(run: WorkflowRun): Promise<Uint8Array | undefined>;
getEncryptionKeyForRun?(runId: string, context?: Record<string, unknown>): Promise<Uint8Array | undefined>;
}
```

The optional `start()` method initializes any background tasks needed by your World (e.g., queue polling).
The optional `start()` method initializes background tasks (for example, queue polling). The optional `close()` method releases resources like connection pools and listeners. The optional `getEncryptionKeyForRun()` method returns the AES-256 key used to encrypt data for a run; if it is not implemented, encryption is disabled.

## The Event Log Model

Expand All @@ -63,8 +66,8 @@ interface Storage {
};

events: {
// Create a new workflow run (runId must be null - server generates it)
create(runId: null, data: RunCreatedEventRequest, params?: CreateEventParams): Promise<EventResult>;
// Create a new workflow run (runId may be client-provided or null for server generation)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: The source code doc comment (interfaces.ts:130) says: "The runId may be provided by the client or left as null for the server to generate." Consider matching this wording exactly for consistency between source and docs.

create(runId: string | null, data: RunCreatedEventRequest, params?: CreateEventParams): Promise<EventResult>;

// Create an event for an existing run
create(runId: string, data: CreateEventRequest, params?: CreateEventParams): Promise<EventResult>;
Expand All @@ -88,7 +91,7 @@ interface Storage {
2. Atomically update the affected entity (run, step, or hook)
3. Return both the created event and the updated entity

**Run Creation:** For `run_created` events, the `runId` parameter is `null`. Your World generates and returns a new `runId`.
**Run Creation:** For `run_created` events, the `runId` parameter may be a client-provided string or `null`. When `null`, your World generates and returns a new `runId`.

**Hook Tokens:** Hook tokens must be unique. If a `hook_created` event conflicts with an existing token, return a `hook_conflict` event instead.

Expand Down Expand Up @@ -165,13 +168,19 @@ The Streamer interface enables real-time data streaming:
interface Streamer {
writeToStream(
name: string,
runId: string | Promise<string>,
runId: string,
chunk: string | Uint8Array
): Promise<void>;

writeToStreamMulti?(
name: string,
runId: string,
chunks: (string | Uint8Array)[]
): Promise<void>;

closeStream(
name: string,
runId: string | Promise<string>
runId: string
): Promise<void>;

readFromStream(
Expand All @@ -184,6 +193,7 @@ interface Streamer {
```

Streams are identified by a combination of `runId` and `name`. Each workflow run can have multiple named streams.
`writeToStreamMulti()` is an optional optimization for batching multiple writes.

## Reference Implementations

Expand Down
4 changes: 2 additions & 2 deletions docs/content/docs/deploying/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ For self-hosting or deploying to other cloud providers, you can use community-ma
To use a different World implementation, set the `WORKFLOW_TARGET_WORLD` environment variable:

```bash
export WORKFLOW_TARGET_WORLD=@workflow-worlds/postgres
export WORKFLOW_TARGET_WORLD=@workflow/world-postgres
# Plus any world-specific configuration
export DATABASE_URL=postgres://...
```
Expand All @@ -87,7 +87,7 @@ The [Observability tools](/docs/observability) work with any World backend. By d
npx workflow inspect runs

# Inspect remote workflows
npx workflow inspect runs --backend @workflow-worlds/postgres
npx workflow inspect runs --backend @workflow/world-postgres
```

Learn more about [Observability](/docs/observability) tools.
2 changes: 1 addition & 1 deletion docs/content/docs/errors/node-js-module-in-workflow.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async function read(filePath: string) {
These common Node.js core modules cannot be used in workflow functions:

- File system: `fs`, `path`
- Network: `http`, `https`, `net`, `dns`, `fetch`
- Network: `http`, `https`, `net`, `dns`
- Process: `child_process`, `cluster`
- Crypto: `crypto` (use Web Crypto API instead)
- Operating system: `os`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default nextConfig;

```typescript lineNumbers title="next.config.ts"
// Fixed - includes withWorkflow
import { withWorkflow } from "workflow/next"; // [!code highlight}
import { withWorkflow } from "workflow/next"; // [!code highlight]
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/foundations/starting-workflows.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export async function POST(request: Request) {
}
```

Your workflow can write to the stream using [`getWritable()`](/docs/api-reference/workflow/get-writable):
Your workflow can obtain a writable stream using [`getWritable()`](/docs/api-reference/workflow/get-writable):

```typescript lineNumbers
import { getWritable } from "workflow";
Expand Down
4 changes: 2 additions & 2 deletions docs/content/docs/foundations/streaming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Use the `Run` object's `readable` property to consume the stream from your API r

```typescript title="app/api/stream/route.ts" lineNumbers
import { start } from "workflow/api";
import { simpleStreamingWorkflow } from "./workflows/simple";
import { simpleStreamingWorkflow } from "./workflows/simple-streaming";

export async function POST() {
const run = await start(simpleStreamingWorkflow);
Expand Down Expand Up @@ -120,7 +120,7 @@ import { streamProcessingWorkflow } from "./workflows/streaming";
export async function POST(request: Request) {
// Streams can be passed as workflow arguments
const run = await start(streamProcessingWorkflow, [request.body]); // [!code highlight]
await run.result();
await run.returnValue;

return Response.json({ status: "complete" });
}
Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/getting-started/astro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ Workflows can be triggered from API routes or any server-side code.

## Run in Development

To start your development server, run the following command in your terminal in the Vite root directory:
To start your development server, run the following command in your terminal in the Astro project root directory:

```bash
npm run dev
Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/observability/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Workflow DevKit provides powerful tools to inspect, monitor, and debug your work
npx workflow
```

The CLI comes pre-installed with the Workflow DevKit and registers the `workflow` command. If the `workflow` package is not already installed, `npx workflow` will install it globally, or use the local installed version if available.
The CLI comes pre-installed with the Workflow DevKit and registers the `workflow` command. If the `workflow` package is not already installed, `npx workflow` will download and run the CLI temporarily, or use the local installed version if available.

Get started inspecting your local workflows:

Expand Down
Loading