foldrun.docs
Browse docs

Docs/The format

The agent file

agents/<name>/agent.md is the only required file an agent has. Frontmatter for the machine, body for the model — and the body is the prompt, so write it as instructions to a colleague rather than as documentation about one.

---
name: competitor-watcher
description: Watches competitor sites and drafts a weekly digest.
model: default
effort: high
tools:
  - web
  - files
  - [[price-tracker]]
secrets: [SLACK_WEBHOOK_TOKEN]
---

You watch our competitors and produce a weekly digest.

Check each site listed in [[competitors]]. Note pricing changes, new features
and new posts. Write the digest to outputs/digest.md.

Identity

field
name kebab-case, unique in the account. The agent’s identity — the folder must match
description what it does and when to use it. Other agents read this when consulting; people read it in the dashboard

Only name and the body are required. Every other field widens or narrows what the agent can reach, and the default is narrow.

Which model, and how hard it thinks

field values
model fast | default | max, an alias (opus), or a full id a tier, so agents don’t rot when models are renamed. Synonyms land on their tier: small/cheap → fast, large/best → max
effort low | medium | high | xhigh | max how long it thinks before answering. Unset leaves the model’s own default

The two are orthogonal — the model is which brain, effort is how long it thinks — and fast + max is a real pairing: the cheap model, told to take its time. The same word means different things on each key: model: max is the most capable model, effort: max is think-hardest.

Match the tier to the work, not to the importance of the desk. A step that orders findings other steps produced is a fast step even when its output is the point of the week; a step that weighs two arguments and picks one is not.

What it may do

field
tools the one grant list — built-in groups, exact SDK names, and your own tools
disallowedTools subtract from what it would otherwise have
skills an allowlist. Absent inherits every skill in scope; [] withholds all of them
agents colleagues it may consult mid-run
scripts programs in scripts/, each becoming a callable tool
apis an HTTP API declared inline, as one tool
mcpServers an MCP server declared inline
secrets vault entries its tools may use — names only, never values
permissionMode plan makes the run read-only, whatever else was granted

The built-in groups are one word each, so you can hold them in your head:

group
read Read, Glob, Grep — inspect but never modify
files Read, Write, Edit, Glob, Grep
bash Bash
web WebSearch (server-side, billed per call) + WebFetch
fetch WebFetch only — the local half
search search_files(query) over knowledge, memory, state and storage at every scope
history recall_runs() and read_run(id) — the workspace’s last thirty finished runs

Anything in tools: that no built-in claims is one of your own tools, resolved against the workspace’s tools/ and then the account library. A [[link]] makes that explicit and is the only way to grant a tool whose name a built-in would otherwise shadow:

tools:
  - read              # the built-in group
  - [[search]]        # your tools/search.md, not the platform's search group

{bash: ask} is accepted for per-call approval in Claude Code; platform runs disable ask-mode and log that they did.

Consulting colleagues

agents:
  - [[fact-checker]]

Each name becomes a consult_<name>(question) tool. The colleague’s persona answers one self-contained question as a toolless call, inline, with the spend landing on the consulting step. Depth is one — consultants cannot consult further. It is deliberately weak: a consult asks a specialist what they think; it does not hand over the task.

Where it runs

field
size small | large (default) | heavy — the sandbox reservation
runtime language runtimes and packages the agent’s own scripts need

size is a price, not just a limit. Memory is a hard ceiling because it is not compressible: a step over it is killed, which on a single-node host protects every other tenant. CPU is not capped — a step bursts to whatever is free and bills at its class rate. Reference figures: 1Gi, 2Gi, 8Gi. Pick small for an agent that mostly waits on an API, heavy for one that renders a browser or holds real data.

runtime:
  python: "3.12"            # optional pin
  packages: [pandas]        # pip
  node: true
  npm: [cheerio]

An agent’s own runtime and the runtimes of the tools it grants merge into one environment per step, so a tool carries its own dependencies and the agent does not repeat them.

Its own model credential

provider:
  name: groq
  token: ${GROQ_API_KEY}
  models: { fast: llama-3.3-70b-versatile }

A name resolves to the endpoint, its wire format and where the key goes; base_url:, format: (anthropic | openai) and auth: (bearer | x-api-key) spell the same thing out for an endpoint no preset covers. params: passes anything else the provider accepts — temperature, seed, response_format — merged into the request verbatim, with a null value removing a field rather than setting it. See Providers.

Running on a clock

schedule (5-field cron, or @hourly/@daily/@weekly/@monthly) with an optional IANA timezone runs the agent on its own. Absent, it runs on demand — the dashboard, foldrun run, or an API call. For anything involving more than one agent, put the schedule on a flow instead.

Everything beside the file

agents/reporter/
├── agent.md          # required
├── skills/           # one capability per folder
├── knowledge/        # given to it; it may read, never write
├── memory/           # what it learned; it writes here
└── scripts/          # code it can call as a tool

memory/ writes are the only writes an agent may make outside outputs/ without an explicit files grant. knowledge/ is denied outright — through the file tools and through bash.

Where files live, from the agent’s point of view

An agent’s working directory is its own folder, and every path is relative to it. Two spellings reach the workspace root and both are fine:

place relative with the prefix
a deliverable for a person ../../storage/report.md workspace/storage/report.md
what the next run needs ../../state/history.md workspace/state/history.md
this step’s scratch outputs/draft.md
the account library (read-only) account/knowledge/prices.md

There is no /tmp for an agent, and no absolute path is inside its workspace. A directory a tool made outside the workspace — a repository it cloned, say — is reached only through that tool’s own read or find action. A path outside the workspace is refused with a message naming the path the agent probably meant; the run page and the agent’s Activity page count those refusals per step, because each one is a wasted turn and a prompt that names the exact path brings the count to zero.

Handing work to a later step

A step is handed the replies of every earlier group. When the reply is a report a person should also read, or a list a later step must get exactly, write it to workspace/storage/ as well — a tool that takes an out= path and tees its own output there is the reliable way, because a model asked to copy a long report by hand shortens it. Reply with one line saying what you concluded; the file is the record.

AGENTS.md — context above the agent

Two scopes, both optional, both inherited: <account>/AGENTS.md for everyone, <workspace>/AGENTS.md for one workspace. Frontmatter there sets defaults — provider:, runtime:, timezone:, notify:, budget: (a monthly cap in USD), foldrun_version: — and the body is context every agent works under.

Nearest wins, but a key replaces the whole value rather than merging into it: an agent’s notify: replaces the account’s, it does not add to it.

Checking it

foldrun check validates all of this offline, before any model is called — a tool, skill or colleague that names nothing, a step that names a missing agent, a broken script path. Run it the way you would run a typecheck.