agents are markdown
Browse docs

Docs/The format

Tools

A tool is one markdown file describing something an agent may call. One noun for capability: transport: says how it connects, and an agent grants it by name in tools:.

tools/email.md             flat — a definition and nothing else
tools/bounce-verify/       folder — tool.md plus the code it runs
  ├── tool.md
  └── run.py

Nothing is callable until an agent names it. That is the whole security model: reading one agent.md tells you its blast radius.

HTTP — an API as a tool

---
transport: http
name: google-ads
description: The Google Ads API. GET /customers/… to read; POST to mutate.
base: https://googleads.googleapis.com/v18
methods: [GET, POST]
headers:
  Authorization: Bearer ${GOOGLE_ADS_TOKEN}
---
field
base the URL every call is relative to
methods the verb allowlist — a tool that declares none is read-only
headers ${SECRET} placeholders, resolved host-side at call time
openapi a URL or file; turns one generic tool into typed ones, one per operation

The model never sees a credential — the host substitutes it as the request goes out. The method allowlist protects against the agent; the key’s own scopes protect against everyone else, so pair a read-only tool with a read-only key.

Script — code as a tool

---
transport: script
name: sql
run: run.py
description: >
  Run SQL over CSV and JSON files in the working directory. Use whenever the
  answer is a number: totals, averages, joins, de-duplication.
args:
  query: The SQL — one SELECT or WITH statement
  files: Comma-separated .csv / .json paths, one table each
timeout: 120
runtime:
  packages: [pandas]
---
field
run the program beside this file. Omit it and a fenced code block in the body is the program (the single-file form)
args each argument and what it means — this is what the model reads
timeout seconds; without one the program runs until it finishes
runtime interpreters and packages, merged into the step’s environment

args descriptions are the tool’s interface. Write them for someone who has never seen the program, and say when to use the tool in description — that sentence is what decides whether it gets called at all.

MCP — someone else’s tools

---
transport: mcp
name: linear
url: https://mcp.linear.app/sse
headers:
  Authorization: Bearer ${LINEAR_TOKEN}
---

Both transports the SDK supports: a local process (command:, with args: and env:) or a remote endpoint (url:, with headers:). Every tool the server exposes reaches the agent that grants it. mcpServers: in an agent’s own frontmatter is the inline spelling of the same thing.

The library — define it once

<account>/library/
├── tools/<name>.md
├── skills/<name>/SKILL.md
├── knowledge/ · memory/ · scripts/

Resolution is nearest wins: an agent’s own beats its project’s, which beats the account library. So a shared integration is defined once for the whole account and rotating its credential is a single edit — and a workspace can still shadow it by defining the same name locally.

The Library page lists, for every shared file, which agents granted it and where a nearer copy overrides it. That list is the blast radius of changing it.

Skills — procedure, not capability

A skill is a folder with a SKILL.md, in the open Agent Skills format:

---
name: pacing-check
description: Check whether ad spend is pacing to budget. Use when asked if spend is on track.
---

Run `scripts/pace.py --spent <amount> --budget <amount>` from this skill's
folder, then report the verdict in one sentence.

Only names and descriptions sit in context; the agent reads the full file when a task matches. So an agent can carry many skills for a few tokens each — which is the reason to move a procedure out of agent.md in the first place.

Skills are discovered in the agent’s own skills/, the workspace’s, the account library, and the cross-client .agents/skills/ convention that other tools read and write. A skill written here drops into them, and one they install is visible here.

A tool is what an agent may call; a skill is how to do something well. The test for moving text out of an agent body: is it procedure (not role), does it apply to some runs rather than all, and does more than one agent need it?

Secrets

Names in secrets:, values in the vault. A secret may also be an OAuth2 credential — the vault stores the refresh recipe (token_url, client_id, client_secret, refresh_token) and the host exchanges it for a live access token immediately before every use, cached until near expiry.

Resolution is nearest-wins across the workspace and account vaults, and the run log says which store each one came from — a workspace quietly falling back to an account credential is the kind of thing you want to see rather than infer.

Testing one

The Tool Test button calls a tool with arguments you type, from where a run would call it, and shows the raw result. That is the difference between “the tool is broken” and “the agent used it wrong”, and it costs no model call.