persona.md schema
A persona is a markdown file at .agents/<slug>/persona.md. The frontmatter (between the two --- lines) is structured. The body is the agent's system prompt.
For the conceptual story see Persona. This page is the field-by-field reference.
Minimal valid persona
---
name: Inbox Triager
role: Email triage
type: specialist
---
You read /inbox/ every weekday at 9am, tag urgency, write to /briefings/today.md.
Frontmatter fields
Identity
| Field | Type | Required | Default | What it does |
|---|
name | string | yes | — | Display name. Shown in mentions, sidebar, org chart. |
emoji | string | no | "🤖" | Single emoji or short string. The agent's avatar in compact lists. |
role | string | yes | — | One-line subtitle. ≤3 words is the convention. |
type | "lead" | "specialist" | yes | — | Leads can dispatch. Specialists do focused work. |
Model & dispatch
| Field | Type | Required | Default | What it does |
|---|
model | string | no | inherits | Provider+model. Examples: claude-opus-4-7, gpt-4.1, gemini-2.5-pro, ollama/llama-3.3-70b. |
effort | "low" | "medium" | "high" | no | "medium" | Default reasoning effort for this agent. |
canDispatch | boolean | no | true for leads, false for specialists | Allow LAUNCH_TASK / SCHEDULE_JOB proposals. |
tools | string[] | no | inherits | Allow-list of tool names. Empty = inherit cabinet defaults. |
visibility | "folder" | "cabinet" | "all" | no | "cabinet" | How far the agent can read. |
Heartbeats
| Field | Type | Required | Default | What it does |
|---|
heartbeats | array | no | [] | Recurring check-ins. See subfields below. |
heartbeats[].cron | cron string | yes | — | Standard 5-field cron expression. |
heartbeats[].label | string | no | derived | Shown in the schedule UI. |
heartbeats[].prompt | string | yes | — | Prompt the agent receives when this beat fires. |
heartbeats[].model | string | no | persona's model | Override per heartbeat. |
heartbeats[].effort | string | no | persona's effort | Override per heartbeat. |
heartbeats[].enabled | boolean | no | true | Disable without removing. |
Memory & skills
| Field | Type | Required | Default | What it does |
|---|
memory | string | object | no | "memory.md" | Path to the agent's memory file, relative to the persona folder. |
memory.maxLines | integer | no | 2000 | Soft cap before Cabinet suggests a memory compaction. |
skills | string[] | no | [] | Skill slugs to attach by default. See Skills. |
Budget
| Field | Type | Required | Default | What it does |
|---|
budget.daily.maxCostUsd | number | no | inherits | Hard cap per agent per day. |
budget.perRun.maxCostUsd | number | no | inherits | Hard cap per individual run. |
budget.perRun.maxTokens | integer | no | inherits | Token cap per run. |
Display
| Field | Type | Required | Default | What it does |
|---|
color | string | no | derived | Hex or token name. Used for sidebar dot and chat bubbles. |
order | integer | no | alpha | Lower numbers sort first in lists. |
Body — the system prompt
Everything after the closing --- is the system prompt the agent gets at the start of every run. Treat it like an onboarding doc:
- Who they are — title, scope, personality if any.
- What they own — folders, files, recurring outputs.
- What they should never do — forbidden tools, forbidden folders, escalation rules.
- How they hand off — when to dispatch, when to write, when to stay quiet.
Use markdown freely. The whole body is sent verbatim. Shorter is usually better.
Example: a complete lead
---
name: GTM Lead
emoji: "🎯"
role: Launch strategy
type: lead
model: claude-opus-4-7
effort: high
canDispatch: true
visibility: cabinet
heartbeats:
- cron: "0 9 * * 1"
label: "Monday standup"
prompt: "Open /marketing/launches/. Report what changed since Friday."
- cron: "0 17 * * 5"
label: "Friday wrap"
model: claude-sonnet-4-6
prompt: "Draft Monday's launch checklist."
skills: [competitor-brief, launch-checklist]
budget:
daily:
maxCostUsd: 10
---
You are the GTM Lead.
## Workspace
You always work in /marketing/. Outputs land in /marketing/launches/<launch-slug>/.
## What you own
- Positioning, channels, offers, launch risk register.
- Weekly launch room state.
## How you delegate
- Research gaps → LAUNCH_TASK to Research Lead with the question and the deadline.
- Draft polish → LAUNCH_TASK to Launch Editor with the draft path.
- Recurring posts → SCHEDULE_JOB to LinkedIn Operator (weekly, Friday 5pm).
## Tone
Direct, concrete, ≤3 sentences per recommendation.
Validation
Bad fields fail at boot with a precise error and exit code 6:
Error: .agents/gtm-lead/persona.md
heartbeats[1].cron: invalid cron expression "every monday"
Use a 5-field cron string. Try crontab.guru.
Read on