Skip to main content
Early Access. Commands and behavior can change between releases.
A workflow is a small JavaScript program that dispatches sub-agents and combines what they send back. agent(prompt) starts one and resolves to its final text, so running ten reviewers at once is await parallel([...]): ordinary code, with the agents doing the thinking. You don’t need a flag or a keyword. Architech uses a workflow on its own when the work has a shape: the same operation over a list, or independent pieces that could run at once. Save that shape in your repo and you can run it by name.

A workflow you can run

Save this as .architech/workflows/review-changed.js:
.architech/workflows/review-changed.js
Then ask for it:
Three reviewers start at the same time. When all three are back, a fourth agent merges their notes into one list. You get the merged list, plus a row in the transcript that showed both phases live.

Background runs

Ask Architech to run a workflow in the background when you have other work to do. It starts the workflow with run_in_background: true, gets a job_id, and receives the result when it finishes. It can read the status or full result again with Workflow({ job_id: "workflow-1" }) without starting the agents again. In an interactive session, Ctrl+Shift+B sends running foreground workflows to the background. Their agents keep running; nothing restarts. Your terminal must send this key combination as its own key. The last 50 finished background results stay available in the current session. Restarting or switching sessions drops the handles, not the agents already in the fleet list. Use the fleet list to inspect or stop single agents; Jobs doesn’t list background workflow results.

When a workflow is the right tool

Reach for one

The same operation repeats over a list · independent readers can run at once · each item flows through the same few stages · you want to run it again next week without retyping it.

Don't

The work is one question: ask it directly · each step depends on what the last one found · you’d be writing the analysis into the script instead of letting the agents do it.
A single prompt is usually better. Every agent() call is a full model run with its own context, so a workflow that fans out five ways costs about five times one agent, plus the merge. That’s worth it when five agents read five different things, and a waste when you split a question with one answer. The script is control flow, not analysis. Keep it short; let the agents think.

Where workflows live

Files in .architech/workflows/ are ordinary source files: commit them, review them in a pull request, share them with your team. Use .js for new workflows. Architech also picks up existing .ts files, but their bodies must still be plain JavaScript.
The body is plain JavaScript, whatever you name the file. It runs in an isolated JavaScript context, not through your bundler. No import statements and no TypeScript type annotations: either is a syntax error that fails the run before its first agent starts.

The meta block

A saved workflow declares a meta object so it can be listed and described without being run.
Architech reads meta by pattern; it doesn’t run it. So two things matter:
  • Write it at the top level as export const meta = { … }, with the closing } at the start of its own line.
  • Give name and description plain string literals: not a variable, not a template with a substitution in it.
A file without a readable meta is left out of the list, not run, and /workflows says how many it skipped. Architech never runs a file in .architech/workflows/ just to find out what it is.

Running one

Ask for a saved workflow by name and Architech passes the values you named through as args:
A workflow does not have to be a file. Describe a shape and Architech writes and runs the script inline for a one-off:

args

args arrives in the script as Architech passed it (an object or list sent as a JSON string is decoded first). It’s what makes a script reusable, so read it at the top and give it a shape you can rely on:

The script API

A script can use these six things and nothing else: no require, no timers, no file system, no network. Return a value from the top level and it becomes the workflow’s result. console is available for debugging.

agent(prompt, opts)

Workflow agents are sub-agents like any other: they appear in the fleet list alongside anything you started by hand.

Failure is a value, not an exception

  • An agent() whose run fails resolves to a string beginning [agent failed: …]. Your script keeps going, and can branch on it.
  • An agent() that runs past its time limit resolves to [agent timed out: …]. The agent itself keeps running in the fleet list. A late result replaces the timeout marker only when the thunk or stage returns that marker unchanged and its parallel() or pipeline() is still waiting. A direct await agent(), a transformed marker or an already-returned combinator is not retroactively updated just because the rest of the workflow is still running.
  • A thunk that throws inside parallel() becomes null in that slot; the others are unaffected.
  • A stage that throws inside pipeline() drops that item to null; the other items keep flowing.
  • A script that throws, or has a syntax error, fails the run, never the session, and every agent it had already dispatched is still reported.
An agent that never starts can return [agent never started: …] when its queue-wait limit is reached. So check for null, [agent failed:, [agent timed out: and [agent never started: before feeding a result into the next prompt.

Two rules

Math.random() and Date.now() throw

Both are removed inside a workflow, and calling either fails the run with a message saying so. A workflow should be re-runnable: the same script with the same args should describe the same run. A script that rolls a die or reads the clock takes a different path each time, and its record no longer matches what it would do again. If you need a seed or a timestamp, decide it outside and pass it in through args:
new Date() is not blocked, but it has the same problem. Take the time from args too.

Label every agent

The live view names each row by opts.label. Give every agent() call a label that says which piece of work it is:
Without a label, the row shows the agent’s number and the cut-off first line of its prompt. Three similar prompts then give you three similar rows, just when you need to see which one is stuck.

What a run looks like

A workflow shows as a live row that fills in as it runs. Phases open and close, each agent gets a line with its state and run time, and the last line sums up the run.
Past eight agents in a phase, extra rows are counted (+ 4 more), never dropped. On a narrow terminal the block folds into fewer, denser lines without losing information. The row stays in your transcript after the run ends.

Limits

There is no budget cap and no runaway limit. Nothing counts what a workflow spends, and nothing stops a script that starts far more agents than you meant. parallel(items.map(…)) over a thousand-item list queues a thousand agents: sub-agents run up to 15 at a time by default and the rest wait in a queue, but every one of them runs. Bound the list in the script.
  • One agent gets ten minutes by default, counted from when it starts, not while it waits in the queue. After that its call stops waiting and resolves to a timed-out string; the agent is not stopped, and the rest of the run continues. Change it per call with timeoutMs.
  • The run itself is not time-limited. It ends when the script returns. Agents still running at that point are named in the result and keep running in the fleet list.
  • No resumable workflow history is persisted. The result and its digest live in the transcript; background handles live only in this session. Running a workflow again runs it from the top.
  • A workflow cannot reach the disk or the network itself. Only the agents can, through their own tools.
  • If sub-agents aren’t available, the workflow refuses up front and says why, instead of hanging on its first agent() call. architech --prime has no Workflow tool; workflows run in normal orchestrator and agent sessions.

Sub-agents

The fleet list and the viewer, where a workflow’s agents show up.