@foldrun/core 0.2.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/LICENSE +202 -0
- package/README.md +239 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +43 -0
- package/dist/src/agent-tools.d.ts +31 -0
- package/dist/src/agent-tools.js +99 -0
- package/dist/src/agents-md.d.ts +9 -0
- package/dist/src/agents-md.js +83 -0
- package/dist/src/api-tools.d.ts +38 -0
- package/dist/src/api-tools.js +313 -0
- package/dist/src/approvals.d.ts +39 -0
- package/dist/src/approvals.js +103 -0
- package/dist/src/arrange.d.ts +8 -0
- package/dist/src/arrange.js +40 -0
- package/dist/src/catalog.d.ts +108 -0
- package/dist/src/catalog.js +255 -0
- package/dist/src/completions.d.ts +61 -0
- package/dist/src/completions.js +578 -0
- package/dist/src/confine.d.ts +31 -0
- package/dist/src/confine.js +298 -0
- package/dist/src/container.d.ts +30 -0
- package/dist/src/container.js +172 -0
- package/dist/src/context-tools.d.ts +81 -0
- package/dist/src/context-tools.js +347 -0
- package/dist/src/deploy.d.ts +100 -0
- package/dist/src/deploy.js +377 -0
- package/dist/src/egress.d.ts +75 -0
- package/dist/src/egress.js +133 -0
- package/dist/src/evals.d.ts +150 -0
- package/dist/src/evals.js +651 -0
- package/dist/src/flow-lint.d.ts +16 -0
- package/dist/src/flow-lint.js +177 -0
- package/dist/src/git-hook.d.ts +1 -0
- package/dist/src/git-hook.js +70 -0
- package/dist/src/git.d.ts +37 -0
- package/dist/src/git.js +101 -0
- package/dist/src/gitrepo.d.ts +95 -0
- package/dist/src/gitrepo.js +355 -0
- package/dist/src/history.d.ts +82 -0
- package/dist/src/history.js +259 -0
- package/dist/src/kinds.d.ts +95 -0
- package/dist/src/kinds.js +421 -0
- package/dist/src/library.d.ts +94 -0
- package/dist/src/library.js +341 -0
- package/dist/src/linkable.d.ts +20 -0
- package/dist/src/linkable.js +113 -0
- package/dist/src/model-probe.d.ts +21 -0
- package/dist/src/model-probe.js +81 -0
- package/dist/src/notify.d.ts +61 -0
- package/dist/src/notify.js +252 -0
- package/dist/src/oauth-presets.d.ts +13 -0
- package/dist/src/oauth-presets.js +39 -0
- package/dist/src/okf.d.ts +220 -0
- package/dist/src/okf.js +656 -0
- package/dist/src/openapi.d.ts +66 -0
- package/dist/src/openapi.js +342 -0
- package/dist/src/paths.d.ts +33 -0
- package/dist/src/paths.js +78 -0
- package/dist/src/platform.d.ts +32 -0
- package/dist/src/platform.js +48 -0
- package/dist/src/providers.d.ts +47 -0
- package/dist/src/providers.js +114 -0
- package/dist/src/refs.d.ts +20 -0
- package/dist/src/refs.js +78 -0
- package/dist/src/run-container.d.ts +227 -0
- package/dist/src/run-container.js +760 -0
- package/dist/src/runner.d.ts +241 -0
- package/dist/src/runner.js +3215 -0
- package/dist/src/runtime.d.ts +41 -0
- package/dist/src/runtime.js +357 -0
- package/dist/src/script-tools.d.ts +62 -0
- package/dist/src/script-tools.js +296 -0
- package/dist/src/secret-files.d.ts +12 -0
- package/dist/src/secret-files.js +92 -0
- package/dist/src/secrets.d.ts +147 -0
- package/dist/src/secrets.js +626 -0
- package/dist/src/starter.d.ts +21 -0
- package/dist/src/starter.js +399 -0
- package/dist/src/step-exec.d.ts +136 -0
- package/dist/src/step-exec.js +391 -0
- package/dist/src/storage.d.ts +123 -0
- package/dist/src/storage.js +640 -0
- package/dist/src/store.d.ts +1052 -0
- package/dist/src/store.js +2378 -0
- package/dist/src/tar.d.ts +30 -0
- package/dist/src/tar.js +111 -0
- package/dist/src/tool-names.d.ts +39 -0
- package/dist/src/tool-names.js +79 -0
- package/dist/src/tool-programs.d.ts +18 -0
- package/dist/src/tool-programs.js +52 -0
- package/dist/src/tool-test.d.ts +19 -0
- package/dist/src/tool-test.js +335 -0
- package/dist/src/translator.d.ts +159 -0
- package/dist/src/translator.js +986 -0
- package/dist/src/triggers.d.ts +60 -0
- package/dist/src/triggers.js +270 -0
- package/dist/src/webhook.d.ts +47 -0
- package/dist/src/webhook.js +148 -0
- package/index.ts +44 -0
- package/package.json +64 -0
- package/src/agent-tools.ts +138 -0
- package/src/agents-md.ts +81 -0
- package/src/api-tools.ts +389 -0
- package/src/approvals.ts +129 -0
- package/src/arrange.ts +42 -0
- package/src/catalog.ts +321 -0
- package/src/completions.ts +652 -0
- package/src/confine.ts +350 -0
- package/src/container.ts +220 -0
- package/src/context-tools.ts +435 -0
- package/src/deploy.ts +458 -0
- package/src/egress.ts +176 -0
- package/src/evals.ts +812 -0
- package/src/flow-lint.ts +215 -0
- package/src/git-hook.ts +73 -0
- package/src/git.ts +117 -0
- package/src/gitrepo.ts +391 -0
- package/src/history.ts +329 -0
- package/src/kinds.ts +507 -0
- package/src/library.ts +419 -0
- package/src/linkable.ts +123 -0
- package/src/model-probe.ts +112 -0
- package/src/notify.ts +281 -0
- package/src/oauth-presets.ts +54 -0
- package/src/okf.ts +768 -0
- package/src/openapi.ts +383 -0
- package/src/paths.ts +79 -0
- package/src/platform.ts +87 -0
- package/src/providers.ts +147 -0
- package/src/refs.ts +83 -0
- package/src/run-container.ts +883 -0
- package/src/runner.ts +3446 -0
- package/src/runtime.ts +404 -0
- package/src/script-tools.ts +383 -0
- package/src/secret-files.ts +101 -0
- package/src/secrets.ts +799 -0
- package/src/starter.ts +415 -0
- package/src/step-exec.ts +498 -0
- package/src/storage.ts +771 -0
- package/src/store.ts +2985 -0
- package/src/tar.ts +124 -0
- package/src/tool-names.ts +91 -0
- package/src/tool-programs.ts +65 -0
- package/src/tool-test.ts +401 -0
- package/src/translator.ts +1029 -0
- package/src/triggers.ts +287 -0
- package/src/webhook.ts +183 -0
- package/templates/blog-desk/AGENTS.md +13 -0
- package/templates/blog-desk/agents/researcher/agent.md +11 -0
- package/templates/blog-desk/agents/writer/agent.md +8 -0
- package/templates/blog-desk/evals/writer-quality.md +10 -0
- package/templates/blog-desk/flows/publish.md +10 -0
- package/templates/blog-desk/knowledge/house-style.md +9 -0
- package/templates/blog-desk/knowledge/index.md +9 -0
- package/templates/hello/AGENTS.md +18 -0
- package/templates/hello/agents/curator/agent.md +32 -0
- package/templates/hello/agents/notetaker/agent.md +24 -0
- package/templates/hello/evals/house-style.md +16 -0
- package/templates/hello/flows/memory-review.md +7 -0
- package/templates/hello/flows/note.md +7 -0
- package/templates/hello/knowledge/house-style.md +15 -0
- package/templates/hello/knowledge/index.md +9 -0
- package/templates/hello/skills/plain-english/SKILL.md +11 -0
- package/templates/hello/state/publishing.md +7 -0
- package/templates/hello/tools/wordcount/run.py +13 -0
- package/templates/hello/tools/wordcount/tool.md +22 -0
package/src/starter.ts
ADDED
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
// The starter workspace, defined once.
|
|
2
|
+
//
|
|
3
|
+
// Two things used to build one: `foldrun init` had its own copy and the
|
|
4
|
+
// dashboard's "new workspace" button had another. They drifted exactly as you
|
|
5
|
+
// would expect — different flow names, one with evals and knowledge and one
|
|
6
|
+
// without — and when structural documents moved from `type:` to `kind:`, one
|
|
7
|
+
// copy was migrated and the other silently kept writing the old spelling.
|
|
8
|
+
//
|
|
9
|
+
// This is the same failure the consistency tests exist to catch: a list in two
|
|
10
|
+
// places, one updated, nothing erroring. So there is one definition here and
|
|
11
|
+
// both callers read it.
|
|
12
|
+
//
|
|
13
|
+
// Not to be confused with KINDS[kind].template(), which makes *one* document
|
|
14
|
+
// of a kind with a placeholder name — that is what the New button uses inside
|
|
15
|
+
// an existing workspace. This is the set of files a brand-new workspace starts
|
|
16
|
+
// with, and they reference each other on purpose: the flow names the agents,
|
|
17
|
+
// the eval names the writer, so `foldrun check` passes and `foldrun run
|
|
18
|
+
// publish` works before anything has been edited.
|
|
19
|
+
|
|
20
|
+
/** One authored file, relative to the workspace root. */
|
|
21
|
+
export interface StarterFile {
|
|
22
|
+
path: string;
|
|
23
|
+
content: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The account root's own files — one scope up from any workspace.
|
|
28
|
+
*
|
|
29
|
+
* The account AGENTS.md was readable from the day `workspaceFrontmatter` and
|
|
30
|
+
* `sharedInstructions` learned to look for it, and nothing ever wrote one. So
|
|
31
|
+
* the outer half of "nearest-wins" existed only for people who had read the
|
|
32
|
+
* spec closely enough to know the file could exist at all, which is the same
|
|
33
|
+
* failure as prose that reached no model: a feature nobody is told about.
|
|
34
|
+
*
|
|
35
|
+
* Deliberately near-empty. This file's frontmatter governs *every* workspace
|
|
36
|
+
* under it, so the scaffold ships the shape and a commented example rather
|
|
37
|
+
* than a live `provider:` — a starter that silently routed every future
|
|
38
|
+
* workspace somewhere would be worse than no starter.
|
|
39
|
+
*/
|
|
40
|
+
export function accountFiles(account: string): StarterFile[] {
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
path: "AGENTS.md",
|
|
44
|
+
content: `---
|
|
45
|
+
foldrun_version: "0.1"
|
|
46
|
+
# Config here applies to every workspace under this account, and a workspace
|
|
47
|
+
# that declares the same key replaces it *whole* — base_url and token never
|
|
48
|
+
# merge across scopes, so a provider block belongs entirely at one level.
|
|
49
|
+
#
|
|
50
|
+
# provider:
|
|
51
|
+
# base_url: https://openrouter.ai/api
|
|
52
|
+
# token: \${OPENROUTER_API_KEY}
|
|
53
|
+
# models: # what this gateway calls each tier
|
|
54
|
+
# fast: google/gemini-2.5-flash
|
|
55
|
+
# max: anthropic/claude-opus-4.1
|
|
56
|
+
# headers: # anything else the gateway wants
|
|
57
|
+
# X-Title: foldrun
|
|
58
|
+
#
|
|
59
|
+
# The token is sent as a bearer credential. A gateway that wants it as a key
|
|
60
|
+
# header asks for that by name: headers: { x-api-key: \${THE_SECRET} }.
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
# ${account}
|
|
64
|
+
|
|
65
|
+
Context every agent in every workspace here shares.
|
|
66
|
+
|
|
67
|
+
Unlike the frontmatter above, this prose **accumulates**: a workspace's
|
|
68
|
+
AGENTS.md is added to it, not swapped for it, so a rule written here cannot be
|
|
69
|
+
dropped further down.
|
|
70
|
+
`,
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function starterFiles(workspace: string): StarterFile[] {
|
|
76
|
+
return [
|
|
77
|
+
{
|
|
78
|
+
// AGENTS.md, not project.md — the file was renamed to the Linux
|
|
79
|
+
// Foundation standard and this scaffold was missed once already, so
|
|
80
|
+
// every workspace made from the dashboard started with a file nothing
|
|
81
|
+
// reads.
|
|
82
|
+
path: "AGENTS.md",
|
|
83
|
+
content: `---
|
|
84
|
+
name: ${workspace}
|
|
85
|
+
description: A starter workspace — edit the agents, then run the flow.
|
|
86
|
+
foldrun_version: "0.1"
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
# ${workspace}
|
|
90
|
+
|
|
91
|
+
Context every agent here shares. Prices, rules, anything they should all know.
|
|
92
|
+
`,
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
{
|
|
96
|
+
// A workspace is meant to be a git repository — that is the whole pitch,
|
|
97
|
+
// that you can diff and review what an agent is. So it has to arrive
|
|
98
|
+
// knowing which of its own files must never be committed. The decisive
|
|
99
|
+
// one is `.foldrun/.secret-key`: the CLI writes the key that decrypts
|
|
100
|
+
// every secret *inside the workspace*, and without this file the first
|
|
101
|
+
// `git add -A` after setting a secret commits it.
|
|
102
|
+
path: ".gitignore",
|
|
103
|
+
content: `# The key that decrypts every secret in this workspace, plus the
|
|
104
|
+
# local run store. Never commit these.
|
|
105
|
+
.foldrun/
|
|
106
|
+
|
|
107
|
+
# Written by runs, not by you.
|
|
108
|
+
runs/
|
|
109
|
+
outputs/
|
|
110
|
+
|
|
111
|
+
.env
|
|
112
|
+
.env.local
|
|
113
|
+
.DS_Store
|
|
114
|
+
`,
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
{
|
|
118
|
+
path: "agents/researcher/agent.md",
|
|
119
|
+
content: `---
|
|
120
|
+
name: researcher
|
|
121
|
+
description: Finds one thing worth writing about, and says why.
|
|
122
|
+
model: fast
|
|
123
|
+
effort: high
|
|
124
|
+
tools:
|
|
125
|
+
- web
|
|
126
|
+
- read
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
Pick exactly one topic, in a short paragraph, and say who it helps and why now.
|
|
130
|
+
Do not write the article.
|
|
131
|
+
`,
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
{
|
|
135
|
+
path: "agents/writer/agent.md",
|
|
136
|
+
content: `---
|
|
137
|
+
name: writer
|
|
138
|
+
description: Turns a brief into a short draft.
|
|
139
|
+
tools:
|
|
140
|
+
- files
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
Write a short draft from the brief you were given. Save it to outputs/draft.md.
|
|
144
|
+
`,
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
{
|
|
148
|
+
path: "flows/publish.md",
|
|
149
|
+
content: `---
|
|
150
|
+
name: publish
|
|
151
|
+
trigger: manual
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
Read the numbers, not the order of the lines.
|
|
155
|
+
Same number = at the same time. Different number = one after the other.
|
|
156
|
+
|
|
157
|
+
1. [[researcher]] — find one topic worth writing about
|
|
158
|
+
2. [[writer]] — draft it
|
|
159
|
+
`,
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
{
|
|
163
|
+
// knowledge/ is an OKF bundle, so this one declares itself in `type:`.
|
|
164
|
+
path: "knowledge/house-style.md",
|
|
165
|
+
content: `---
|
|
166
|
+
type: Reference
|
|
167
|
+
title: How we write
|
|
168
|
+
description: How we write. Agents read this; they never rewrite it.
|
|
169
|
+
status: stable
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
- Short sentences. One idea each.
|
|
173
|
+
- Say the number, not "significant growth".
|
|
174
|
+
`,
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
{
|
|
178
|
+
// The other half of OKF, and the half the starter never showed. Same
|
|
179
|
+
// format as knowledge/, different write permission: an agent may add
|
|
180
|
+
// here, and when it does the runtime stamps `generated:` so a fact it
|
|
181
|
+
// worked out never looks like one you gave it.
|
|
182
|
+
path: "memory/what-worked.md",
|
|
183
|
+
content: `---
|
|
184
|
+
type: Fact
|
|
185
|
+
title: What worked last time
|
|
186
|
+
description: Something learned from a run. Agents add files here themselves.
|
|
187
|
+
status: stable
|
|
188
|
+
# generated: is stamped automatically when an agent writes a memory.
|
|
189
|
+
# Add verified: with a \`human:\` actor once you have checked one yourself —
|
|
190
|
+
# that is what moves it from unverified to human-reviewed in the index.
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
Short drafts got edited less than long ones. Prefer four paragraphs to eight.
|
|
194
|
+
`,
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
{
|
|
198
|
+
// For the CODING TOOL the author is using, not for the platform — this is
|
|
199
|
+
// the one file here that foldrun itself never reads. Claude Code and its
|
|
200
|
+
// peers look for AGENTS.md/CLAUDE.md at the root of whatever they open,
|
|
201
|
+
// and without one they infer conventions from the tree, which for a
|
|
202
|
+
// workspace of loosely-structured markdown means guessing frontmatter
|
|
203
|
+
// fields that do not exist and putting agents in the wrong place.
|
|
204
|
+
//
|
|
205
|
+
// The platform already imports .claude/agents/*.md as agents, so a
|
|
206
|
+
// subagent authored in Claude Code deploys as a foldrun agent with no
|
|
207
|
+
// conversion. That path is much more useful when the tool knows it
|
|
208
|
+
// exists, which is most of what this file is for.
|
|
209
|
+
path: "CLAUDE.md",
|
|
210
|
+
content: `# Working on this foldrun workspace
|
|
211
|
+
|
|
212
|
+
This is a foldrun workspace: agents, flows and knowledge as markdown. There is
|
|
213
|
+
no build — the files ARE the program — so the loop is edit, check, run, deploy.
|
|
214
|
+
|
|
215
|
+
## The loop
|
|
216
|
+
|
|
217
|
+
\`\`\`sh
|
|
218
|
+
foldrun check # validate everything, offline, no model calls
|
|
219
|
+
foldrun run <flow> # run it locally against real models
|
|
220
|
+
foldrun eval # run the evals
|
|
221
|
+
foldrun deploy --url <server> --token $FOLDRUN_TOKEN
|
|
222
|
+
\`\`\`
|
|
223
|
+
|
|
224
|
+
\`check\` is cheap and catches a broken flow before a schedule fires it at 3am.
|
|
225
|
+
Run it after edits, the way you would run a typecheck.
|
|
226
|
+
|
|
227
|
+
## Where things go
|
|
228
|
+
|
|
229
|
+
| Path | What |
|
|
230
|
+
|---|---|
|
|
231
|
+
| \`AGENTS.md\` | shared context every agent in this workspace sees |
|
|
232
|
+
| \`agents/<name>/agent.md\` | one role: its persona, model, tools |
|
|
233
|
+
| \`flows/<name>.md\` | steps, in order, naming the agents that run them |
|
|
234
|
+
| \`knowledge/\` | reference material agents read |
|
|
235
|
+
| \`memory/\` | what past runs learned — agents write here themselves |
|
|
236
|
+
| \`evals/\` | tests for agents, same idea as unit tests |
|
|
237
|
+
| \`skills/\` | a procedure an agent can follow, named in \`skills:\` |
|
|
238
|
+
| \`tools/\` | a folder tool: its definition and its code together |
|
|
239
|
+
| \`scripts/\` | code the agents call, referenced by \`scripts:\` |
|
|
240
|
+
| \`state/\` | what runs accumulate. Yours to read, never deployed over |
|
|
241
|
+
| \`.claude/agents/<name>.md\` | a Claude Code subagent — deploys AS an agent |
|
|
242
|
+
|
|
243
|
+
\`knowledge/\` is what you tell the agents; \`memory/\` is what they worked out.
|
|
244
|
+
Regenerated every run means a file; accumulated across runs means \`state/\`.
|
|
245
|
+
|
|
246
|
+
That last row is worth knowing: a subagent you write in Claude Code is imported
|
|
247
|
+
as \`agents/<name>/agent.md\` at deploy, no conversion. Write it either way.
|
|
248
|
+
|
|
249
|
+
## What a deploy does NOT touch
|
|
250
|
+
|
|
251
|
+
\`runs/\`, \`state/\`, \`secrets.json\`, and any memory an agent wrote that your
|
|
252
|
+
push does not mention. Those belong to the platform, not to git — a deploy that
|
|
253
|
+
reverted what an agent learned would make every run a little dumber.
|
|
254
|
+
|
|
255
|
+
Secrets never go in these files. \`foldrun secrets\` puts them in the vault, and
|
|
256
|
+
agents reference them by name.
|
|
257
|
+
|
|
258
|
+
## Talking to a deployed workspace
|
|
259
|
+
|
|
260
|
+
The CLI is local except for \`deploy\`. To inspect or drive a workspace running
|
|
261
|
+
on a server, use the HTTP API — every route takes the same API key
|
|
262
|
+
(\`Authorization: Bearer $FOLDRUN_TOKEN\`, from Settings → API keys) or a browser
|
|
263
|
+
session, and refuses without one.
|
|
264
|
+
|
|
265
|
+
\`\`\`sh
|
|
266
|
+
export FOLDRUN_TOKEN=... FOLDRUN_URL=https://your-server WS=my-workspace
|
|
267
|
+
api() { p=$1; shift; curl -sS -H "authorization: Bearer $FOLDRUN_TOKEN" "$FOLDRUN_URL/api/$p" "$@"; }
|
|
268
|
+
|
|
269
|
+
api workspaces/$WS/runs # recent runs, newest first
|
|
270
|
+
api workspaces/$WS/runs/<id> # the full trail of one
|
|
271
|
+
api workspaces/$WS/runs/<id>/stream # follow a live one (SSE)
|
|
272
|
+
api workspaces/$WS/flows/<flow>/run -X POST # start one
|
|
273
|
+
\`\`\`
|
|
274
|
+
|
|
275
|
+
All of it, \`/api/workspaces/<workspace>\` unless noted:
|
|
276
|
+
|
|
277
|
+
| Route | Methods | For |
|
|
278
|
+
|---|---|---|
|
|
279
|
+
| \`/\` | GET DELETE PATCH | the workspace itself |
|
|
280
|
+
| \`/deploy\` | POST | what \`foldrun deploy\` calls |
|
|
281
|
+
| \`/source\` | GET PUT PATCH DELETE | read and write single files |
|
|
282
|
+
| \`/runs\` | GET | list runs |
|
|
283
|
+
| \`/runs/<id>\` | GET DELETE | one run, every step |
|
|
284
|
+
| \`/runs/<id>/stream\` | GET | live events, server-sent |
|
|
285
|
+
| \`/runs/<id>/stop\` | POST | kill it — destroys the sandbox too |
|
|
286
|
+
| \`/runs/<id>/rerun\` | POST | again, or from a chosen step |
|
|
287
|
+
| \`/runs/<id>/approve\` | POST | release a run waiting on a human |
|
|
288
|
+
| \`/flows\` · \`/flows/<f>\` | GET POST · POST DELETE PATCH | list, create, edit |
|
|
289
|
+
| \`/flows/<f>/run\` | POST | start a flow |
|
|
290
|
+
| \`/agents\` · \`/agents/<a>/run\` | GET POST · POST | list agents, run one |
|
|
291
|
+
| \`/evals\` · \`/evals/<e>/run\` | GET POST · POST | list evals, run one |
|
|
292
|
+
| \`/tools/<t>/test\` | POST | exercise one tool alone |
|
|
293
|
+
| \`/storage\` · \`/storage/download\` · \`/storage/upload-url\` | GET POST PUT DELETE · GET · POST | workspace files |
|
|
294
|
+
| \`/assets\` | POST | upload an asset |
|
|
295
|
+
| \`/hooks/<f>/rotate\` | POST | new webhook token for a flow |
|
|
296
|
+
| \`/vocabulary\` | GET | what this workspace's documents may say |
|
|
297
|
+
|
|
298
|
+
Account-level, outside \`/workspaces\`: \`/api/secrets\`, \`/api/keys\`, \`/api/schedule\`,
|
|
299
|
+
\`/api/approvals\`, \`/api/usage\`, \`/api/library/<kind>\`, \`/api/team\`, \`/api/billing\`,
|
|
300
|
+
\`/api/healthz\` (open) and \`/api/metrics\` (Prometheus).
|
|
301
|
+
|
|
302
|
+
Debugging a failed run is usually: \`runs\` to find it, \`runs/<id>\` to read which
|
|
303
|
+
step failed and what it cost, fix the markdown, \`deploy\`, then \`rerun\`.
|
|
304
|
+
|
|
305
|
+
Every route, with request and response shapes, is in \`docs/api.md\` in the
|
|
306
|
+
foldrun repository — including secrets, keys, billing, OAuth, webhooks and the
|
|
307
|
+
git push endpoint.
|
|
308
|
+
|
|
309
|
+
## Writing a flow
|
|
310
|
+
|
|
311
|
+
A numbered list of steps. The number is the GROUP: same number means those
|
|
312
|
+
steps run in parallel, and the flow waits for all of them before the next.
|
|
313
|
+
|
|
314
|
+
\`\`\`markdown
|
|
315
|
+
---
|
|
316
|
+
trigger: manual # manual | schedule | webhook
|
|
317
|
+
schedule: "0 9 * * 1" # cron, when trigger: schedule
|
|
318
|
+
timezone: Australia/Sydney
|
|
319
|
+
model: default # a default for every step here
|
|
320
|
+
effort: low
|
|
321
|
+
overlap: skip # skip | queue — what a second run does while one is live
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
1. [[researcher]] — Find three sources on {{topic}}.
|
|
325
|
+
2. [[writer]] — Draft from what the researcher found.
|
|
326
|
+
model: max
|
|
327
|
+
verify: the draft cites every source
|
|
328
|
+
3?. [[editor]] — Tighten it.
|
|
329
|
+
4!. [[publisher]] — Publish it.
|
|
330
|
+
\`\`\`
|
|
331
|
+
|
|
332
|
+
\`3?.\` is optional — it may be skipped. \`4!.\` needs a human to approve before it
|
|
333
|
+
runs. \`[[flow:other-flow]]\` in place of an agent runs another flow as a step.
|
|
334
|
+
|
|
335
|
+
Indented under a step, any of:
|
|
336
|
+
|
|
337
|
+
| | |
|
|
338
|
+
|---|---|
|
|
339
|
+
| \`approve: true\` | stop for a human (\`!\` is shorthand for this) |
|
|
340
|
+
| \`when: <condition>\` | run only if it holds |
|
|
341
|
+
| \`case: <value>\` / \`else: true\` | branch on the previous step's result |
|
|
342
|
+
| \`retry: 2\` | re-run on failure, up to 5 |
|
|
343
|
+
| \`timeout: 900\` | seconds before the step is cut off |
|
|
344
|
+
| \`verify: <claim>\` | the step fails unless this is true of its output |
|
|
345
|
+
| \`model:\` / \`effort:\` | override the flow's default for this step |
|
|
346
|
+
| \`loop: 3\` / \`until: <condition>\` | repeat until it holds, at most 5 |
|
|
347
|
+
| \`each: lines\` | run once per line of the previous result |
|
|
348
|
+
| \`each: rows of <path>\` | run once per CSV row |
|
|
349
|
+
| \`max: 10\` | cap how many iterations \`each:\` produces |
|
|
350
|
+
| \`on-fail: [[agent]]\` | who handles it when this step fails |
|
|
351
|
+
| \`wait: 30m\` | pause before running — \`90s\`, \`30m\`, \`4h\`, \`3d\` |
|
|
352
|
+
| \`wait: event\` | hold until something POSTs the run's event URL; the body reaches the step |
|
|
353
|
+
| \`ask: <question>\` | ask a human, use the answer |
|
|
354
|
+
| \`preview: draft/*.mdx\` | what the approval box shows — paths under \`storage/\`, globs allowed |
|
|
355
|
+
| \`delegate: [[a]], [[b]]\` | hand the step to whichever fits, up to 5 |
|
|
356
|
+
| \`output: json\` | the reply ends with one JSON value; the next step gets it as data, \`each: items\` fans out over it |
|
|
357
|
+
| \`each: items\` | run once per element of the previous step's JSON array |
|
|
358
|
+
|
|
359
|
+
## Writing an agent
|
|
360
|
+
|
|
361
|
+
Frontmatter then prose. The prose IS the system prompt, so write it to be read
|
|
362
|
+
by a model: what this role is for, what it must not do, what good looks like.
|
|
363
|
+
|
|
364
|
+
\`\`\`markdown
|
|
365
|
+
---
|
|
366
|
+
name: researcher
|
|
367
|
+
description: Finds and summarises sources.
|
|
368
|
+
model: default # fast | default | max
|
|
369
|
+
effort: low # how hard to think about it
|
|
370
|
+
size: large # small | large | heavy — the sandbox it rents
|
|
371
|
+
tools: [WebSearch, Read, my-folder-tool] # built-ins and your own tools/, one list
|
|
372
|
+
disallowedTools: [Bash] # subtract from what it would otherwise have
|
|
373
|
+
skills: [house-style] # from skills/
|
|
374
|
+
scripts: [summarise.py] # from scripts/, each becomes a callable tool
|
|
375
|
+
apis: [{ name: crm }] # an HTTP API, as a tool
|
|
376
|
+
mcpServers: {} # an MCP server, as a tool
|
|
377
|
+
agents: [writer] # colleagues this one may consult
|
|
378
|
+
secrets: [CRM_TOKEN] # from the vault — never written in these files
|
|
379
|
+
provider: {} # BYOK: your own model credential
|
|
380
|
+
permissionMode: plan # plan first, act once approved
|
|
381
|
+
runtime: # only if scripts need packages
|
|
382
|
+
packages: [requests]
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
You research a topic and report what you found...
|
|
386
|
+
\`\`\`
|
|
387
|
+
|
|
388
|
+
Only \`name\` and the prose are required. Every other field widens or narrows
|
|
389
|
+
what the agent can reach, and the default is narrow.
|
|
390
|
+
|
|
391
|
+
\`runtime:\` installs pip/npm packages in the sandbox each agent runs in. Pin
|
|
392
|
+
versions the normal way (\`pandas>=2\`, \`lodash@^4\`). Python and Node are
|
|
393
|
+
supported; anything else should ship as a committed binary.
|
|
394
|
+
|
|
395
|
+
Link documents to each other with \`[[wikilinks]]\` — the name, not the path.
|
|
396
|
+
`,
|
|
397
|
+
},
|
|
398
|
+
|
|
399
|
+
{
|
|
400
|
+
path: "evals/writer-quality.md",
|
|
401
|
+
content: `---
|
|
402
|
+
name: writer-quality
|
|
403
|
+
agent: writer
|
|
404
|
+
model: fast
|
|
405
|
+
effort: low
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## writes something
|
|
409
|
+
task: Write two sentences about rain.
|
|
410
|
+
expect:
|
|
411
|
+
- judge: it is two sentences and mentions rain
|
|
412
|
+
`,
|
|
413
|
+
},
|
|
414
|
+
];
|
|
415
|
+
}
|