How to Create Custom Agents with Specific Tools and System Prompts in Forge

You can create custom agents in Forge by adding Markdown files with YAML front-matter to ./.forge/agents/ or ~/.forge/agents/, defining the agent's id, tools whitelist, and system_prompt template, which Forge loads via ForgeAgentRepository and renders at runtime using the current environment context.

Forge ships with three built-in agents—forge, muse, and sage—but the antinomyhq/forgecode repository allows you to create custom agents with specific tools and system prompts tailored to your workflow. These custom agents are defined in Markdown files with YAML front-matter that specify everything from tool access to model parameters. When you start a conversation, Forge parses these definitions, renders the system prompt template against the current environment, and enforces tool restrictions without requiring any code changes.

Where Forge Discovers Custom Agents

Forge searches for agent definitions in three locations, with later sources overriding earlier ones:

  1. Project-local agents – ./.forge/agents/*.md relative to the current working directory.
  2. Global custom agents – ~/.forge/agents/*.md in your home directory.
  3. Built-in agents – Compiled into the binary.

The resolution logic lives in ForgeAgentRepository, which walks these directories and keeps the last occurrence of each id. This precedence ensures that CWD > Global > Built-in, meaning a project-local definition always wins.

Agent File Format and Front-Matter Schema

Each custom agent is a Markdown file parsed by gray_matter into an AgentDefinition. The front-matter supports the following keys:

  • id (required) – Unique identifier for addressing the agent (e.g., :my-agent).
  • title – Human-readable name for listings.
  • description – Summary shown in forge agents list.
  • system_prompt – Template string for the system message.
  • tools – Array of permitted tool names (supports glob patterns like mcp_*).
  • tool_supported – Boolean override for model-level tool support.
  • custom_rules – Additional style guidelines injected into the prompt.
  • provider, model, temperature, max_tokens – Model configuration overrides.
  • max_turns, compact – Execution control settings.

The file body after the front-matter serves as the system prompt template if system_prompt is omitted. Templates use Handlebars syntax and can reference variables like {{env.cwd}} and {{tool_names.read}}.

How System Prompts Are Rendered at Runtime

When a conversation initiates, SystemPrompt::add_system_message constructs a SystemContext containing:

  • The current Environment (working directory, OS, etc.).
  • Available tool definitions from ToolCatalog::iter().
  • A tool_names mapping for template interpolation.
  • Aggregated custom rules from both agent and repository levels.

The TemplateEngine renders the agent’s system_prompt template against this context, producing the final system message visible to the LLM.

Restricting Tool Access with Whitelists

The tools array in your agent definition acts as a whitelist. During execution, ToolResolver::is_allowed (called via validate_tool_call) checks each tool invocation against this list, supporting glob patterns like mcp_* to match multiple tools. If a tool isn't listed, the call is blocked before reaching the executor.

Creating Your First Custom Agent

Follow these steps to create custom agents with specific tools and system prompts in Forge:

  1. Create a Markdown file with the agent definition (see examples below).
  2. Place the file in ./.forge/agents/ for project-specific agents or ~/.forge/agents/ for global access.
  3. Verify discovery by running forge agents list to see your agent alongside built-ins.
  4. Invoke the agent using its id: :agent-id your prompt here.

Forge automatically resolves naming conflicts via resolve_agent_conflicts in agent.rs, ensuring local definitions override global ones.

Practical Agent Configuration Examples

Minimal Custom Agent

Create a code reviewer agent with limited tool access:

---
id: code-reviewer
title: Code Reviewer
description: Reviews Rust code and suggests improvements.
tools:
  - fs_search
  - read
  - write
custom_rules: |
  - Be concise.
  - Prefer using `derive_setters` where appropriate.
---

You are a meticulous Rust code reviewer.  
Focus on correctness, safety, and idiomatic style.  
When you suggest a change, include an inline diff in markdown.

Save this as ~/.forge/agents/code-reviewer.md. The body serves as the template, with access to {{env.cwd}} and tool name variables.

Agent with Glob Tool Patterns

Whitelist entire tool categories using wildcards:

---
id: data-fetcher
title: Data Fetcher
description: Retrieves remote data and stores it locally.
tools:
  - fetch
  - mcp_*
---

You are a data-fetching assistant. Use the `fetch` tool for HTTP GET requests.
When invoking any `mcp_*` tool, include a short justification.

The ToolResolver expands mcp_* to match all MCP-related tools automatically.

Model Override Configuration

Force specific model settings for specialized tasks:

---
id: vision-assistant
title: Vision Assistant
description: Works with images using a vision-capable model.
provider: openai
model: gpt-4o
temperature: 0.7
tools:
  - read
  - image_read
---

You are an assistant that can analyse images.  
When the user supplies an image path, use the `read` tool to retrieve its contents.
If the model supports image input, also call `image_read` to get a visual description.

These settings override global defaults for sessions using this agent.

CLI Usage

List and invoke your custom agents:


# List all available agents

forge agents list

# Use the custom agent

:code-reviewer Review the error handling in src/main.rs

Summary

  • Forge loads custom agents from ./.forge/agents/ and ~/.forge/agents/, with project-local files taking precedence over global and built-in definitions.
  • Define agents using Markdown with YAML front-matter parsed into AgentDefinition structs; the id and tools fields are required for basic functionality.
  • System prompts are Handlebars templates rendered by SystemPrompt::add_system_message with access to environment variables and tool catalogs.
  • Tool access is restricted via whitelists processed by ToolResolver::is_allowed, supporting glob patterns for flexible categorization.
  • Invoke custom agents using the :agent-id syntax in the Forge CLI.

Frequently Asked Questions

Can I override a built-in Forge agent like "forge" or "muse"?

Yes. Create a custom agent file with the same id as a built-in agent (e.g., id: forge) in ./.forge/agents/ or ~/.forge/agents/. The resolve_agent_conflicts function ensures your definition takes precedence over the compiled default.

What happens if I don't specify a tools list in the agent definition?

If the tools field is omitted or empty, the agent likely inherits default permissions or restrictions based on the ToolResolver implementation. However, for security and predictability, you should explicitly whitelist required tools using the tools array.

Can I use custom variables in my system prompt templates?

Yes. The template engine passes a SystemContext that includes env (environment details), tool_names (mappings), and any custom variables defined in TemplateConfig. Reference them using Handlebars syntax like {{env.cwd}} or {{tool_names.read}} within your system prompt body or system_prompt front-matter field.

How do I debug why my custom agent isn't loading?

Run forge agents list to verify the agent appears. If missing, check that:

  1. The file is in ./.forge/agents/ or ~/.forge/agents/ with a .md extension.
  2. The YAML front-matter is valid and the id field is present (required by parse_agent_file).
  3. The file name doesn't contain spaces or special characters that might interfere with path resolution via EnvironmentInfra::agent_path.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →