writing agents

the full .agent.md format spec. every field, every default, every gotcha.

file location

any path ending in .agent.md. convention is /agents/<name>.agent.md but not required. you can colocate agents with the files they work on — eg /customers/followup.agent.md — and it works the same.

frontmatter schema

name: string                 # required. unique within project.
description: string          # optional. human summary.
model: string                # required. eg claude-opus, claude-sonnet, gpt-5, llama-3
cwd: string                  # required. working directory path.
tools: string[]              # required. list of enabled tool names.

# optional
schedule: string             # cron expression
triggers:
  - file_change: glob
  - mention: string
  - webhook: name
env:
  KEY: value                 # scoped env vars
timeout_s: number            # default 300
max_tool_calls: number       # default 50
permissions:
  write: glob[]              # restrict writes
  read: glob[]               # restrict reads
runner: string               # 'cpu' | 'gpu' | specific seat name

body

everything under the frontmatter is the system prompt. write it in english. the agent sees your drive in real time, so you can reference paths directly:

you are an expert at turning ugly csvs into clean part files.

when invoked:
1. read /inbox/*.csv
2. for each row, create /parts/<slug>.part.md with typed frontmatter
3. move the csv to /archive/
4. post a summary to /inbox/summary.md

variables in the body

{{args}} — the invoke args {{trigger}} — what fired the agent (manual/mention/cron/webhook) {{date}} — current iso date {{user}} — user handle if manual {{env.KEY}} — from frontmatter env

permissions

by default an agent can read + write anywhere under its cwd. to restrict:

permissions:
  write: [/customers/**, /marketing/outreach/**]
  read: [/**]

globs are relative to cwd unless absolute.

cost control

timeout_s: 180
max_tool_calls: 30

if either is exceeded the run ends with status cutoff. you can see the partial transcript in /runs.

linting

we check your .agent.md on save. if the frontmatter doesnt parse or a tool doesnt exist, you get a red squiggle and the agent wont run. no silent failures fr.

testing

write a sibling <name>.agent.test.md with inputs blocks. click test and the runner cranks through them in a sandbox with network disabled and writes diffed artifacts to /.vibe/test-runs/. no prod side effects.