Writing your own sequences
The sequences we ship are defaults, not doctrine. code-task, review-task
and research-task encode how we build. They exist so a new install is useful on
day one, and plenty of people run them unchanged and never write one.
This page is for when your process differs. It is a capability, not a step you owe anybody.
code-task is written in the format this page describes, which makes it the
longest worked example there is. toryo sequence source code-task prints it,
comments and all, once it is installed.
What you are actually writing#
A sequence is a YAML file in your own repository, under
.toryo/sequences/. Nothing is compiled into toryo, there is no plugin to
register, and there is no fork. The engine reads your file and runs it exactly as
it runs ours.
What goes in it is your own process: the steps, what each hands the next, which of them run an agent, and where the run should stop and ask a person. The things a team argues about in review, or that a senior engineer does from memory.
Because it is a file in your repository, it travels the way the rest of your code does. It is reviewed in a pull request, versioned with the code it describes, forked by another team, and handed to a new hire as a working definition of how you build rather than a wiki page about it.
Where a sequence can live#
Two homes, and a project beats the global one:
~/.toryo/sequences/: yours, on this machine, for every project.<repo>/.toryo/sequences/: the project's, and travels with it in git.
Name yours after one of ours and yours is the one that runs. That is how you
change a shipped sequence: you do not edit ours, you shadow it. Board marks a
shadowed name with a fork badge so it is never a surprise which one ran.
One name is reserved. ideas-verify is toryo's own maintenance machinery, fired
on a schedule, and it refuses to be replaced by a file of that name.
Four ways to make one#
None of them is a text editor unless you want it to be.
Describe it to an agent#
Board's Sequence Design screen has an Author with agent door. You say what
you want in prose, an agent drafts the YAML, and you keep talking until it is
right. Every turn snapshots the draft it started from, so any turn can be
reverted.
The draft lives outside your live sequences directory until you accept it, so nothing half-finished is ever runnable. And board re-validates the file itself on every turn rather than trusting the agent's summary: Accept stays disabled until that check is clean, whatever the agent claimed it did.
Fill in a form#
The same screen's detail rail has a Parameters view over any sequence's
input: fields. Each one binds to Ask at run time, Default, or Fixed.
Fixed is the one worth knowing. Pin baseBranch: main for your team and the
run form stops asking: the field disappears from the launcher instead of being
answered identically forever.
Amendments patch the document rather than rewriting it, so your comments and layout survive.
Write the YAML#
The editor is right there on the same screen, and toryo sequence validate is
the same gate from a terminal:
toryo sequence validate ./my-sequence.yaml
It compiles the file and reports unknown steps, steps nothing can reach, disallowed fields, bad routing, and template tokens that will not resolve. Run it before anything else.
If you are writing YAML with an agent's help in your own session, the
/toryo-sequence-authoring skill is the full format reference and is already
installed.
Import somebody else's#
toryo sequence import ForceBuilders/toryo-sequences --path sequences/nightly.yaml
import fetches the file, compiles it, prints the whole thing, and writes it only
once you say yes. A GitHub source is pinned to a commit sha first, and the written
file carries a provenance header naming where it came from and the digest of what
arrived.
Read the prompts before you accept. The format is pure data, so loading a stranger's file cannot execute anything inside toryo itself. That says nothing about what the sequence does: a worker step's prompt reaches an agent session with a shell. That is why the preview prints every prompt verbatim and never truncates, and why import is a terminal command rather than a button.
Managing the files#
Five verbs, so nothing has to be dropped into a directory by hand. Each takes an
optional --project naming which home to act on.
toryo sequence create nightly-triage --file draft.yaml
toryo sequence source nightly-triage > draft.yaml
toryo sequence clone nightly-triage weekly-triage
toryo sequence edit nightly-triage --file draft.yaml
toryo sequence delete weekly-triage --project my-repo
sourcegives you the file's bytes back, comments and all, and piping it intoeditround-trips exactly.create,cloneandeditrun the validate gate before touching disk, and the write is atomic. A rejected edit leaves the previous file exactly as it was, so a bad change can never leave you with half a sequence.clonerewrites the name textually, so the copy keeps your comments.editnever renames. Renaming isclonethendelete.
Two things are refused on purpose. A shipped sequence cannot be cloned, edited or read back as source, because ours are code rather than YAML and there is nothing to copy. Write your own under the same name instead, which is the supported way to change one. And toryo's own maintenance sequences refuse edit and delete, so a scheduled job cannot have its machinery pulled out from under it.
What a step can be#
Five kinds, covered on Sequence: worker (an agent session),
completion (one model call returning JSON you declared the shape of),
transform (reshape the last step's output), setup (the side-effecting one:
mint a git worktree, clone a repo, copy files into place, run a command), and
human (stop and ask you).
A human gate is worth designing rather than accepting. It can show the operator files the run produced, link out to something an earlier step made (the pull request, say), put the agent's own questions in front of them as pickable options, and render decision buttons you named rather than a generic form.
Four smaller knobs are worth knowing because they answer questions the obvious form of the file cannot:
- A step's harness can be chosen per run, from a value the caller passed or
an earlier step produced (
llm: {from: run.providers.plan, cases: …}). The path may reach into a nested input field, and every segment is checked when the file loads rather than silently taking the fallback forever. - A step's write scope can come from an earlier step (
writeScopeFrom: steps.plan.output.predictedPaths) instead of being a list you type. That is how two runs touching the same files queue behind each other rather than racing: the planner predicts the change-set and the implementer declares it. - A
sandboxtransform is handed the run's artifact directory asstate.runDir, so a transform that builds a prompt can name a path the agent it feeds will read. There is still no filesystem inside the sandbox. - A step's prompt can have its varying parts computed (
promptFrom:), by your own TypeScript in that same sandbox. The prose stays in the file, where you can read and grep it; only the parts that actually change (a block a retry carries, a capped list, a sentence that pluralises) come from code, as fields the template names. It runs inside the step it builds, so what it printed and how long it took land on that step's own row.
An edit never disturbs a running run#
A run pins the sequence it started with. Edit the file mid-run and the run in flight carries on against what it began with, while the next run picks up your change. There is no daemon to restart and no window where a half-saved file is what executes.
Where things go wrong#
validatefails on a template token. The step you referenced does not run before this one, or you spelled its output field differently.- A warning names a disabled harness. The file is fine; this machine has that harness switched off. See Harnesses.
- Board shows a
forkbadge. A file is shadowing a shipped sequence of the same name. That is the mechanism working, but it is worth knowing which one ran. editis refused on a shipped sequence. Expected. Create your own file under that name instead.
Full command surface: CLI & contract reference.