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.