Skip to main content

Custom Sub-agents

Trellis ships three sub-agents (trellis-implement, trellis-check, trellis-research). You can modify them or add your own. This chapter walks through the Claude Code format as the main example, then lists the frontmatter differences on other platforms.
Sub-agents ship on 11 of 14 configured platforms: Claude Code, Cursor, OpenCode, Codex, Kiro, Gemini CLI, Qoder, CodeBuddy, Copilot, Droid, Pi Agent. The agent file format varies by platform (Markdown / TOML / JSON), and on platforms without a PreToolUse hook or extension equivalent the sub-agents read their JSONL manifest plus prd.md, design.md if present, and implement.md if present via a pull-based prelude instead of having that context injected. Codex can also run in inline mode, where the main session reads the same artifacts through skills. Kilo, Antigravity, and Devin do not expose a sub-agent primitive — the implement / check work runs inline in the main session.

Sub-agent definition (Claude Code example)

A sub-agent definition file lives at .claude/agents/{name}.md and uses YAML frontmatter:
Key frontmatter fields on Claude Code:

Sub-agent file format is platform-specific

The file extension, frontmatter shape, and tool-declaration syntax differ per platform:

Pi Agent model and thinking config

Pi sub-agent definitions live under .pi/agents/{name}.md. They use Markdown with YAML frontmatter, like Claude-style agents, plus optional Pi run configuration:
The Pi extension reads this frontmatter before it launches the child Pi process. It starts nested agents in text/no-session mode, forwards the current Trellis context id, and maps run config to Pi CLI args: Per-call model / thinking passed to the Pi subagent tool overrides frontmatter for that one child run. fallbackModels / fallback_models is parsed for pi-subagents-compatible files, but Trellis does not pass it to Pi CLI because Pi has no documented stable fallback-model flag. For custom context injection, use a task-local JSONL file convention and extend .pi/extensions/trellis/index.ts to handle the new sub-agent name. Pi Agent does not load Python hook scripts. If you author a sub-agent that should work on multiple platforms, put the canonical Claude-Code version in packages/cli/src/templates/claude/agents/ and add platform adapters in packages/cli/src/configurators/ that translate the frontmatter into each platform’s native syntax. Trellis already does this for the shipped trellis-implement / trellis-check / trellis-research.

Modifying a shipped sub-agent

Example: add a timeout and a stricter tool budget to trellis-check.
If you plan to roll this out across your team, put the change in .trellis/spec/backend/ (or wherever your convention lives) instead of the agent definition, so the sub-agent’s behavior changes through spec injection rather than a fork.

Creating a new sub-agent

Example: a trellis-test sub-agent that writes tests for the current diff.

Context injection

If you want your sub-agent to receive task and spec context the way the shipped ones do:
  1. Accept a JSONL name convention (e.g. test.jsonl) in each task directory.
  2. Load the JSONL entries first, then prd.md, then design.md if present, then implement.md if present.
  3. On platforms with a PreToolUse (sub-agent) hook or extension equivalent — Claude Code, Cursor, OpenCode, CodeBuddy, Droid, Pi Agent — edit inject-subagent-context or the Pi extension to handle the new sub-agent type.
  4. On platforms without that injection point (Codex, Kiro, Gemini, Qoder, Copilot), follow the pull-based prelude pattern the shipped sub-agents use: prepend a block at the top of the agent file telling the sub-agent to Read its JSONL and task artifacts before acting.
For a detailed walkthrough, see chapter 11 on hooks.