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
6 changes: 6 additions & 0 deletions .changeset/run-get-writable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@workflow/core': minor
'workflow': minor
---

Add `Run#getWritable()` to append to an existing run's stream.
10 changes: 10 additions & 0 deletions docs/content/docs/v4/api-reference/workflow-api/get-run.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ import type { WorkflowReadableStreamOptions } from "workflow/api";
export default WorkflowReadableStreamOptions;`}
/>

#### WorkflowRunWritableStreamOptions

<TSDoc
definition={`
import type { WorkflowRunWritableStreamOptions } from "workflow/api";
export default WorkflowRunWritableStreamOptions;`}
/>

See [Writing to another run's stream](/docs/foundations/streaming#writing-to-another-runs-stream) for usage and lifecycle details.

#### StopSleepOptions

<TSDoc
Expand Down
28 changes: 28 additions & 0 deletions docs/content/docs/v4/foundations/streaming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,34 @@ export async function POST(request: Request) {
}
```

## Writing to another run's stream

`getRun(runId).getWritable()` appends to a stream owned by another run. This lets short-lived runs contribute to a long-lived holder run's stream using only its ID.

```typescript title="workflows/turn.ts" lineNumbers
import { getRun } from "workflow/api";

type SessionEvent = { turn: number; text: string };

async function runTurn(holderRunId: string, turn: number) {
"use step";

const writable = await getRun(holderRunId).getWritable<SessionEvent>(); // [!code highlight]
const writer = writable.getWriter();

await writer.write({ turn, text: "done" });
writer.releaseLock(); // [!code highlight]
}
```

Pass `{ namespace: "name" }` to target a [namespaced stream](#namespaced-streams). The writable can also be forwarded through `start()` and into steps.

<Callout type="warn">
Contributors should call `releaseLock()`, which flushes pending writes. Calling `close()` closes the shared stream for every writer.
</Callout>

The API grants append access, not read access or additional authorization. The owning run controls the stream's lifecycle, and an unknown run rejects with `WorkflowRunNotFoundError`.

## Common patterns

### Progress updates for long-running tasks
Expand Down
10 changes: 10 additions & 0 deletions docs/content/docs/v5/api-reference/workflow-api/get-run.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ import type { WorkflowReadableStreamOptions } from "workflow/api";
export default WorkflowReadableStreamOptions;`}
/>

#### WorkflowRunWritableStreamOptions

<TSDoc
definition={`
import type { WorkflowRunWritableStreamOptions } from "workflow/api";
export default WorkflowRunWritableStreamOptions;`}
/>

See [Writing to another run's stream](/docs/foundations/streaming#writing-to-another-runs-stream) for usage and lifecycle details.

#### StopSleepOptions

<TSDoc
Expand Down
28 changes: 28 additions & 0 deletions docs/content/docs/v5/foundations/streaming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,34 @@ export async function POST(request: Request) {
}
```

## Writing to another run's stream

`getRun(runId).getWritable()` appends to a stream owned by another run. This lets short-lived runs contribute to a long-lived holder run's stream using only its ID.

```typescript title="workflows/turn.ts" lineNumbers
import { getRun } from "workflow/api";

type SessionEvent = { turn: number; text: string };

async function runTurn(holderRunId: string, turn: number) {
"use step";

const writable = await getRun(holderRunId).getWritable<SessionEvent>(); // [!code highlight]
const writer = writable.getWriter();

await writer.write({ turn, text: "done" });
writer.releaseLock(); // [!code highlight]
}
```

Pass `{ namespace: "name" }` to target a [namespaced stream](#namespaced-streams). The writable can also be forwarded through `start()` and into steps.

<Callout type="warn">
Contributors should call `releaseLock()`, which flushes pending writes. Calling `close()` closes the shared stream for every writer.
</Callout>

The API grants append access, not read access or additional authorization. The owning run controls the stream's lifecycle, and an unknown run rejects with `WorkflowRunNotFoundError`.

## Common patterns

### Progress updates for long-running tasks
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export {
Run,
type WorkflowReadableStream,
type WorkflowReadableStreamOptions,
type WorkflowRunWritableStreamOptions,
} from './runtime/run.js';
export {
type CancelRunOptions,
Expand Down
Loading
Loading