Program stability × Agent initiative

Let code drive the flow. Agents handle judgment.

Dynamic Workflow puts orchestration in TypeScript. Order, concurrency, and stopping rules become explicit; a complete Agent Loop runs only where the task needs understanding and judgment.

See how it works
01 / CODE HOLDS THE PLAN 02 / AGENTS HANDLE JUDGMENT 03 / HUMANS RETAIN RESPONSIBILITY
01

WHY DYNAMIC WORKFLOW

Not every step
needs a model.

Skills carry knowledge and strategy. When mechanical steps also live in natural language, the Agent often has to interpret the plan again as it advances. Dynamic Workflow moves that control flow into code.

01

Code holds the plan

Phases, branches, Barriers, retry limits, and stopping rules live in code, where they can be reviewed and tested.

02

Agents handle judgment

agent() starts a complete ReAct Loop with tools and its own Context—not a one-shot Prompt completion.

03

Schema gives code a stable shape

When code consumes an Agent result, JSON Schema validates its shape before the next step runs.

02

CREATE & RUN

Create from a prompt.
Run with one command.

Generate a Workflow from one sentence, or run the bundled Deep Research example from the repository root.

Open the example
TERMINAL / CREATE GENERATE
PROMPT → CODEX AGENT WORKFLOW.TS → STDOUT
TERMINAL / DEEP RESEARCH RUN
JSONL EVENTS → STDERR RESULT → STDOUT
03

PORTABLE BY DESIGN

One file,
Run anywhere.

Run the same workflow.ts as a cloud or FaaS service, inside CI/CD, a desktop app, or directly from the CLI.

WORKFLOW.TS / PORTABLE

Bring the runtime · keep the Workflow

HOST_01 Cloud service
HOST_02 Desktop
HOST_03 CLI
HOST_04 FaaS service
HOST_05 CI/CD
04

THE WORKFLOW IS CODE

Ordinary TypeScript.
Only agent() starts an Agent Loop.

Use arrays, branches, loops, and concurrency for the mechanical work. Call agent() when a step needs understanding, exploration, or judgment.

Read the Workflow API contract
workflow.ts
01 import { agent, log, parallel, phase, pipeline } from "@deerwork-ai/deer-workflow";
02
03 export const meta = {
04   name: "research-synthesis",
05   description: "Researches and synthesizes a topic.",
06   phases: [
07     { title: "Plan" },
08     { title: "Research" },
09     { title: "Synthesize" },
10   ],
11   exampleArgs: { topic: "Agentic workflow design" },
12 };
13
14 export default async function workflow(args: { topic: string }) {
15   phase("Plan");
16   log(`Planning research for ${args.topic}`);
17   const plan = await agent<{ angles: string[] }>(
18     `Plan independent research angles for ${args.topic}`,
19     {
20       schema: {
21         type: "object",
22         properties: { angles: { type: "array", items: { type: "string" } } },
23         required: ["angles"],
24         additionalProperties: false,
25       },
26     },
27   );
28
29   phase("Research");
30   log(`Researching ${plan.angles.length} angles`);
31   const signals = await parallel(
32     plan.angles.map((angle) => () => agent(`Research ${angle}`)),
33   );
34   const findings = await pipeline(
35     signals.filter(Boolean),
36     (signal) => agent(`Extract key facts:\n${signal}`),
37   );
38   log(`Prepared ${findings.length} findings`);
39
40   phase("Synthesize");
41   return agent(`Synthesize:\n${JSON.stringify(findings)}`);
42 }
FLOW READY EXPLICIT IMPORTS / ASYNC RUNTIME