Agent Ready Academy
Module 4: Custom Agents and Multi-Agent Patterns

Building a Custom Agent

Hands-on: creating a specialized code reviewer agent from scratch

~15 min readIncludes code

Overview

You have learned why custom agents exist, how to structure their definition files with YAML frontmatter, and how to control their permissions with the tools field. Now it is time to build one. In this lesson, you will create a code reviewer agent from scratch -- a specialized agent that analyzes pull requests, flags issues by severity, and produces structured feedback. You will follow the process step by step: defining the goal, writing the frontmatter, composing the system prompt, and testing the agent against real code.

Step 1: Define the Goal

Before writing a single line of the agent definition, answer three questions:

  1. What does this agent do? It reviews code changes and produces a structured report of issues found.
  2. What tools does it need? Read, Glob, and Grep to view and search files. No Edit, Write, or Bash -- it should never modify the codebase.
  3. What makes it different from a general-purpose agent? It has a reviewer's mindset: it looks for problems, not solutions. It reports issues but does not fix them.

These three answers become the foundation for everything that follows. If you cannot answer them clearly, the agent is not ready to be built.

Step 2: Create the Agent Directory

If your repository does not already have an agents directory, create it:

Terminal

This gives you the standard location for all custom agent definitions. The .claude/ directory may already exist if you have a settings.json or other Claude configuration files.

Step 3: Write the Frontmatter

Create the agent file at .claude/agents/code-reviewer.md. Start with the required YAML frontmatter:

.claude/agents/code-reviewer.md (frontmatter)

The frontmatter establishes the agent's identity and constraints before a single line of the system prompt is written:

  • name: code-reviewer -- the identifier used to invoke this agent
  • description -- tells Claude when to delegate to this agent; the phrase "Use after modifying code" encourages proactive delegation
  • tools: Read, Glob, Grep -- enforces read-only access; the agent cannot edit files, write files, or run commands regardless of what anyone asks
  • model: sonnet -- uses a capable model that balances quality and speed for analysis

Step 4: Write the System Prompt

Now add the system prompt body after the frontmatter. Build it section by section.

Start with the role definition:

.claude/agents/code-reviewer.md (role)

Notice the explicit "You do NOT" statements right up front. The agent's identity and boundaries are established in the first paragraph.

Add context-gathering instructions:

.claude/agents/code-reviewer.md (context)

Add the review methodology:

.claude/agents/code-reviewer.md (methodology)

The ordered list gives the agent a consistent process to follow. Starting with correctness and security ensures the most important issues are caught first.

Define the output format:

.claude/agents/code-reviewer.md (output format)

A rigid output format makes reviews consistent and scannable. Every developer on the team knows exactly where to look for critical issues.

Set explicit constraints:

.claude/agents/code-reviewer.md (constraints)

Step 5: The Complete Agent File

Here is the full agent definition, assembled from the sections above:

.claude/agents/code-reviewer.md

Notice how the frontmatter and system prompt complement each other. The tools: Read, Glob, Grep in frontmatter enforces read-only access at the platform level. The "NEVER modify" constraints in the system prompt reinforce this behaviorally. Together, they create an agent that is both well-behaved and technically constrained.

Step 6: Understanding the Agent Lifecycle

When you invoke this agent, here is what happens:

Agent lifecycle sequence: the developer invokes the code-reviewer agent via the CLI. The CLI loads frontmatter (tools, model), system prompt, and CLAUDE.md, then initializes the agent. The developer asks for a review. The agent reads the source file, greps for imports, reads tests, and returns a structured review report. The agent cannot call Edit, Write, or Bash.

The key observation is that the agent's lifecycle is entirely read-only. The tools frontmatter ensures it has Read, Glob, and Grep -- nothing else. Even if the agent's reasoning tells it to edit a file, the platform blocks the attempt.

Step 7: Test the Agent

Testing your agent is straightforward. Invoke it and verify three things:

Test the happy path -- Give it a file to review and check that the output matches your expected format:

Terminal

Verify that the output contains the Summary, Issues Found, and Verdict sections in the correct format.

Test the boundaries -- Ask the agent to do something outside its role:

Terminal

The agent should refuse to make changes. Because tools: Read, Glob, Grep does not include Edit or Write, the platform prevents any file modifications even if the agent tries.

Test the context gathering -- Review the agent's output for evidence that it read CLAUDE.md and related files. The review should reference project conventions and understand the broader context, not just the isolated file.

Step 8: Iterate and Refine

Your first agent definition will not be perfect. After a few uses, you will notice:

  • Missing guidance -- The agent makes a type of comment you did not anticipate. Add instructions to handle it.
  • Too verbose -- The agent writes paragraph-length explanations for nits. Add a constraint: "Keep nit explanations to one sentence."
  • Missing context -- The agent does not check related files. Add an explicit step to read imports and tests.
  • Inconsistent format -- The agent drifts from the output format. Make the format more explicit with examples.

Treat the agent definition like code: iterate on it based on real-world usage, commit improvements, and review changes with your team.

The best agent definitions are written over weeks, not in a single session. Start with a minimal version and refine based on actual reviews.

Building Other Agent Types

The same process applies to any agent type. Here is a quick template for a different archetype -- a migration helper that updates deprecated API calls:

.claude/agents/api-migrator.md

Notice how this agent has broader tools (including Edit, Bash) because its role requires modifying files and running tests to verify results. The tools match the task.

Checklist: Before You Ship an Agent

Before committing a new agent definition to your repository, verify:

  • The name field clearly communicates the agent's role
  • The description field explains when to use the agent
  • The tools field is as restrictive as the task allows
  • The system prompt establishes identity, methodology, and constraints
  • The output format is explicitly defined (if the agent produces structured output)
  • You have tested the happy path, boundary cases, and context gathering
  • The file is committed to .claude/agents/ in version control

Summary

Building a custom agent follows a deliberate process: define the goal, write the YAML frontmatter with name, description, and tools, compose the system prompt section by section, test the agent against real code, and iterate based on results. The code reviewer agent you built in this lesson demonstrates the pattern: focused frontmatter that enforces read-only access, a structured methodology, a rigid output format, and explicit constraints. This same process applies to any agent archetype -- test writers, migrators, security auditors, and beyond. In the next lesson, you will learn how to coordinate multiple agents working together on complex tasks.

Check Your Understanding

Question 1 of 2

What is the first step before writing an agent definition file?