Create a Custom Agent in TOML
On this page
Lesson rewritten November 2, 2026. Previous examples used keys that do not exist in agent files (
model,system_prompt,auto_approve) and non-existent tools (list_dir,edit_file). Keys and tool names now align with the official reference and Vibe source code. Sources: Agents · Configuration reference — Agent definition files · built-in tools (mistral-vibe repo).
Beyond Built-in Agents
Built-in agents cover standard personas, but your projects have unique needs: a payments team requires different safeguards than a documentation team. Vibe lets you create custom agents by placing a .toml file in ~/.vibe/agents/ (user-level) or ./.vibe/agents/ (project-level, loaded only if the folder is trusted). Behavior defined in a file is readable, versionable, and shareable, unlike instructions repeated every session.
The agent name matches the filename: redteam.toml launches with vibe --agent redteam. The name main is reserved.
Agent File Keys
| Key | Role |
|---|---|
agent_type | "agent" (default, selectable by user) or "subagent" (launched only by delegation) |
display_name, description | Display name and description; description is mandatory for a subagent |
instructions | Inline instructions appended after the system prompt (for a subagent, these replace it) |
system_prompt_id | Name of a Markdown file in ~/.vibe/prompts/ or ./.vibe/prompts/, without the extension |
active_model | Alias of the model to use for this agent |
enabled_tools, disabled_tools | Allowlist and blocklist of tools (exact names, glob patterns, or re: expressions) |
[tools.<tool>] | Per-tool permissions: permission = "always", "ask", or "never", plus for bash, allowlist and denylist of command prefixes |
safety | Visual indicator only (input border color): safe, neutral, destructive, smart, or yolo; it enforces no permissions (Lesson 3) |
Tools You Can Name
Vibe’s built-in tools use these names: read_file, write_file, edit (formerly search_replace), bash, grep, todo, task (delegation to a subagent), skill, ask_user_question, web_fetch, and web_search. Tools from an MCP server are named {server}_{tool}, and connector tools are connector_{connector}_{tool}. A misspelled tool name in enabled_tools matches nothing: verify spelling before concluding an agent “refuses” to write a file.
First Agent: The Planner
Vibe has no built-in plan agent; the documentation provides this read-only example to explore a repository and propose a plan before any modification:
# ~/.vibe/agents/plan.toml
display_name = "Plan"
description = "Explores the repository and proposes a plan before any modification."
safety = "safe"
disabled_tools = ["edit", "write_file"]
instructions = """
Explore the repository and propose a step-by-step implementation plan.
Do not modify any files until the user approves the plan.
"""
[tools.bash]
permission = "ask"
Launch it with vibe --agent plan. Once the plan is approved, press Shift+Tab to switch to accept-edits for execution. Note the file order: in TOML, any key written after a table header like [tools.bash] belongs to that table. Place top-level keys first, and [tools.*] blocks at the end.
A Documentation Agent
# ~/.vibe/agents/doc-writer.toml
display_name = "Technical Writer"
description = "Writes technical documentation based on source code."
safety = "neutral"
enabled_tools = ["read_file", "grep", "write_file", "edit", "ask_user_question"]
instructions = """
Based on the source code:
1. Write a docstring for every public function.
2. Maintain a structured README with examples.
3. Document required environment variables.
Style: professional, concise, supported by code examples.
"""
[tools.write_file]
permission = "ask"
It can read, search, and write, but cannot run commands: bash is not in its list. Every file creation requires your approval. Try it on a small module before applying it to an entire repository.
Choosing an Agent Model
active_model expects the alias of a configured model. Vibe ships with a built-in model, Mistral Medium 3.5, aliased as mistral-medium-3.5. For another model, first declare a preset in config.toml, then reference its alias:
# ~/.vibe/config.toml
[[models]]
name = "codestral-latest"
provider = "mistral"
alias = "codestral"
# in the agent file
active_model = "codestral"
Without active_model, the agent uses the session’s model.
Writing Instructions
Two paths exist. instructions contains inline text appended after Vibe’s system prompt: this is the simplest approach. system_prompt_id points to a Markdown file in the prompts/ folder, useful for long prompts reviewed in code reviews. One behavioral detail matters: a custom agent’s prompt applies only if you select it before your first message (via --agent or Shift+Tab). If you switch agents mid-session, its tools, permissions, and model apply immediately, but its prompt takes effect only after /clear.
Best Practices
Least privilege first: give an agent only the tools it needs. An analysis agent does not need write_file; a writer does not need bash. Removing each tool makes an entire category of errors impossible.
One agent per responsibility next: a catch-all file produces mediocre responses everywhere. Three targeted files beat one generic one.
Precise instructions finally: define the exact role, project conventions, expected output format, and errors to avoid. When an agent disappoints, it is almost always because one of these four points is missing.
Key Takeaways
- A custom agent is a
.tomlfile in~/.vibe/agents/or./.vibe/agents/; its name matches the filename - Useful keys:
display_name,description,instructionsorsystem_prompt_id,active_model,enabled_tools,disabled_tools,[tools.<tool>] - Tool names:
read_file,write_file,edit,bash,grep,todo,task,skill,ask_user_question,web_fetch,web_search active_modelexpects a model preset alias (ormistral-medium-3.5, built-in)- Place
[tools.*]blocks at the end of the file