<!-- Markdown mirror. Canonical: https://empryo.com/docs/tools/agents -->

# Agents

> Define specialized subagents as markdown files. Empryo reads them from project and global scopes, including your existing .claude and .opencode dirs.

An agent is a markdown file that defines a specialized worker: what it is for, which model runs it, which tools it may touch, and — in the body — the system prompt it thinks with. When the main agent dispatches parallel work, it can hand a task to one of your definitions instead of a generic explorer.

This is the same layout the rest of the ecosystem converged on in 2026, so Empryo reads the agent directories you already have. An existing `.claude/agents/reviewer.md` works here with no porting step.

## Write one

Create a markdown file with `name` and `description` frontmatter. The body becomes the agent's system prompt.

```markdown
---
name: perf-hunter
description: Finds hot paths and allocation churn. Use before optimizing anything.
mode: explore
tools: read, grep, genome_analyze
effort: low
---

You hunt for performance problems. Report the top 3 hot paths with `file:line`
and the measured or inferred cost of each. Never edit files.
```

Run `/agents` to see every definition Empryo found, grouped by scope, with the overrides each one carries. Press Enter on a row to read its full prompt, `r` to re-scan after an edit. On the desktop app the same view is a drawer, also on `/agents`.

Edits land within a few seconds — there is no restart step.

## Scopes

Definitions resolve from project and global directories, with project winning any name collision:

```
.empryo/agents/                     project
.agents/agents/                     project
.claude/agents/                     project  (Claude Code compatible)
.opencode/agent/                    project  (opencode compatible)
.gemini/agents/                     project  (Gemini CLI compatible)

~/.empryo/agents/                   global
~/.agents/agents/                   global
~/.claude/agents/                   global
~/.config/opencode/agent/           global
~/.gemini/agents/                   global
```

Subdirectories are scanned too, so you can organize definitions into folders like `agents/review/`. Identity comes from the `name` field (or the filename when `name` is absent), never the path.

When two directories define the same name, the higher-precedence file wins silently at dispatch time — but the collision is tracked: `agent_create` warns which file it shadows (or is shadowed by), so a definition you just wrote never loses to a forgotten `.claude/agents/` copy without telling you.

## Frontmatter

Only `name` and `description` are required. Everything else narrows what the agent may do.

| Field             | Meaning                                                                                             |
| :---------------- | :-------------------------------------------------------------------------------------------------- |
| `name`            | Unique id, lowercase and hyphenated. Falls back to the filename                                      |
| `description`     | When to delegate to this agent — the main agent routes on this text                                  |
| `mode`            | `explore` (read-only) or `code` (may edit). Omit to let the task decide                              |
| `model`           | A full `provider/model` id, or an alias mapped onto Empryo's tiers                                   |
| `tools`           | Allowlist. Omit to inherit the role's full belt                                                      |
| `disallowedTools` | Denylist, applied on top of `tools`                                                                  |
| `effort`          | Reasoning effort for this agent's runs                                                               |
| `maxTurns`        | Hard cap on agentic steps                                                                            |
| `skills`          | Skills preloaded into the agent's context                                                            |
| `temperature`     | Sampling temperature override for this agent's runs                                                  |
| `color`           | Display color for panels and transcripts                                                             |

Unknown keys are ignored rather than fatal, so a `permission:` block written for another harness will not break a definition Empryo otherwise understands.

### Modes

`mode` decides whether the agent can edit files. A definition that declares one always wins over what the dispatcher asked for — an `explore` agent stays read-only even when handed an editing task. Vocabulary from other tools is mapped onto the same two roles, so opencode's `subagent` and `primary` both work.

A `tools` list is a hard gate, not a hint: blocked tools stay visible to the model with their schema intact but refuse to run, naming the agent that restricted them.

### Models

A full `provider/model` id is honored exactly. Bare aliases (`sonnet`, `haiku`, `opus`) map onto Empryo's cheap and capable tiers rather than being guessed into a provider — your configured provider may not be the one the definition's author had. `inherit`, or omitting the field, keeps whatever the dispatcher picked.

## Run one

The main agent picks an agent on its own when a task matches a definition's description — that is what `description` is for, so write it as a routing instruction ("Use after writing or modifying code"), not as a title. Every definition appears in the dispatch tool's catalog, so the model can name it explicitly too:

- `dispatch(tasks:[{task: "…", agent: "perf-hunter"}])` — an in-turn parallel worker under that definition's prompt, model, and tool policy.
- `background_dispatch(task: "…", agent: "perf-hunter")` — the same, detached: you get a `bg-N` handle and keep working while it runs.

A named agent decides its own role and model, with one hard rule: a definition can never grant edit power the session denied — read-only stays read-only.

Headless runs an entire session under a definition:

```bash
empryo --headless --agent perf-hunter "why is the boot path slow?"
```

An unknown name is an error listing what is available, rather than a silent fall back to the default agent.

Workers running under a definition are labeled with it: the desktop Subagents panel, the per-agent activity modal, and the TUI dispatch tree all badge the lane with the definition's name, so a custom agent is never mistaken for a generic explorer.

## Let the agent write one

Forge can create definitions itself with the `agent_create` tool — name, description, and prompt land as a markdown file in `.empryo/agents/` (or `~/.empryo/agents/` with `scope: global`), dispatchable in the same turn. Describe a repeatable role once ("a release-notes writer that reads CHANGELOG style") and it becomes part of the catalog.
