Files
analysis_claude_code/s16_workflow_runtime/README.md
Cursor Agent 87d484251a Cut s16 README mainline to March-style short skeleton
Compress ZH/EN/JA essay into problem → ASCII/figure → minimal code →
try it. Move pattern grid, quarantine, primitives card, and overview
SVG into details; bump translation-sync to v18.

Co-authored-by: Xinlu Lai <CrazyBoyM@users.noreply.github.com>
2026-08-12 14:07:24 +00:00

6.7 KiB
Raw Blame History

s16: Workflow Runtime — Put the Recipe in Code

English · 中文 · 日本語

s01 → ... → s14 → s15s16s17

Workflow = orchestration written as code. Script owns topology; the model judges each step.

Harness layer: Orchestration — a multi-agent script above the single-agent loop.

Trust the model. Engineer the harness. Workflows take that one floor up.


Problem

On long jobs, plan and action share one chat: stop early, grade your own homework kindly, lose quiet constraints after compressions. Soft chat memory is a weak place for parallelism, stable result shapes, and resume.

Nudging turn-by-turn is like texting the chef every ten seconds. A workflow is a recipe the kitchen can follow.

Idea

Helpers (subagents) still think. The script owns loops, fan-out, and merge. Intermediates live in variables and a journal — not the conversation.

Orchestration moves from intelligence to structure.

  messages[] ──► Workflow(...) ──► tool_result
                      │
                      ▼
              script owns: agent / parallel / pipeline
                      │
                      ▼
                 variables + journal

One Workflow tool call starts the run; one result comes back when it finishes.

Runtime overview diagram

Workflow Runtime Overview

Two doors

  • Dynamic: model writes a JS orchestration script for this task (script / scriptPath).
  • Saved: good script under .claude/workflows/; call by name + args.
  • Static (cousin outside): Agent SDK / claude -p written ahead — usually more generic.

Static vs dynamic

Left: fixed pipeline → generic report. Right: cut for your code → a specific recommendation.

This chapter is a Python teaching runtime (no JS VM). Concepts map to Claude Code; the demo uses the Saved door. In the product the model can submit executable scripts — we just skip embedding a JS interpreter here.

# teaching sketch — not the full schema
Workflow({ "name": "review-changes", "args": { "changes": "..." } })
# Claude Code also accepts: script | scriptPath | resumeFromRunId

Three verbs

  agent      one helper, one job (optional schema → validated JSON)
  pipeline   each item walks stages alone (default — no barrier)
  parallel   wait for every tray (barrier — use sparingly)

On failure the fleet continues: parallelnull in that slot; pipeline drops that item and its later stages. Filter before merge.

Resume: journal records calls in invocation order; replay the longest unchanged prefix, then run live. Real JS runtimes ban Date.now() / Math.random(). This demo does not fully sandbox that — write deterministic scripts anyway.

  journal  [A] [B] [C] [D]
  resume    hit hit  ✂  live
Official primitive card + quieter verbs

Workflow primitives

agent; parallel (barrier) vs pipeline (streaming stages). Claude Code also has model / isolation / agentType; teaching surface is smaller.

Quieter: phase, log, nested workflow, args, budget.

Two shapes + one sample

Feel two first (full six-pattern grid in the fold below):

  Fanout          task ──► ● ● ● ● ══barrier══► synthesize
  Adversarial     worker ──► verifier×N  → keep what still stands

Sample review-changes = Fanout with Adversarial inside: pipeline(audit, verify) per dimension; parallel verifiers; keep only isReal.

  correctness ── audit ── verify ──┐
  security    ── audit ── verify ──┤── confirmed
  performance ── audit ── verify ──┤
  style       ── audit ── verify ──┘
# from code.py (abbreviated)
async def sample_workflow(ctx, args):
    ctx.phase("Review")
    results = await ctx.pipeline(DIMENSIONS, audit, verify)
    confirmed = [f for r in results if r for f in r["confirmed"]]
    return {"confirmed": confirmed}

The fleet cannot stop early, the author is not the judge, and topology is not rewritten every chat turn.

Six-pattern grid + primitive map

Six Workflow Patterns

Pattern Primitive sketch Skip when…
Classify-And-Act agent → branch → agent Same treatment for every item
Fanout-And-Synthesize pipeline / parallel → merge One pass already fits
Adversarial Verification produce → parallel(verify) → filter A wrong answer is cheap
Generate-And-Filter parallel(gens) → filter Answer space is already tiny
Tournament pairwise judge agents A clear rubric picks a winner
Loop Until Done while + stop + budget Work size is known
# teaching sketch
kind = await ctx.agent("classify this ticket", schema=KIND)
if kind["type"] == "billing":
    return await ctx.agent("handle billing…")
Untrusted input: quarantine

The agent that reads tickets should not also hold PR keys. Readers stay read-only → structured summary; a trusted actor acts on the summary only.

  backlog (untrusted) → [quarantine: readers → dedupe → summary] → [trusted: actor]

Quarantine triage

High-privilege tools stay on the trusted side. Pair with /loop if the backlog never sleeps.

How this hangs on s15

s15 stays the host loop; s16 only adds a Workflow tool. Product runs can be background; the teaching CLI keeps demo / resume in the foreground for phases and cache hits.

Neighbors & when not

Who holds the plan? s06 one-shot delegate, s13 mailbox peers, s15 one loop, s16 script + journal, s17 asks “is the whole goal done?”

Ordinary coding: one s15 turn or one honest s06 often wins. Workflows cost tokens and coordination — reach for them when structure must outlast a single context.

Try it

python s16_workflow_runtime/code.py          # s15 host + Workflow (real API)
python s16_workflow_runtime/code.py demo     # fixed fixture; watch phases
python s16_workflow_runtime/code.py resume   # same runId; expect cache hits

A full resume should show agents=0 tokens=0.

Next

s16 is how a batch runs. s17 Goal Loop asks: stop, or take another turn?