{"slug": "claude-code-workflows-deterministic-multi-agent-orchestration", "title": "Claude Code Workflows: Deterministic Multi-Agent Orchestration", "summary": "Anthropic's Claude Code introduced deterministic multi-agent orchestration workflows, enabling developers to script parallel agent execution, fan-out, reduce, and synthesis patterns. A 130-line workflow example demonstrated nine agents independently scanning Vue and Nuxt ecosystem sources, merging findings, and ranking them by impact, showcasing the feature's ability to handle comprehensive, confidence-critical, and large-scale tasks beyond a single context window.", "body_md": "Claude Code shipped **workflows** recently, and the docs describe a lot of machinery: deterministic orchestration, `parallel`\n\nand `pipeline`\n\n, journaling and resume, adversarial verify patterns. I wanted to understand it rather than skim the feature list, and the way I learn a tool is to build the smallest real thing with it.\n\nSo I picked a task with an obvious fan-out shape: “what happened in the Vue and Nuxt ecosystem this week.” Many independent sources to check, then a merge, then a write-up. I wrote a ~130-line workflow that spawns nine agents in parallel, each scouring a different source, collects their findings into one list, ranks them by impact, and writes a digest. It’s a throwaway, but building it taught me how the whole feature fits together. This post is what I learned.\n\nA workflow is the newest piece of Claude Code’s orchestration story. In my [ post on agent teams ](/posts/from-tasks-to-swarms-agent-teams-in-claude-code/) Claude Code Agent Teams: How Multiple Sessions Coordinate (2026) Agent teams let multiple Claude Code sessions coordinate, communicate, and self-organize. Here's how they work, when to use them, and what they cost. I traced the progression from subagents to teams. Workflows are the next rung, and they solve a different problem than either: when you want the *control flow itself* to be deterministic, not decided turn-by-turn by a model.\n\nIf you want a sense of the ceiling before the toy example, Jarred Sumner credited dynamic workflows and adversarial code review for porting Bun from Zig to Rust in six days:\n\nDynamic workflows and adversarial code review was part of what made it possible to rewrite Bun in Rust in 6 days.\n\nNew in Claude Code (research preview): dynamic workflows. Claude writes an orchestration script on the fly, then spins up a large fleet of coordinated subagents in parallel to take on your most complex tasks. Use the word \"workflow\" in a prompt to get started.\n\n## ✨ TLDR\n\n- → A workflow is a plain JavaScript script that orchestrates subagents deterministically: you own the loops and fan-out, agents do the thinking\n- → The shape that generalizes: fan out → reduce → synthesize\n- → agent() runs one subagent (use a schema for validated JSON), parallel() is a barrier, pipeline() streams items through stages with no barrier\n- → Default to pipeline(); reach for a parallel() barrier only when a stage needs all prior results at once\n- → Compose verify/judge/loop-until-dry patterns for confidence, not more agents\n- → It's opt-in and token-hungry, so reach for it when a job needs breadth, verification, or scale a single context can't hold\n\n## Table of Contents\n\n## Open Table of Contents\n\n## Where Workflows Fit\n\nMost of the time a single Claude Code session works turn-by-turn: read a file, decide, call a tool, look at the result, decide again. That loop is the right tool for most work. Some jobs don’t fit one head and one context window though:\n\n**Comprehensive** jobs: “review every file in this diff”, “audit all 40 dependencies”.**Confidence-critical** jobs: “find the bug, then have three independent skeptics try to refute it”.**Scale** jobs: migrations, sweeps, anything bigger than one context can hold.\n\nSubagents and agent teams can attack these, but there’s a subtle difference in *who holds the plan*.\n\n| Subagents | Agent Teams | Workflows | |\n|---|---|---|---|\nWhat it is | A worker Claude spawns | Independent Claude sessions | A script the runtime executes |\nWho decides what’s next | Claude, turn by turn | Claude and the teammates | The script |\nWhere results live | Claude’s context | Each session’s context | Script variables |\nWhat’s repeatable | The worker definition | The team setup | The orchestration itself |\nScale | A few per turn | A handful of sessions | Dozens to hundreds of agents |\n\nWith subagents and skills, Claude is the orchestrator. It decides turn by turn what to spawn, and every result lands back in its context window. A workflow moves the plan into code. The script holds the loop, the branching, and the intermediate results, so Claude’s context only ever sees the final answer. That is what lets a workflow scale to hundreds of agents without drowning the conversation.\n\n## The Core Idea\n\nA normal agent decides the control flow as it goes. A workflow inverts that. *You* write the control flow as plain code, and each individual step is delegated to a fresh subagent. The orchestration is deterministic; only the work inside each `agent()`\n\ncall is model-powered.\n\nThat distinction is the whole point. When you write this:\n\n``` js\nconst results = await parallel(files.map((f) => () => agent(`Review ${f}`)));\n```\n\nYou know exactly one agent runs per file, they all run concurrently, and you get an array back. There are no emergent “the model decided to skip three files” surprises. You get determinism in the orchestration and model judgment inside each step.\n\nThe shape that keeps showing up is **fan out → reduce → synthesize**:\n\n``` php\n        \ngraph LR\n  A[fan out] --> B[agent 1]\n  A --> C[agent 2]\n  A --> D[agent ...]\n  A --> E[agent N]\n  B --> F[reduce: dedupe + rank]\n  C --> F\n  D --> F\n  E --> F\n  F --> G[synthesize: write the result]\n```\n\nSwap the sources and prompts and the same skeleton becomes a market scan, a dependency audit, a code review, or a research report.\n\n## The Example I Built to Learn It\n\nHere is the workflow I wrote. I picked the newsletter task because it forces you to use every part of the feature: a wide fan-out, a reduce step, and a synthesis step. Every script starts with a `meta`\n\nblock that must be a **pure literal**, then a body using the orchestration primitives.\n\n``` js\nexport const meta = {\n  name: \"vue-newsletter\",\n  description: \"Research Vue/Nuxt sources in parallel and synthesize a newsletter\",\n  phases: [\n    { title: \"Research\", detail: \"one agent per source\" },\n    { title: \"Curate\", detail: \"dedupe + rank by impact\" },\n    { title: \"Write\", detail: \"synthesize the newsletter\" },\n  ],\n};\n```\n\n### 1. Fan out with `parallel()`\n\nNine sources, nine agents, all at once. Each returns structured JSON validated against a schema, so the model retries on mismatch and I never parse free text:\n\n``` js\nphase(\"Research\");\nconst raw = await parallel(\n  SOURCES.map((s) => () =>\n    agent(s.prompt, {\n      label: `research:${s.key}`,\n      phase: \"Research\",\n      schema: ITEM_SCHEMA, // forces validated structured output\n      agentType: \"general-purpose\",\n    }),\n  ),\n);\n```\n\nThe `SOURCES`\n\narray is just data: one entry per source with a prompt. GitHub core releases, the Nuxt ecosystem, the official blogs, Hacker News, Reddit, dev.to, key people like Evan You and Anthony Fu, and the newsletter/podcast circuit.\n\n### 2. Reduce with plain JavaScript\n\nFlattening, deduping, and filtering is just code. No agent needed:\n\n``` js\nconst collected = raw.filter(Boolean); // skipped/failed agents become null\nconst flatItems = collected.flatMap((c) => c.items);\nlog(`Collected ${flatItems.length} items`);\n```\n\n### 3. Synthesize with sequential `agent()`\n\ncalls\n\n``` js\nphase(\"Curate\");\nconst curated = await agent(curatePrompt, { phase: \"Curate\", schema: CURATED_SCHEMA });\n\nphase(\"Write\");\nconst newsletter = await agent(writePrompt, { phase: \"Write\" });\n\nreturn { newsletter, itemCount: flatItems.length, curated };\n```\n\nThe run I did while testing pulled together a Nuxt UI release, a Vue Router v5 minor, a Vue core patch, and a Madrid conference recap: seventeen items across nine sources in about three minutes. Good enough to convince me the orchestration worked, which was the whole point of building it.\n\n## The Primitives\n\nA handful of functions do all the work.\n\n** agent(prompt, opts?)** spawns one subagent. Without options it returns the agent’s final text. The options worth knowing:\n\n`schema`\n\n: a JSON Schema. The subagent is forced to return validated structured data.`label`\n\n: the display name in the progress UI.`phase`\n\n: assigns the agent to a progress group. Use it inside`parallel()`\n\nand`pipeline()`\n\nto avoid racing on the global`phase()`\n\nstate.`model`\n\n: override the model for this one call. Default is to omit it so the agent inherits your session model.`agentType`\n\n: use a custom subagent type instead of the default workflow agent.`isolation: \"worktree\"`\n\n: run the agent in its own git worktree. Only when agents write files in parallel and would otherwise conflict.\n\n** parallel(thunks)** runs tasks concurrently. It is a\n\n**barrier**: it waits for every thunk before returning. A thunk that throws resolves to\n\n`null`\n\nrather than rejecting the whole call, so always `.filter(Boolean)`\n\nthe results. You can pass a hundred thunks and they’ll all complete, but only a handful run at once: concurrency is capped at roughly your core count, and the excess queue.** pipeline(items, ...stages)** runs each item through all stages\n\n**independently, with no barrier between stages**. Item A can be in stage 3 while item B is still in stage 1. Each stage callback receives\n\n`(prevResult, originalItem, index)`\n\n.** workflow(nameOrRef, args?)** runs\n\n*another*workflow inline as a sub-step and returns whatever it returns. Pass a name to invoke a saved workflow, or\n\n`{ scriptPath }`\n\nto run a script file. This is composition: a research workflow can call `/deep-research`\n\nas one of its stages instead of reimplementing the fan-out. The child shares the parent’s concurrency cap, agent counter, and token budget, and shows up as its own group in `/workflows`\n\n. Nesting is one level deep: a `workflow()`\n\ncall inside a child throws.\n\n```\n// inside a script: hand a sub-question off to the bundled deep-research workflow\nconst report = await workflow(\"deep-research\", { question: topic });\n```\n\nThe rest are small helpers: `phase(title)`\n\nstarts a progress group, `log(msg)`\n\nemits a narrator line, `args`\n\ncarries the JSON you passed in when launching, and `budget`\n\nexposes the token target so you can scale depth dynamically (it’s `null`\n\nwhen you launch without a target, so guard any loop-until-budget on `budget.total`\n\nor it runs to the agent cap).\n\nWarning\n\n`Date.now()`\n\n, `Math.random()`\n\n, and an argless `new Date()`\n\nall throw inside a workflow. Workflows journal every `agent()`\n\ncall so a run can resume, and non-determinism would invalidate that cache. If you need a timestamp, pass it through `args`\n\n. If you need variety across agents, vary the prompt or label by index.\n\n`pipeline`\n\nvs `parallel`\n\n: The Decision That Matters\n\nThis trips people up, so here is the rule I follow.\n\n**Default to pipeline().** Reach for a\n\n`parallel()`\n\nbarrier between stages *only*when a stage needs\n\n**all** prior results at once.\n\nLegitimate reasons for a barrier:\n\n- ✅ Dedupe or merge across the full result set before expensive downstream work.\n- ✅ Early-exit on the total (“0 findings, skip verification entirely”).\n- ✅ A prompt that references “the other findings” for comparison.\n\nNot legitimate:\n\n- ❌ “I need to flatten or filter first.” Do it inside a pipeline stage.\n- ❌ “The stages feel conceptually separate.” Separate is not the same as synchronized.\n- ❌ “It’s cleaner code.” Barrier latency is real wall-clock waste.\n\nThe smell test: if you wrote `parallel`\n\n→ transform → `parallel`\n\n, and that middle transform has no cross-item dependency, you should have used a pipeline. The newsletter example *does* use a barrier, and correctly: curation has to see every source before it can dedupe and rank across them.\n\n## Quality Patterns\n\nThe primitives compose into reusable harnesses. This is the real value over spawning more agents: the structure is what produces confidence. A few I lean on:\n\n**Adversarial verify**: for each finding, spawn N independent skeptics prompted to*refute*it. Kill it unless a majority survive. Stops plausible-but-wrong findings from shipping.**Perspective-diverse verify**: give each verifier a distinct lens (correctness, security, performance, does-it-reproduce) instead of N identical ones. Diversity catches failure modes redundancy can’t.**Judge panel**: generate N attempts from different angles, score with parallel judges, synthesize from the winner while grafting the best of the runners-up.**Loop-until-dry**: for unknown-size discovery, keep spawning finders until K consecutive rounds surface nothing new.\n\nHere is loop-until-dry with a diverse-lens verify, condensed:\n\n``` js\nconst seen = new Set();\nconst confirmed = [];\nlet dry = 0;\nwhile (dry < 2) {\n  const found = (await parallel(FINDERS.map((f) => () =>\n    agent(f.prompt, { phase: \"Find\", schema: BUGS })))).filter(Boolean).flatMap((r) => r.bugs);\n  const fresh = found.filter((b) => !seen.has(key(b)));\n  if (!fresh.length) {\n    dry++;\n    continue;\n  }\n  dry = 0;\n  fresh.forEach((b) => seen.add(key(b)));\n  const judged = await parallel(fresh.map((b) => () =>\n    parallel([\"correctness\", \"security\", \"repro\"].map((lens) => () =>\n      agent(`Judge \"${b.desc}\" via the ${lens} lens — real?`, { phase: \"Verify\", schema: VERDICT })))\n      .then((vs) => ({ b, real: vs.filter(Boolean).filter((v) => v.real).length >= 2 }))));\n  confirmed.push(...judged.filter((v) => v.real).map((v) => v.b));\n}\n```\n\nOne detail makes or breaks this: dedupe against everything *seen*, not just confirmed results. Otherwise rejected findings reappear every round and the loop never converges.\n\n## A Shipped Example: How `/deep-research`\n\nWorks\n\nMy newsletter generator is a toy. If you want to see these patterns in a real, bundled workflow, run `/deep-research`\n\n. It takes a question and returns a cited report, and under the hood it’s the same **fan out → reduce → synthesize** skeleton with an **adversarial verify** pass bolted on. It’s the quality pattern from the section above, running in production.\n\nWhen you launch it the workflow announces its plan and runs in the background while you keep working:\n\nIt moves through five phases:\n\n**Scope:** one agent decomposes your question into five distinct search angles, so the searches don’t all chase the same wording.**Search:** five web searches run in parallel, one per angle. This is the fan-out.**Fetch:** dedupe the URLs across angles, pull the top ~15 sources, and extract individual claims from them.**Verify:** the interesting part. Each claim gets an adversarial three-vote check, with skeptics trying to refute it. Claims that don’t survive never reach the report.**Synthesize:** one final agent writes the cited report from the claims that held up.\n\nMap that onto the primitives and you can almost see the script: a single `agent()`\n\nfor scope, a `parallel()`\n\nfan-out for the five searches, plain JavaScript to dedupe in fetch, a per-claim verify pass (the same `parallel()`\n\nof skeptics from the loop-until-dry example), and a closing `agent()`\n\nto synthesize. The phases show up in `/workflows`\n\nas named groups (`Scope 1/1`\n\n, `Search 0/5`\n\n, `Fetch`\n\n, `Verify`\n\n, `Synthesize`\n\n), each with its own agent count, token total, and elapsed time, so you can drill into any single search or verification and read its prompt and result.\n\nThis is the difference between “ask Claude to research something” and a workflow. A single agent doing web research holds every half-read source in one context and never checks its own claims. `/deep-research`\n\ndecomposes the search so coverage is wide, keeps the intermediate sources out of your conversation, and runs a verification pass a single turn-by-turn agent would never run against itself.\n\n## Triggering and Watching a Run\n\nWorth saying plainly: from Claude Code’s side, a workflow is **a tool**. There’s a `Workflow`\n\ntool the same way there’s a `Read`\n\nor `Bash`\n\ntool, and “running a workflow” means Claude calls that tool with a script. The runtime executes the script in the background while your session stays responsive, which is why you can keep chatting while dozens of agents churn away.\n\nThere are a few ways a workflow gets written and launched:\n\n**Say “workflow” in your prompt.** Include the word and Claude writes a workflow script for the task instead of working through it turn by turn.**Run a saved or bundled command.** A workflow you saved to the project, or the built-in`/deep-research`\n\ncovered above.**Turn on** Claude plans a workflow for every substantial task in the session.`ultracode`\n\n.\n\nRun a workflow to audit every API endpoint under src/routes/ for missing auth checks. Spawn one agent per route file, then have a second pass verify each finding before reporting.\n\nWhen a run does what you wanted, you can save it: Claude Code writes the script into ** .claude/workflows/** in your repo as a\n\n`<name>.js`\n\nfile (the appendix below is exactly that file for my newsletter). Because it lives in the repo, it’s version-controlled and anyone who clones it can launch it by name and pass arguments:Run the vue-newsletter workflow with args `{\"weekStart\":\"2026-06-04\",\"weekEnd\":\"2026-06-11\"}`\n\nRuns happen in the background, and ** /workflows** is how you watch them: it lists every run, including which ones are\n\n**currently running**, and opens a progress view showing each phase with its agent count, token total, and elapsed time. You can drill into a phase, then into a single agent, to read its prompt and result, pause or stop a run, or press\n\n`s`\n\nto save a good one’s script as a reusable `/<name>`\n\ncommand under `.claude/workflows/`\n\n.## When to Reach for One\n\n```\n        \ngraph TD\n  A[Does the job need breadth,<br/>verification, or scale?] -->|No| B[Single session<br/>or a subagent]\n  A -->|Yes| C[Do you want the control flow<br/>to be deterministic and repeatable?]\n  C -->|No| D[Agent team]\n  C -->|Yes| E[Write a workflow]\n```\n\n**Good fit** ✅\n\n- Decomposing a job so every part is covered in parallel (audits, reviews, sweeps).\n- Anything you want to\n*re-run*with the same structure (a weekly competitor scan, a release checklist). - Confidence-critical work where a repeatable verify or judge pass beats one model’s first answer.\n\n**Bad fit** ❌\n\n- An ordinary task one agent can do turn by turn. Let one agent do it.\n- Work that needs you to weigh in between every stage. A workflow can’t take mid-run input; only agent permission prompts pause it.\n- Anything where the token cost of dozens of agents isn’t justified by breadth or scale.\n\nWarning\n\nA workflow spawns many agents, so one run can use meaningfully more tokens than doing the same task in conversation, and it counts toward your plan’s usage. Every agent uses your session’s model unless the script routes a stage elsewhere, so check `/model`\n\nbefore a large run and consider routing cheap stages to a smaller model.\n\n## Conclusion\n\n- A workflow is a JavaScript script that orchestrates subagents deterministically. You own the control flow, agents do the thinking, and the plan lives in code so the conversation only sees the final answer.\n- The shape that generalizes is\n**fan out → reduce → synthesize**. The newsletter generator I built is a deliberately small instance of it. `agent()`\n\nruns one (use a`schema`\n\nfor validated structured output),`parallel()`\n\nis a barrier,`pipeline()`\n\nstreams items through stages with no barrier.**Default to pipeline.**- The leverage is the repeatable quality patterns: adversarial verify, diverse lenses, judge panels, loop-until-dry.\n- It is opt-in and token-hungry. Reach for it when a job needs breadth, independent verification, or scale a single context can’t hold. Otherwise let one agent do the work.\n\nIf you’ve already worked through [ subagents and skills ](/posts/claude-code-customization-guide-claudemd-skills-subagents/) Claude Code Customization Guide (2026): CLAUDE.md vs Skills vs Subagents When should you use CLAUDE.md, a slash command, a skill, or a subagent in Claude Code? A decision guide with real examples for each, so you stop guessing which one fits the job. , workflows are the natural next tool. The fastest way to understand them is the same way I did: pick a small task with a clear fan-out shape and build the throwaway version. Mine was a newsletter generator I won’t run again. The point was never the newsletter; it was seeing how the pieces fit, so that when a job needs breadth or verification, reaching for a workflow is obvious.\n\n## Appendix: The Full Script\n\nEverything above is excerpts. Here is the complete `.claude/workflows/vue-newsletter.js`\n\nin one piece, so you can see how the `meta`\n\nblock, the schemas, the source list, and the three phases fit together. It’s plain JavaScript: no imports, no filesystem access, inputs via `args`\n\n, results via `return`\n\n.\n\n## vue-newsletter.js: the complete workflow\n\n``` js\nexport const meta = {\n  name: 'vue-newsletter',\n  description: 'Research Vue/Nuxt ecosystem sources in parallel for a given week and synthesize a newsletter',\n  whenToUse: 'Generate a weekly Vue/Nuxt newsletter. Pass args {weekStart, weekEnd, label} as ISO dates (e.g. {\"weekStart\":\"2026-05-21\",\"weekEnd\":\"2026-05-28\"}). With no args, agents cover the past 7 days from today.',\n  phases: [\n    { title: 'Research', detail: 'one agent per source — releases, blogs, social, people' },\n    { title: 'Curate', detail: 'dedupe + rank items by impact' },\n    { title: 'Write', detail: 'synthesize the final newsletter' },\n  ],\n}\n\n// Args are optional. Pass {weekStart, weekEnd, label} as ISO dates to scope a specific week.\n// With no args, agents are told to cover \"the past 7 days from today\" (they resolve the date via web search).\nconst hasRange = args && args.weekStart && args.weekEnd\nconst weekStart = hasRange ? args.weekStart : null\nconst weekEnd = hasRange ? args.weekEnd : null\nconst label = (args && args.label) || (hasRange ? `Week of ${weekStart}–${weekEnd}` : 'this week')\nconst window = hasRange ? `between ${weekStart} and ${weekEnd}` : 'within the past 7 days from today'\n\nconst ITEM_SCHEMA = {\n  type: 'object',\n  additionalProperties: false,\n  properties: {\n    source: { type: 'string' },\n    items: {\n      type: 'array',\n      items: {\n        type: 'object',\n        additionalProperties: false,\n        properties: {\n          title: { type: 'string' },\n          url: { type: 'string' },\n          summary: { type: 'string', description: '1-3 sentence plain summary of what changed / why it matters' },\n          category: { type: 'string', enum: ['release', 'article', 'tooling', 'discussion', 'tutorial', 'people', 'other'] },\n          date: { type: 'string', description: 'ISO date if known, else empty' },\n          impact: { type: 'string', enum: ['high', 'medium', 'low'] },\n        },\n        required: ['title', 'url', 'summary', 'category', 'impact'],\n      },\n    },\n  },\n  required: ['source', 'items'],\n}\n\n// Each source is researched by its own agent in parallel.\nconst SOURCES = [\n  {\n    key: 'core-releases',\n    prompt: `Find releases/changelogs published ${window} for these GitHub repos: vuejs/core, vuejs/router (vue-router), vuejs/pinia, vueuse/vueuse, vitejs/vite, vitejs/vitest. For each new release in that window, give the version, the highlights, and the release URL. Skip anything outside the date window.`,\n  },\n  {\n    key: 'nuxt-releases',\n    prompt: `Find releases/changelogs published ${window} for the Nuxt ecosystem on GitHub: nuxt/nuxt, nuxt/ui, nuxt/image, nuxt/content, unjs/nitro, unjs/h3. Give version, highlights, and URL for each release in that window only.`,\n  },\n  {\n    key: 'vue-blog',\n    prompt: `Check the official Vue.js blog (blog.vuejs.org) and Vue.js news for posts published ${window}. Summarize each post with its URL.`,\n  },\n  {\n    key: 'nuxt-blog',\n    prompt: `Check the official Nuxt blog (nuxt.com/blog) for posts published ${window}. Summarize each with URL.`,\n  },\n  {\n    key: 'hackernews',\n    prompt: `Search Hacker News (news.ycombinator.com) for stories about Vue, Nuxt, Vite, or Pinia that were active/posted ${window}. Include the HN discussion URL and the linked article. Note points/comments if visible.`,\n  },\n  {\n    key: 'reddit',\n    prompt: `Search Reddit r/vuejs and r/Nuxt for notable threads posted ${window} — announcements, releases, popular discussions, showcased projects. Give the reddit thread URL for each.`,\n  },\n  {\n    key: 'devto',\n    prompt: `Search dev.to for the most useful Vue and Nuxt tagged articles published ${window} (tutorials, deep-dives, tips). Give URLs.`,\n  },\n  {\n    key: 'people',\n    prompt: `Look for notable updates, posts, or talks ${window} from key Vue/Nuxt people: Evan You (@youyuxi / VoidZero), Daniel Roe (Nuxt lead), Anthony Fu (VueUse/Vitesse/Slidev), Eduardo San Martin Morote (posva — router/pinia), Sébastien Chopin (Nuxt/NuxtLabs). Include VoidZero and NuxtLabs company news too. Give URLs.`,\n  },\n  {\n    key: 'newsletters-podcasts',\n    prompt: `Find Vue/Nuxt newsletter issues and podcast episodes published ${window}: Vue.js Newsletter (news.vuejs.org), This Week in Vue, Michael Thiessen's newsletter, DejaVue podcast, Deox/Vue Mastery content. Summarize and give URLs.`,\n  },\n]\n\nphase('Research')\nconst raw = await parallel(\n  SOURCES.map((s) => () =>\n    agent(\n      `You are researching the Vue.js / Nuxt ecosystem for a weekly newsletter covering ${label} (${window}).\\n\\n${s.prompt}\\n\\nUse web search and fetch real URLs. Only include items genuinely within the date window. Return real, verifiable URLs — never invent links. If you find nothing in the window, return an empty items array. Set impact based on how much the average Vue developer should care.`,\n      { label: `research:${s.key}`, phase: 'Research', schema: ITEM_SCHEMA, agentType: 'general-purpose' },\n    ),\n  ),\n)\n\nconst collected = raw.filter(Boolean)\nconst flatItems = collected.flatMap((c) => (c.items || []).map((it) => ({ ...it, source: c.source })))\nlog(`Collected ${flatItems.length} items across ${collected.length} sources`)\n\nphase('Curate')\nconst CURATED_SCHEMA = {\n  type: 'object',\n  additionalProperties: false,\n  properties: {\n    highlights: { type: 'array', items: { type: 'string' }, description: '2-4 sentence TLDR bullets of the biggest stories this week' },\n    items: {\n      type: 'array',\n      items: {\n        type: 'object',\n        additionalProperties: false,\n        properties: {\n          title: { type: 'string' },\n          url: { type: 'string' },\n          summary: { type: 'string' },\n          category: { type: 'string' },\n          impact: { type: 'string' },\n        },\n        required: ['title', 'url', 'summary', 'category', 'impact'],\n      },\n    },\n  },\n  required: ['highlights', 'items'],\n}\n\nconst curated = await agent(\n  `Here are raw newsletter candidate items gathered from multiple sources for the Vue/Nuxt week of ${label}:\\n\\n${JSON.stringify(flatItems, null, 2)}\\n\\nCurate them:\\n1. Remove duplicates (same release/article surfaced by multiple sources — keep the best canonical URL).\\n2. Drop low-quality, off-topic, or spammy entries.\\n3. Rank by impact (high first).\\n4. Write 3-5 punchy \"highlights\" bullets capturing the week's biggest stories.\\nKeep every URL exactly as provided — do not fabricate or alter links.`,\n  { phase: 'Curate', schema: CURATED_SCHEMA },\n)\n\nphase('Write')\nconst newsletter = await agent(\n  `Write a polished weekly Vue.js / Nuxt newsletter in Markdown for ${label}.\\n\\nUse this curated data:\\n${JSON.stringify(curated, null, 2)}\\n\\nStructure:\\n- A title with the week range and a one-paragraph intro setting the tone.\\n- \"📌 This Week's Highlights\" — the highlights bullets.\\n- \"🚀 Releases\" — version bumps with what changed (group Vue core + Nuxt + tooling).\\n- \"📝 Articles & Tutorials\".\\n- \"🛠️ Tooling & Ecosystem\".\\n- \"💬 Community & Discussion\".\\n- \"👤 From the Core Team & Community\" — people/company news.\\n- A short friendly sign-off.\\n\\nEvery item must be a markdown link to its real URL. Keep summaries tight and developer-focused. Omit any empty section. Output ONLY the markdown newsletter.`,\n  { phase: 'Write' },\n)\n\nreturn { newsletter, itemCount: flatItems.length, curated }\n```\n\n", "url": "https://wpnews.pro/news/claude-code-workflows-deterministic-multi-agent-orchestration", "canonical_source": "https://alexop.dev/posts/claude-code-workflows-deterministic-orchestration/", "published_at": "2026-05-28 00:00:00+00:00", "updated_at": "2026-06-16 19:57:36.749903+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "large-language-models", "generative-ai"], "entities": ["Claude Code", "Anthropic", "Vue", "Nuxt", "Jarred Sumner", "Bun", "Zig", "Rust"], "alternates": {"html": "https://wpnews.pro/news/claude-code-workflows-deterministic-multi-agent-orchestration", "markdown": "https://wpnews.pro/news/claude-code-workflows-deterministic-multi-agent-orchestration.md", "text": "https://wpnews.pro/news/claude-code-workflows-deterministic-multi-agent-orchestration.txt", "jsonld": "https://wpnews.pro/news/claude-code-workflows-deterministic-multi-agent-orchestration.jsonld"}}