Custom Agent Development Guide
Note: This document focuses on Agent role development (TUI/Daemon multi-role switching). For Subagent role configuration, please refer to the
[subagent]section in Configuration File Guide.
This document describes how to configure custom Agents in xiaoo. An Agent role is declared entirely through TOML configuration in ~/.config/xiaoo/config.toml. Slash commands (~/.xiaoo/commands/<name>.md) are a separate feature — they are standalone prompt templates invoked from the TUI input box, not agent role definitions — but a slash command can be used to drive an agent by invoking a skill or by pre-expanding a prompt body before the turn is submitted.
1. Agent Configuration Architecture
Agent Role Configuration
└── TOML Config (~/.config/xiaoo/config.toml) [REQUIRED]
├── Description
├── System Prompt (prompt)
├── Max turns (optional)
└── Tool Permission Management (fine-grained control) [OPTIONAL]
How it works: On startup, the TUI/Daemon reads all [agent.<name>] entries from config.toml into the agent role registry. The builtin plan role is injected automatically and cannot be overridden. The Core tab (the default agent with no role-specific prompt) is always present and represents the absence of an active role.
Slash commands under ~/.xiaoo/commands/ are loaded separately by apps/endside/src/services/command_loader.rs and are surfaced as /command-name autocompletions; they are not merged into agent roles.
2. TOML Configuration
TOML serves as the registration entry point for every Agent role. An Agent must be declared in TOML to be recognized by the runtime.
2.1 File Location
Edit ~/.config/xiaoo/config.toml
2.2 Configuration Structure
Edit [agent.<name>] and [agent.<name>.tools]
Example:
[tui]
agent_order = ["Agent1", "Core", "Agent2", "plan"]
[agent.code-reviewer]
description = "Reviews code for best practices and potential issues"
prompt = "You are a code reviewer. Focus on security, performance, and maintainability."
[agent.code-reviewer.tools]
file_write = false
file_edit = false
[tui].agent_order is optional. It controls the full Agent tab order. Include Core to place the default agent anywhere in the tab bar; if Core is omitted, it stays first for backward compatibility. Roles omitted from the list are appended in the default alphabetical order. The builtin plan role is always appended last if not explicitly ordered.
2.3 Configuration Reference
Basic Configuration ([agent.<name>])
| Field | Required | Description |
|---|---|---|
description |
Yes | Agent description displayed in help output |
prompt |
Yes | System Prompt defining the Agent's behavior |
max_turns |
No | Optional cap on agent loop turns for this role |
The
planrole is builtin (seeapps/shared/src/builtin_agent_roles.rs). Declaring[agent.plan]in config is rejected at startup.
Tool Permissions ([agent.<name>.tools])
| Setting | Description |
|---|---|
tool_name = true |
Explicitly allow the tool |
tool_name = false |
Explicitly deny the tool |
| Not defined | Falls back to global permission policy |
3. Slash Command Files (Separate Feature)
Slash commands are reusable prompt templates invoked from the TUI input box
with /<name>. They live in ~/.xiaoo/commands/<name>.md and are loaded by
apps/endside/src/services/command_loader.rs. They are not agent role
definitions and are not linked to [agent.<name>] entries — a command file
just provides a prompt body that gets submitted as the user turn (optionally
with leading /command args parsing).
3.1 File Location
Create a Markdown file in ~/.xiaoo/commands/:
~/.xiaoo/commands/
├── bugfix.md
├── deploy.md
└── review.md
The command name is the filename stem (without .md). Invoke it in the TUI
with /<name>, optionally followed by arguments.
3.2 File Format
---
description: Automated bugfix workflow for AET
---
Automatically detect the language of user input and respond in the same language.
Invoke the bugfix-automation skill with the provided natural language arguments, then execute exactly as the skill presents.
3.3 Format Breakdown
| Section | Description |
|---|---|
Frontmatter wrapped in --- |
Optional YAML-like metadata; only description is read by the loader |
Body after closing --- |
Prompt body injected as the user turn when the slash command is invoked |
3.4 Frontmatter Fields
| Field | Required | Description |
|---|---|---|
description |
No | Short summary shown in slash autocompletion; empty string if omitted |
The command loader only parses
descriptionfrom the frontmatter.disable-model-invocationis a skill frontmatter field (see skill_usage.md), not a command-file field — setting it in a command file has no effect on agent behavior.
3.5 Relationship to Agents
A slash command does not switch the active agent role. To combine them:
- Switch to the desired agent role with
Tab(or via[tui].agent_order). - Invoke the slash command — its body is submitted as the user turn for the currently active agent role.
The *.Chat.command.before hooker (see plugins.md) can
inspect or transform the command body before it becomes a user turn.
4. Configuration Checklist
After creating an Agent role, verify the following:
-
config.tomlcontains an[agent.<name>]declaration (required) -
descriptionandpromptare both set - Tool permissions in TOML follow the principle of least privilege
- The Agent loads successfully (use Tab to switch agent in TUI)
- You did not declare
[agent.plan](it is builtin and cannot be overridden)