foldrun 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -16
- package/bin/foldrun.mjs +333 -46
- package/docs/agents.md +483 -0
- package/docs/api-usage.md +156 -0
- package/docs/api.md +435 -0
- package/docs/backups-and-restore.md +171 -0
- package/docs/budgets-and-billing.md +362 -0
- package/docs/cli.md +449 -0
- package/docs/coding-agents.md +224 -0
- package/docs/deploying.md +77 -0
- package/docs/evals.md +90 -0
- package/docs/faq.md +53 -0
- package/docs/flows.md +670 -0
- package/docs/getting-started.md +142 -0
- package/docs/glossary.md +78 -0
- package/docs/harness.md +128 -0
- package/docs/how-it-works.md +255 -0
- package/docs/introduction.md +47 -0
- package/docs/knowledge-and-memory.md +85 -0
- package/docs/notifications.md +320 -0
- package/docs/providers.md +241 -0
- package/docs/runs.md +238 -0
- package/docs/scheduling.md +103 -0
- package/docs/secrets.md +163 -0
- package/docs/security.md +167 -0
- package/docs/self-hosting.md +65 -0
- package/docs/status.md +73 -0
- package/docs/storage-and-sharing.md +118 -0
- package/docs/team-and-access.md +146 -0
- package/docs/tools.md +1810 -0
- package/docs/troubleshooting.md +155 -0
- package/docs/versions.md +79 -0
- package/docs/workspaces.md +160 -0
- package/package.json +9 -5
- package/src/commands.mjs +6487 -260
- package/src/guide.mjs +172 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Getting started
|
|
2
|
+
|
|
3
|
+
An agent is a folder. A flow is a numbered list. There is no build step — the
|
|
4
|
+
files are the program — so the loop is edit, check, run, deploy.
|
|
5
|
+
|
|
6
|
+
## Install and make something that runs
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install -g foldrun
|
|
10
|
+
export ANTHROPIC_API_KEY=sk-ant-... # an API key from console.anthropic.com
|
|
11
|
+
# or: export CLAUDE_CODE_OAUTH_TOKEN=... from `claude setup-token` (see the CLI reference)
|
|
12
|
+
|
|
13
|
+
foldrun init my-account
|
|
14
|
+
cd my-account
|
|
15
|
+
foldrun check # free: no model is called
|
|
16
|
+
foldrun run publish --task "write about rain"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`init` scaffolds an **account folder** with one workspace in it, and that
|
|
20
|
+
workspace already works: two agents, a flow that names them, an eval, and
|
|
21
|
+
knowledge they share. `check` validates all of it offline —
|
|
22
|
+
run it after edits the way you would run a typecheck. It is the cheapest
|
|
23
|
+
feedback in the system and it catches a broken flow before a schedule fires it
|
|
24
|
+
at 3am rather than after.
|
|
25
|
+
|
|
26
|
+
## What you just made
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
my-account/
|
|
30
|
+
AGENTS.md context every workspace here inherits
|
|
31
|
+
library/ tools, skills, scripts shared by all of them
|
|
32
|
+
workspaces/
|
|
33
|
+
main/
|
|
34
|
+
AGENTS.md context every agent in THIS workspace sees
|
|
35
|
+
agents/researcher/agent.md one role: persona, model, tools
|
|
36
|
+
agents/writer/agent.md
|
|
37
|
+
flows/publish.md the steps, in order
|
|
38
|
+
knowledge/ what you tell the agents
|
|
39
|
+
memory/ what they worked out — they write here
|
|
40
|
+
evals/ tests for agents
|
|
41
|
+
CLAUDE.md conventions, for your editor
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
That is the shape the platform keeps, so the folder you edit is the folder that
|
|
45
|
+
runs. `--workspace <name>` names the first workspace (default `main`) and
|
|
46
|
+
`foldrun new <name>` adds another. `foldrun init --flat` makes the older
|
|
47
|
+
single-folder shape instead, and every command still reads it.
|
|
48
|
+
|
|
49
|
+
`CLAUDE.md` is the one file foldrun never reads. It is there so Claude Code and
|
|
50
|
+
its peers know the layout instead of guessing at it.
|
|
51
|
+
|
|
52
|
+
## Writing an agent
|
|
53
|
+
|
|
54
|
+
Frontmatter, then prose. **The prose is the system prompt**, so write it to be
|
|
55
|
+
read by a model: what the role is for, what it must not do, what good looks
|
|
56
|
+
like.
|
|
57
|
+
|
|
58
|
+
```markdown
|
|
59
|
+
---
|
|
60
|
+
name: researcher
|
|
61
|
+
description: Finds and summarises sources.
|
|
62
|
+
model: default
|
|
63
|
+
tools: [web, write]
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
You research a topic and report what you found. Prefer primary sources.
|
|
67
|
+
Say when you could not find something rather than inferring it.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Only `name` and the prose are required. Every other field widens or narrows
|
|
71
|
+
what the agent can reach, and the default is narrow.
|
|
72
|
+
|
|
73
|
+
A field that names files — `tools:`, `skills:`, `agents:` — takes the same
|
|
74
|
+
`[[link]]` the prose does, or a bare name; both mean the same thing. Use the
|
|
75
|
+
block form when you link:
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
tools:
|
|
79
|
+
- read # a built-in group
|
|
80
|
+
- [[site_repo]] # your own tools/site_repo.md
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## If you use Claude Code
|
|
84
|
+
|
|
85
|
+
A subagent at `.claude/agents/<name>.md` **deploys as a foldrun agent** — no
|
|
86
|
+
conversion, no second format. Write it however Claude Code taught you and it
|
|
87
|
+
becomes a role on the platform.
|
|
88
|
+
|
|
89
|
+
## Running it somewhere that is not your laptop
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
foldrun login # approve it in the browser, once
|
|
93
|
+
foldrun deploy # pushes this workspace
|
|
94
|
+
foldrun invoke publish --wait # runs it there
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`foldrun login` signs in to the hosted platform; `foldrun login --url
|
|
98
|
+
https://your-server` to your own. In CI, set `FOLDRUN_URL` and
|
|
99
|
+
`FOLDRUN_TOKEN` (Settings → API keys) instead — see [Deploying](/deploying/).
|
|
100
|
+
|
|
101
|
+
A deploy is checked before any of it goes live, and it refuses while a run is
|
|
102
|
+
in flight — swapping files under a running flow means step 3 reads agents that
|
|
103
|
+
step 1 never saw. `--force` overrides that when you mean to.
|
|
104
|
+
|
|
105
|
+
It never touches `runs/`, `state/`, `secrets.json`, or memory an agent wrote
|
|
106
|
+
that your push does not mention. Those belong to the platform, not to git: a
|
|
107
|
+
deploy that reverted what an agent learned would make every run a little
|
|
108
|
+
dumber.
|
|
109
|
+
|
|
110
|
+
## Secrets
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
foldrun secrets set STRIPE_KEY # prompted, never echoed, never in a file
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Agents name them in `secrets:` and receive the value at run time. They are never
|
|
117
|
+
written into the workspace, so a workspace is always safe to commit.
|
|
118
|
+
|
|
119
|
+
## The checklist on the dashboard
|
|
120
|
+
|
|
121
|
+
A new account's home page shows a **Getting started** card: create a
|
|
122
|
+
workspace, write or deploy an agent, run a flow, get a run to finish, add a
|
|
123
|
+
secret, schedule a flow or give it a webhook, invite a teammate, set up
|
|
124
|
+
billing (where the plan asks for it) and install the CLI — "4 of 8", with the
|
|
125
|
+
next step first and a link to where to do it. Each step is worked out from
|
|
126
|
+
the account as it is (a run on record, a secret in the vault, a key minted
|
|
127
|
+
for the CLI), so it ticks itself whichever way you did the thing; there is
|
|
128
|
+
nothing to mark. **Dismiss** hides it for you alone; the line at the foot of
|
|
129
|
+
the page brings it back, and it goes away by itself once every step is done.
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
foldrun onboarding # the same steps, in the terminal
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The API is `GET /api/me/onboarding`; hiding the card is a person's own
|
|
136
|
+
setting, so it is done from the dashboard, not with a key.
|
|
137
|
+
|
|
138
|
+
## Where to go next
|
|
139
|
+
|
|
140
|
+
- **The grammar** — every field an agent or flow can carry: Help
|
|
141
|
+
- **The API** — driving a deployed workspace over HTTP: the API reference
|
|
142
|
+
- **The CLI** — every command and flag: the CLI reference
|
package/docs/glossary.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Glossary
|
|
2
|
+
|
|
3
|
+
**account** — the top level: people, keys, the library, the wallet, and the
|
|
4
|
+
workspaces under it. Has one owner.
|
|
5
|
+
|
|
6
|
+
**agent** — one role: a folder with an `agent.md` whose frontmatter grants and
|
|
7
|
+
whose prose is the prompt.
|
|
8
|
+
|
|
9
|
+
**AGENTS.md** — context and defaults, at the account and at each workspace.
|
|
10
|
+
Prose accumulates downward; a frontmatter key replaces whole.
|
|
11
|
+
|
|
12
|
+
**budget** — a cap: per run (in a flow, or on an agent for its own steps),
|
|
13
|
+
per workspace over a day, week or month, per account the same. Unset is no
|
|
14
|
+
limit.
|
|
15
|
+
|
|
16
|
+
**conclusion** — a step's final reply, as opposed to every turn joined. What
|
|
17
|
+
checks and headlines read.
|
|
18
|
+
|
|
19
|
+
**desk** — an everyday name for a workspace that does one job on its own —
|
|
20
|
+
a blog desk, a Reddit desk — its agents and flows, running on a schedule.
|
|
21
|
+
Nothing in the format is called a desk; it is a workspace.
|
|
22
|
+
|
|
23
|
+
**deploy** — pushing a workspace's source tree to the platform, by
|
|
24
|
+
`foldrun deploy` or `git push`. Never touches runs, state, secrets or memory.
|
|
25
|
+
|
|
26
|
+
**eval** — a test for an agent or a flow: a task and what a good answer
|
|
27
|
+
must contain. Runs on every push.
|
|
28
|
+
|
|
29
|
+
**flow** — orchestration: a numbered list of steps. Same number, same time.
|
|
30
|
+
|
|
31
|
+
**gate** — a step that parks the run for a person (`!`, `approve:`, `ask:`).
|
|
32
|
+
|
|
33
|
+
**group** — the steps that share a number. A step is handed every earlier
|
|
34
|
+
group's replies.
|
|
35
|
+
|
|
36
|
+
**headline** — the first meaningful line of a step's conclusion. The run's
|
|
37
|
+
headline is the last step's.
|
|
38
|
+
|
|
39
|
+
**knowledge** — what people give an agent. Read by all, written by none.
|
|
40
|
+
|
|
41
|
+
**library** — the account's shared tools, skills, knowledge and memory.
|
|
42
|
+
Nearest wins: a workspace shadows it by defining the same name.
|
|
43
|
+
|
|
44
|
+
**memory** — what an agent learned, one fact per file. The one place it
|
|
45
|
+
writes without a grant.
|
|
46
|
+
|
|
47
|
+
**preview** — a copy of a workspace deployed from a branch, evals run,
|
|
48
|
+
schedules off, deleted with the branch.
|
|
49
|
+
|
|
50
|
+
**run** — the record of a flow being driven: every step, event and cost.
|
|
51
|
+
|
|
52
|
+
**sandbox** — where a step executes: a container or a gVisor pod, made for
|
|
53
|
+
the step and destroyed after it.
|
|
54
|
+
|
|
55
|
+
**share** — a public link to one file in `storage/`, tokened, expiring.
|
|
56
|
+
|
|
57
|
+
**skill** — a capability an agent loads when a task matches, in the open
|
|
58
|
+
Agent Skills format. Inherited unless allowlisted.
|
|
59
|
+
|
|
60
|
+
**state** — what the next run needs from this one. Travels with a deploy,
|
|
61
|
+
never overwritten by one.
|
|
62
|
+
|
|
63
|
+
**storage** — bytes a person reads or downloads. Regenerated each run.
|
|
64
|
+
|
|
65
|
+
**tier** — `fast`, `default`, `max`: which brain, resolved to a model by the
|
|
66
|
+
platform so agents do not rot when models are renamed.
|
|
67
|
+
|
|
68
|
+
**tool** — what an agent may call: an API, a script, an MCP server. Granted
|
|
69
|
+
by name in `tools:`; absent unless named.
|
|
70
|
+
|
|
71
|
+
**trigger** — how a flow starts: a person, a schedule, a webhook, an email,
|
|
72
|
+
another flow, a file, a URL that changed.
|
|
73
|
+
|
|
74
|
+
**verify** — a check on a step's outcome: a shell command, or `contains:`,
|
|
75
|
+
`matches:`, `file:`, `judge:`. Where arithmetic goes.
|
|
76
|
+
|
|
77
|
+
**workspace** — a folder, and the unit of editing, deploying, permission,
|
|
78
|
+
budget and backup.
|
package/docs/harness.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# The harness
|
|
2
|
+
|
|
3
|
+
The model decides. The harness decides what that decision may touch, and what
|
|
4
|
+
counts as done.
|
|
5
|
+
|
|
6
|
+
Everything in this page already exists somewhere else in these docs: gates are
|
|
7
|
+
in [Flows](flows), budgets in [Budgets](budgets-and-billing), grants in
|
|
8
|
+
[Agents](agents). This page is the other way round: not what each field does,
|
|
9
|
+
but **what a step needs before it is safe to leave running while you sleep.**
|
|
10
|
+
|
|
11
|
+
## The five jobs
|
|
12
|
+
|
|
13
|
+
| job | what it answers | where it lives |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| Reach | what may it touch | `tools:`, `secrets:`, the sandbox, the egress boundary |
|
|
16
|
+
| Truth | how do we know it worked | `verify:`, `confirm=`, `until:` |
|
|
17
|
+
| Cost | what does being wrong cost | `budget:`, `timeout:`, `max:` |
|
|
18
|
+
| Consent | who says yes to the irreversible | `4!.`, `ask:`, `preview:` |
|
|
19
|
+
| Memory | how do we find out afterwards | the run record, `notify:`, the ledger |
|
|
20
|
+
|
|
21
|
+
A gap in any one is a different accident. A step with no reach limit does harm.
|
|
22
|
+
A step with no truth check **reports success it did not earn**, which is worse,
|
|
23
|
+
because nobody comes looking.
|
|
24
|
+
|
|
25
|
+
## The checklist
|
|
26
|
+
|
|
27
|
+
Run any step that acts on the outside world through these eight.
|
|
28
|
+
|
|
29
|
+
**1. Can it only do its job?**
|
|
30
|
+
Grant the tools it needs and no more. An agent that must not edit gets `read`,
|
|
31
|
+
not `write`. The publisher that posts should not hold the tool that rewrites
|
|
32
|
+
what it is posting — on 2026-09-14 a send step edited its own gate file to get
|
|
33
|
+
past a guard, and the fix was taking the editing tools away, not asking it
|
|
34
|
+
nicely.
|
|
35
|
+
|
|
36
|
+
**2. Does the runtime know it worked?**
|
|
37
|
+
"The tool returned ok" is not evidence. A save can report success and revert.
|
|
38
|
+
Use `confirm=` on a browser call that writes, and `verify:` on the step:
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
2. [[publisher]] — post the approved draft
|
|
42
|
+
verify: matches: (^|\n)[#*_>\s]*GOOD\b.*/comments/
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**3. Does the failure say what to do?**
|
|
46
|
+
A check that fails with "exit 1" costs somebody an hour. Write the fix into
|
|
47
|
+
the message:
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
verify: node -e "const fs=require('fs');if(!fs.existsSync('workspace/storage/unanswered.csv')){console.error('the scan wrote no storage/unanswered.csv, and the next step fans out over it. Fix: run the tool once per office and let it write the file.');process.exit(1)}"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**4. Is a retry safe?**
|
|
54
|
+
`retry:` is for flakiness — a timeout, a 503, a cold start. It is not for a
|
|
55
|
+
refusal. A credential that was rejected will be rejected again, and repeating
|
|
56
|
+
a refused write is how a silent 403 becomes a block on your whole address.
|
|
57
|
+
When a step can be refused rather than merely fail, say so in the agent: one
|
|
58
|
+
`BLOCKED` reply naming the secret to renew, and no second attempt.
|
|
59
|
+
An outward step is not retried when its check fails after its tools ran:
|
|
60
|
+
the email went, and a retry would send it again. A failure mid-send is still
|
|
61
|
+
retried, so `check` and `deploy` warn on `retry:` on any outward step.
|
|
62
|
+
|
|
63
|
+
**5. Who approves the irreversible?**
|
|
64
|
+
`!` or `ask:` on the step that spends money, sends mail or publishes, with
|
|
65
|
+
`preview:` pointing at the artefact itself. The gate belongs **where the
|
|
66
|
+
irreversible thing happens**, not at the end of the flow: everything before it
|
|
67
|
+
should be research that costs cents.
|
|
68
|
+
|
|
69
|
+
**5b. Does the tool say it is outward?**
|
|
70
|
+
Mark it `outward: true` in the tool's frontmatter. `check` then refuses any
|
|
71
|
+
step that grants it without a `verify:` or a gate, so the rule on this page
|
|
72
|
+
stops being advice.
|
|
73
|
+
|
|
74
|
+
**6. Is it recorded before it happens?**
|
|
75
|
+
Write the ledger row before the call, with the run id and the external id,
|
|
76
|
+
`pending` first and the outcome after. A row written afterwards is missing
|
|
77
|
+
exactly when you need it: when the call half-succeeded.
|
|
78
|
+
|
|
79
|
+
**7. Will you hear about it?**
|
|
80
|
+
`notify:` with at least `failed`. A desk nobody is told about is a desk that
|
|
81
|
+
fails quietly for a week.
|
|
82
|
+
|
|
83
|
+
**8. What did it cost?**
|
|
84
|
+
Every step records its own cost and the run carries the total. Add `budget:`
|
|
85
|
+
where you want a ceiling; leave it off where you do not. Unset means no limit,
|
|
86
|
+
and the platform invents no default.
|
|
87
|
+
|
|
88
|
+
## Truth is the one people skip
|
|
89
|
+
|
|
90
|
+
Reach and consent feel like security, so they get done. Truth feels like
|
|
91
|
+
paperwork, so it gets skipped, and it is the one that fails silently.
|
|
92
|
+
|
|
93
|
+
The pattern to internalise: **a write is not done until something other than
|
|
94
|
+
the writer says so.** In a browser that is `confirm=`, which reloads the page
|
|
95
|
+
and requires the change to be in what the server returns. For a file it is a
|
|
96
|
+
`verify:` that reads the file back. For an outward action it is the ledger row
|
|
97
|
+
and the read-back of the external record.
|
|
98
|
+
|
|
99
|
+
On 2026-09-17 a desk drove Medium for hours. Every fill reported ok, every Save
|
|
100
|
+
reported ok, and every value was gone on the next load, because a Cloudflare
|
|
101
|
+
challenge had quietly started refusing writes. Nothing in the logs was false.
|
|
102
|
+
There was simply nothing in the system that asked the server what it had.
|
|
103
|
+
|
|
104
|
+
## The harness has to guard itself
|
|
105
|
+
|
|
106
|
+
Everything above is about an agent's work. The same questions apply to the
|
|
107
|
+
platform's own credentials, and they are easier to get wrong because nothing
|
|
108
|
+
fails until everything does.
|
|
109
|
+
|
|
110
|
+
The rule that matters: **a credential is read when it is used, never held from
|
|
111
|
+
boot.** The platform's model key is a mounted file, read per step
|
|
112
|
+
(`FOLDRUN_MODEL_KEY_FILE`), so a refresh reaches the next step by itself.
|
|
113
|
+
Before that it was an environment variable, and since refreshing an OAuth
|
|
114
|
+
token revokes the old one, every refresh needed a restart that could not
|
|
115
|
+
happen while work was in flight. That is not a scheduling problem to be tuned;
|
|
116
|
+
it is a design where the correct behaviour is impossible on a busy day.
|
|
117
|
+
|
|
118
|
+
If you take one thing from this section: a credential your system cannot
|
|
119
|
+
reload without stopping is a credential that will expire at the worst moment,
|
|
120
|
+
and the failure will look like something else.
|
|
121
|
+
|
|
122
|
+
## What this does not cover
|
|
123
|
+
|
|
124
|
+
The harness constrains an agent; it does not make it correct. A step can pass
|
|
125
|
+
every check in this page and still write a bad article, pick the wrong lawyer
|
|
126
|
+
or mis-read a rule. That is what [evals](evals) are for, and what a reviewer
|
|
127
|
+
step is for. The checklist keeps a wrong answer cheap and visible; it does not
|
|
128
|
+
make the answer right.
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# How it works
|
|
2
|
+
|
|
3
|
+
Eight nouns, one reference syntax, and a flow that is a numbered list. Nothing
|
|
4
|
+
here is a framework you import — every one of these is a markdown file you can
|
|
5
|
+
open, diff and review.
|
|
6
|
+
|
|
7
|
+
## The eight nouns
|
|
8
|
+
|
|
9
|
+
Four are **grants**: an agent has them because its file says so, and reading
|
|
10
|
+
that one file tells you the blast radius.
|
|
11
|
+
|
|
12
|
+
| | |
|
|
13
|
+
|---|---|
|
|
14
|
+
| **agent** | one role — a folder with an `agent.md` |
|
|
15
|
+
| **flow** | orchestration — a numbered list of steps |
|
|
16
|
+
| **tool** | what it may call: an API, a script, or an MCP server |
|
|
17
|
+
| **skill** | a capability it loads when a task matches |
|
|
18
|
+
|
|
19
|
+
Four are **places**: always there, never granted. They differ only by who may
|
|
20
|
+
write.
|
|
21
|
+
|
|
22
|
+
| | who writes | |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| **knowledge/** | nobody | given to it; reading is denied to nothing, writing to everything |
|
|
25
|
+
| **memory/** | the agent | what it learned, one fact per file, indexed |
|
|
26
|
+
| **state/** | the workspace | the bookmark between runs |
|
|
27
|
+
| **storage/** | anyone | bytes, not source — PDFs, CSVs, images |
|
|
28
|
+
|
|
29
|
+
The line between the last two is worth learning early: a value **regenerated**
|
|
30
|
+
each run is `storage/`; a value **accumulated** across runs is `state/`.
|
|
31
|
+
|
|
32
|
+
Capability is opt-in, knowledge cascades. `tools:` grants nothing until you
|
|
33
|
+
name it. `skills:` is the opposite — leave it out and the agent inherits every
|
|
34
|
+
skill in scope; write it and it becomes an allowlist. An empty `skills: []`
|
|
35
|
+
therefore withholds all of them, which is legal and almost never what someone
|
|
36
|
+
means.
|
|
37
|
+
|
|
38
|
+
## `[[name]]` — the one reference syntax
|
|
39
|
+
|
|
40
|
+
The rule is one sentence: **if it names a file, you can link it.** Agents,
|
|
41
|
+
flows, skills, tools, knowledge and memory are files. Secrets, `model:`,
|
|
42
|
+
`size:` and `effort:` are values, and are never linked.
|
|
43
|
+
|
|
44
|
+
| where | what it means |
|
|
45
|
+
|---|---|
|
|
46
|
+
| first link on a step line | **structural** — the agent that step runs |
|
|
47
|
+
| `[[flow:weekly]]` on a step line | a whole flow, composed in place |
|
|
48
|
+
| in any prose | resolved to the real relative path before the model sees it |
|
|
49
|
+
| `[[storage/leads.csv]]` | that file |
|
|
50
|
+
| `[[storage/]]`, `[[state/]]` | the folder, when you mean *where* rather than *which* |
|
|
51
|
+
| in `tools:`, `skills:`, `agents:`, `delegate:`, `after:` | the same name, spelled as a link |
|
|
52
|
+
|
|
53
|
+
Names match on filename **or** the document's own `title:`/`name:`, blind to
|
|
54
|
+
case, hyphens and underscores — so a link survives a rename that a literal
|
|
55
|
+
path would not. Anything unmatched passes through as written: the syntax is
|
|
56
|
+
sugar over paths, never a gate, and a typo never breaks a run.
|
|
57
|
+
|
|
58
|
+
Two details worth knowing:
|
|
59
|
+
|
|
60
|
+
- **Links expand only where text becomes a prompt** — an agent's body, a step's
|
|
61
|
+
instruction, an eval's task. Inside a knowledge or tool document they stay
|
|
62
|
+
literal, because there the link is for the person reading.
|
|
63
|
+
- **In `tools:`, the brackets mean "mine."** A bare `search` is the platform's
|
|
64
|
+
search group; `[[search]]` is your `tools/search.md`. That is the only way
|
|
65
|
+
to grant a tool named after a built-in.
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
tools:
|
|
69
|
+
- read # a built-in group
|
|
70
|
+
- [[site_repo]] # your own tools/site_repo.md
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Use the block form when you link. To YAML, `[[x]]` is a nested list, so the
|
|
74
|
+
inline `tools: [read, [[site_repo]]]` parses correctly but reads badly.
|
|
75
|
+
|
|
76
|
+
The idiom to write by: **link what you read, spell out what you write.** A link
|
|
77
|
+
points at something that exists — an input. An output destination does not
|
|
78
|
+
exist yet, so it stays a literal path.
|
|
79
|
+
|
|
80
|
+
## A flow is a numbered list
|
|
81
|
+
|
|
82
|
+
Steps run in ascending order, and each receives the previous group's results.
|
|
83
|
+
Output passing is the default, not configuration.
|
|
84
|
+
|
|
85
|
+
```markdown
|
|
86
|
+
1. [[researcher]] — gather this week's competitor updates
|
|
87
|
+
2. [[writer]] — turn the research into a 300-word digest at outputs/digest.md
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Steps sharing a number run in parallel**, and the next group receives every
|
|
91
|
+
result, labelled per agent. The number is the whole scheduling model:
|
|
92
|
+
|
|
93
|
+
```markdown
|
|
94
|
+
1. [[researcher]] — gather the facts
|
|
95
|
+
2. [[optimist]] — argue the bull case
|
|
96
|
+
2. [[skeptic]] — argue the bear case
|
|
97
|
+
3. [[editor]] — weigh both and write the verdict
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`2?` marks a step optional — it fails without failing the flow. `2!` parks it
|
|
101
|
+
for a human.
|
|
102
|
+
|
|
103
|
+
### Routing
|
|
104
|
+
|
|
105
|
+
`case:` steps in one group are exclusive branches: the first whose text appears
|
|
106
|
+
in the previous results runs, and an `else:` step runs when none matched.
|
|
107
|
+
|
|
108
|
+
```markdown
|
|
109
|
+
1. [[classifier]] — reply with exactly one word, BUG or QUESTION
|
|
110
|
+
2. [[debugger]] — investigate and fix
|
|
111
|
+
case: BUG
|
|
112
|
+
2. [[writer]] — answer it clearly
|
|
113
|
+
case: QUESTION
|
|
114
|
+
2. [[triager]] — neither label fit; say what is missing
|
|
115
|
+
else: true
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`when:` is the non-exclusive sibling — every matching step runs. That is why
|
|
119
|
+
routing has its own word instead of being a mode on `when:`.
|
|
120
|
+
|
|
121
|
+
### The critic loop
|
|
122
|
+
|
|
123
|
+
```markdown
|
|
124
|
+
1. [[writer]] — draft the post
|
|
125
|
+
2. [[editor]] — review it; end your reply with APPROVED when it is ready
|
|
126
|
+
loop: 3
|
|
127
|
+
until: APPROVED
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The marker must stand **alone on its own line**. "APPROVED once the citation is
|
|
131
|
+
fixed" contains the word but is a rejection, and reading it as a pass would end
|
|
132
|
+
the loop with the correction unmade — which is the failure the loop exists to
|
|
133
|
+
prevent. Generate–critique–revise, with the model deciding only whether to say
|
|
134
|
+
the word and the file deciding the shape.
|
|
135
|
+
|
|
136
|
+
### Fan-out
|
|
137
|
+
|
|
138
|
+
```markdown
|
|
139
|
+
1. [[scout]] — list the competitor URLs, one per line
|
|
140
|
+
2. [[analyst]] — analyse this one site
|
|
141
|
+
each: lines
|
|
142
|
+
max: 10
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The declared shape stays one line in the file; the width comes from the data.
|
|
146
|
+
`each: items` fans out over the array an earlier `output: json` step returned,
|
|
147
|
+
and `each: rows of workspace/storage/leads.csv` over a CSV.
|
|
148
|
+
|
|
149
|
+
### Composition
|
|
150
|
+
|
|
151
|
+
A step may name a flow instead of an agent — `1. [[flow:weekly]] — …` — and its
|
|
152
|
+
steps run in place, keeping their own parallelism. Cycles, and nesting past
|
|
153
|
+
three levels, are errors.
|
|
154
|
+
|
|
155
|
+
## Working as a team
|
|
156
|
+
|
|
157
|
+
Three ways for agents to reach each other, in increasing order of how much the
|
|
158
|
+
model decides:
|
|
159
|
+
|
|
160
|
+
**Steps** — you decide who runs next. The default, and the one to prefer.
|
|
161
|
+
|
|
162
|
+
**Consult** (`agents:`) — a specialist answers one question, inline:
|
|
163
|
+
|
|
164
|
+
```yaml
|
|
165
|
+
agents:
|
|
166
|
+
- [[fact-checker]]
|
|
167
|
+
- [[researcher]]
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Each becomes a `consult_<name>(question)` tool. The colleague's persona answers
|
|
171
|
+
one self-contained question as a **toolless** call, with the spend landing on
|
|
172
|
+
the calling step. Depth is one — consultants cannot consult further. It is
|
|
173
|
+
deliberately weak: a consult is asking a specialist what they think, not handing
|
|
174
|
+
over the task.
|
|
175
|
+
|
|
176
|
+
**Delegate** (`delegate:`) — the model picks, from a list you wrote:
|
|
177
|
+
|
|
178
|
+
```markdown
|
|
179
|
+
2. [[triager]] — decide who should take this
|
|
180
|
+
delegate: enricher, emailer, writer
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The agent ends its reply with `agent: instruction` lines, choosing only from the
|
|
184
|
+
declared set (at most five). The picks run as a fresh group immediately after,
|
|
185
|
+
and both the set and the picks are on the record. Choosing nobody is a normal
|
|
186
|
+
outcome.
|
|
187
|
+
|
|
188
|
+
What all three have in common is the line the format holds: a model chooses
|
|
189
|
+
*what to do within a step*; the **file** decides what happens after it. There is
|
|
190
|
+
no free-form handoff between agents, because that pattern's common failure is a
|
|
191
|
+
loop where every agent re-plans and nobody owns the task.
|
|
192
|
+
|
|
193
|
+
## Gates, failure and cost
|
|
194
|
+
|
|
195
|
+
| option | what it does |
|
|
196
|
+
|---|---|
|
|
197
|
+
| `approve: true` / `ask: <question>` | park until a person releases it; the answer typed at the gate reaches the prompt |
|
|
198
|
+
| `wait: 3d` / `wait: event` | hold for a duration, or until something POSTs the run's event URL |
|
|
199
|
+
| `retry: <n>` | attempts after the first, up to 5 |
|
|
200
|
+
| `on-fail: <agent>` | another agent takes the step over, with the failure as context |
|
|
201
|
+
| `verify: <command>` | a shell command, or `contains:` / `matches:` / `file:` / `judge:` |
|
|
202
|
+
| `timeout: <seconds>` | **the only clock there is** |
|
|
203
|
+
|
|
204
|
+
Two of those deserve emphasis. **Without `timeout:`, a step runs until it
|
|
205
|
+
finishes** — the platform sets no clock of its own anywhere, so every limit that
|
|
206
|
+
exists is one written in a markdown file. And **`verify:` is where anything
|
|
207
|
+
decided by arithmetic goes**: step options are matched as text, deliberately, so
|
|
208
|
+
a threshold belongs in a command that can be tested — `verify: jq -e '.total > 0'`
|
|
209
|
+
— rather than in a comparison in frontmatter.
|
|
210
|
+
|
|
211
|
+
## Picking the model
|
|
212
|
+
|
|
213
|
+
`model:` takes a tier — `fast`, `default`, `max` — rather than a model id, so
|
|
214
|
+
agents do not rot when models are renamed. `effort:` is the orthogonal half:
|
|
215
|
+
which brain, versus how long it thinks. `fast` + `max` is a real pairing — the
|
|
216
|
+
cheap model, told to take its time.
|
|
217
|
+
|
|
218
|
+
Resolution is nearest-wins — the step, then the flow, then the agent — and the
|
|
219
|
+
run trace names which level won, so "why did this run on haiku" is answerable
|
|
220
|
+
from the run rather than by opening three files.
|
|
221
|
+
|
|
222
|
+
```markdown
|
|
223
|
+
---
|
|
224
|
+
name: digest
|
|
225
|
+
model: fast # every step, unless the step says otherwise
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
1. [[scout]] — list the URLs
|
|
229
|
+
2. [[analyst]] — the one hard step
|
|
230
|
+
model: max
|
|
231
|
+
effort: xhigh
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Match the tier to the work, not to the importance of the desk. A step that
|
|
235
|
+
reads a page and pulls out three fields is a `fast` step even when the report
|
|
236
|
+
it feeds is the point of the week; a step that weighs two arguments and picks
|
|
237
|
+
one is not. See [Providers](providers) for pointing a tier at your own
|
|
238
|
+
endpoint, which is how a tier becomes cheaper still.
|
|
239
|
+
|
|
240
|
+
## Choosing between the shapes
|
|
241
|
+
|
|
242
|
+
| you want | use |
|
|
243
|
+
|---|---|
|
|
244
|
+
| a second opinion inside one step | `agents:` consult |
|
|
245
|
+
| the model to pick who is next, from a short list | `delegate:` |
|
|
246
|
+
| you to decide who is next | numbered steps |
|
|
247
|
+
| N of the same work | `each:` |
|
|
248
|
+
| a quality gate | `loop:` + `until:` |
|
|
249
|
+
| reuse across flows | `[[flow:name]]` |
|
|
250
|
+
| a person | `approve:` / `ask:` |
|
|
251
|
+
|
|
252
|
+
`foldrun check` validates all of this offline, before any model is called: a
|
|
253
|
+
step naming an agent that does not exist, a `delegate:` or `on-fail:` that
|
|
254
|
+
names nobody, a tool or skill that resolves to nothing. Run it the way you
|
|
255
|
+
would run a typecheck.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Introduction
|
|
2
|
+
|
|
3
|
+
Agents are just folders. foldrun is the platform that runs them: an agent is
|
|
4
|
+
a folder with an `agent.md` in it; a flow is a numbered
|
|
5
|
+
list of steps; a tool is a file that says what may be called. There is no
|
|
6
|
+
build step and no SDK to import — the files are the program — so the same
|
|
7
|
+
folder runs on your laptop with the CLI or on the hosted platform,
|
|
8
|
+
unchanged.
|
|
9
|
+
|
|
10
|
+
## What it is for
|
|
11
|
+
|
|
12
|
+
Work that a person used to do on a schedule, and that a model can now do with
|
|
13
|
+
supervision: the weekly report, the nightly import, the morning scan of what
|
|
14
|
+
changed, the draft that a human approves before it goes out. Each of those is
|
|
15
|
+
a flow. Each role in it is an agent. The person who used to do the work
|
|
16
|
+
becomes the person who reads the headline and clicks approve.
|
|
17
|
+
|
|
18
|
+
The design bets on three things:
|
|
19
|
+
|
|
20
|
+
- **Files are the right unit.** An agent's prompt, its tools, its knowledge
|
|
21
|
+
and what it has learned are all files you can open, diff, review and put in
|
|
22
|
+
git. Nothing is hidden in a database that only the platform can read.
|
|
23
|
+
- **The file decides, the model works.** A flow says who runs and in what
|
|
24
|
+
order; a model decides only what to do inside its step. There is no
|
|
25
|
+
free-form handoff between agents, because that is where systems loop.
|
|
26
|
+
- **Capability is a grant, not an instruction.** An agent can call a tool
|
|
27
|
+
because its file names it. An agent that cannot write to your website has
|
|
28
|
+
no tool that writes, rather than a paragraph asking it not to.
|
|
29
|
+
|
|
30
|
+
## Two ways to run it
|
|
31
|
+
|
|
32
|
+
| | you need | what runs where |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| **Locally** | `npm install -g foldrun` and a model key | everything on your machine; no account, no server |
|
|
35
|
+
| **Hosted** | an account | ours: schedules, sandboxes, a vault, a team |
|
|
36
|
+
|
|
37
|
+
The same workspace moves between them with `foldrun deploy` or a `git push`.
|
|
38
|
+
Start locally; that is where every workspace should be born. The CLI and
|
|
39
|
+
runtime are open source (Apache-2.0); the platform is not distributed — see
|
|
40
|
+
[Running it yourself](self-hosting).
|
|
41
|
+
|
|
42
|
+
## Where to go
|
|
43
|
+
|
|
44
|
+
- [Getting started](getting-started) — install, make a workspace, run it.
|
|
45
|
+
- [How it works](how-it-works) — the eight nouns and the flow grammar, in one read.
|
|
46
|
+
- [Workspaces](workspaces), [Agents](agents), [Flows](flows), [Tools](tools) — the format, field by field.
|
|
47
|
+
- [Runs](runs), [Budgets and billing](budgets-and-billing), [Security](security) — what happens when it runs.
|