Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .changeset/workflow-retention-passthrough.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"agents": minor
---

Pass Workflow instance retention options through `Agent.runWorkflow()`.
10 changes: 9 additions & 1 deletion docs/agents/workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,11 @@ const instanceId = await this.runWorkflow(
{
id: "custom-id", // optional - auto-generated if not provided
metadata: { userId: "user-456", priority: "high" }, // optional - for querying
agentBinding: "MyAgent" // optional - auto-detected from class name if not provided
agentBinding: "MyAgent", // optional - auto-detected from class name if not provided
retention: {
successRetention: "1 day",
errorRetention: "7 days"
}
}
);
```
Expand All @@ -258,6 +262,10 @@ const instanceId = await this.runWorkflow(
- `options.id` - Custom workflow ID (auto-generated if not provided)
- `options.metadata` - Optional metadata stored for querying (not passed to workflow)
- `options.agentBinding` - Agent binding name (auto-detected from class name if not provided). When called from a sub-agent, this is the root Agent binding name.
- `options.retention` - Workflow instance retention passed unchanged to
[`Workflow.create()`](https://developers.cloudflare.com/workflows/build/workers-api/#workflowinstancecreateoptions).
Use `successRetention` for successful instances and `errorRetention` for
errored or terminated instances.

**Returns:** Workflow instance ID

Expand Down
5 changes: 4 additions & 1 deletion packages/agents/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11216,7 +11216,10 @@ export class Agent<
// Create the workflow instance
const instance = await workflow.create({
id: workflowId,
params: augmentedParams
params: augmentedParams,
...(options?.retention === undefined
? {}
: { retention: options.retention })
});

// Track the workflow in our database
Expand Down
24 changes: 24 additions & 0 deletions packages/agents/src/tests-d/workflow-retention.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { expectTypeOf } from "vitest";
import type { RunWorkflowOptions } from "../workflows";

expectTypeOf<RunWorkflowOptions["retention"]>().toEqualTypeOf<
WorkflowInstanceCreateOptions["retention"]
>();

const validRetention = {
retention: {
successRetention: "1 day",
errorRetention: 60_000
}
} satisfies RunWorkflowOptions;

void validRetention;

const invalidRetention = {
retention: {
// @ts-expect-error Workflow retention uses WorkflowSleepDuration units.
successRetention: "1 fortnight"
}
} satisfies RunWorkflowOptions;

void invalidRetention;
17 changes: 16 additions & 1 deletion packages/agents/src/tests/agents/workflow.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Agent } from "../../index.ts";
import type { WorkflowStatus, WorkflowInfo } from "../../workflows.ts";
import type {
RunWorkflowOptions,
WorkflowStatus,
WorkflowInfo
} from "../../workflows.ts";

type WorkflowSubAgentState = {
status: string;
Expand Down Expand Up @@ -701,6 +705,17 @@ export class TestWorkflowAgent extends Agent {
});
}

async runSimpleWorkflowWithRetentionTest(
workflowId: string,
retention: NonNullable<RunWorkflowOptions["retention"]>
): Promise<string> {
return this.runWorkflow(
"SIMPLE_WORKFLOW",
{ value: "retention-test" },
{ id: workflowId, retention }
);
}

// Start a simple workflow using the Agent's generated default ID
async runSimpleWorkflowTestWithDefaultId(params: {
value: string;
Expand Down
19 changes: 19 additions & 0 deletions packages/agents/src/tests/workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,25 @@ async function getTestAgent(name: string) {

describe("workflow operations", () => {
describe("workflow tracking", () => {
it("starts and tracks a workflow with custom retention", async () => {
const agentStub = await getTestAgent("workflow-retention-test");
const workflowId = "workflow-with-retention";

const instanceId = await agentStub.runSimpleWorkflowWithRetentionTest(
workflowId,
{
successRetention: "1 day",
errorRetention: "2 weeks"
}
);

expect(instanceId).toBe(workflowId);
expect(await agentStub.getWorkflowById(workflowId)).toMatchObject({
workflowId,
workflowName: "SIMPLE_WORKFLOW"
});
});

it("should insert and retrieve a workflow tracking record", async () => {
const agentStub = await getTestAgent("workflow-tracking-test-1");

Expand Down
2 changes: 2 additions & 0 deletions packages/agents/src/workflow-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ export type RunWorkflowOptions = {
metadata?: Record<string, unknown>;
/** Agent binding name (auto-detected from class name if not provided) */
agentBinding?: string;
/** Retention policy for the underlying Workflow instance */
retention?: WorkflowInstanceCreateOptions["retention"];
};

/**
Expand Down
Loading