Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Agents

Agents are the building blocks of agentful - specialized AI workers, each with a specific domain of expertise, well-defined responsibilities, and clear boundaries. They don't just "write code" - they follow patterns, enforce standards, and collaborate through the orchestrator.

What Are Agents?

An agent is defined by:

  1. Name - Unique identifier (e.g., backend, frontend, tester)
  2. Description - What it does, what it doesn't do
  3. Model - Which AI model powers it (Sonnet for specialists, Opus for coordinators)
  4. Tools - What it can access (Read, Write, Edit, Bash, Task, etc.)
  5. Scope - What it's responsible for
  6. Patterns - How it implements features

Here's a typical agent definition:

---
name: backend
description: Implements backend services, repositories, controllers, APIs. Never modifies frontend code.
model: sonnet
tools: Read, Write, Edit, Glob, Grep, Bash
---
 
# Backend Agent
 
You are the **Backend Agent**. You implement server-side code using clean architecture patterns.
 
## Your Scope
- API Routes & Controllers
- Service Layer
- Repository Layer
- Database schemas
- Authentication
 
## NOT Your Scope
- UI components → @frontend
- Tests → @tester
- Code review → @reviewer

Why Multiple Agents?

The Problem with "Do Everything" AI

A single AI agent that tries to do everything suffers from:

  • Context confusion - Frontend patterns mixed with backend patterns
  • Quality inconsistency - Different standards for different domains
  • Validation complexity - Hard to enforce domain-specific rules
  • Scalability limits - Can't specialize in every framework

The agentful Solution

Specialization = Quality

Each agent:

  • Knows its domain deeply
  • Follows consistent patterns
  • Enforces domain-specific rules
  • Stays within its boundaries

The Seven Core Agents

1. Orchestrator Agent

The conductor that never plays an instrument
Role: Coordinate all work
Model: Opus (most capable)
Tools: Read, Write, Edit, Glob, Grep, Task, AskUserQuestion, TodoWrite
Responsibilities:
  • Read PRODUCT.md to understand what we're building
  • Track progress in .agentful/completion.json
  • Read state from .agentful/state.json
  • Delegate ALL implementation to specialist agents
  • Ensure validation happens after every change
  • Block on user decisions when needed
What it NEVER does:
  • Write code directly
  • Skip validation
  • Make assumptions about user preferences
Example delegation:
Task("backend", "Implement JWT authentication service per PRODUCT.md section 3")
Task("reviewer", "Review all authentication changes")
Task("tester", "Write tests for authentication module")

2. Architect Agent

The tech stack analyst
Role: Analyze tech stack and generate specialized agents
Model: Opus
Tools: Read, Write, Edit, Glob, Grep, Task
Responsibilities:
  • Read PRODUCT.md to identify the tech stack
  • Generate specialized agents for languages/frameworks
  • Update existing agents with tech-specific patterns
  • Create .agentful/architecture.json documenting decisions
Example output:
{
  "detected_stack": {
    "frontend": {
      "framework": "Next.js",
      "version": "14",
      "language": "TypeScript"
    },
    "database": {
      "provider": "PostgreSQL",
      "orm": "Prisma"
    }
  },
  "generated_agents": [
    "nextjs-agent",
    "prisma-agent"
  ]
}

3. Backend Agent

Server-side specialist
Role: Implement services, repositories, APIs, databases
Model: Sonnet
Tools: Read, Write, Edit, Glob, Grep, Bash
Scope:
  • API Routes & Controllers
  • Service Layer (business logic)
  • Repository Layer (data access)
  • Database schemas and migrations
  • Authentication (JWT, sessions, OAuth)
  • Input validation with Zod
  • Error handling
NOT its scope:
  • UI components → @frontend
  • Tests → @tester
  • Code review → @reviewer
Implementation pattern:
// Repository Layer
export class UserRepository {
  async findById(id: string): Promise<User | null> {
    return db.user.findUnique({ where: { id } });
  }
}
 
// Service Layer
export class UserService {
  constructor(private repo: UserRepository) {}
 
  async registerUser(input: RegisterInput): Promise<User> {
    const existing = await this.repo.findByEmail(input.email);
    if (existing) throw new ConflictError('User already exists');
    return this.repo.create(input);
  }
}
 
// Controller/Route
export async function POST(req: Request) {
  const body = await req.json();
  const service = new UserService(new UserRepository());
  const user = await service.registerUser(body);
  return Response.json(user, { status: 201 });
}

4. Frontend Agent

UI and client-side specialist
Role: Implement components, pages, hooks, styling
Model: Sonnet
Tools: Read, Write, Edit, Glob, Grep, Bash
Scope:
  • UI Components (reusable component library)
  • Pages (route pages and views)
  • Custom React hooks
  • State management (Context, Zustand, Redux)
  • Form handling and validation
  • Styling (Tailwind, CSS Modules, styled-components)
  • Client-side logic and interactions
NOT its scope:
  • Backend API routes → @backend
  • Database operations → @backend
  • Tests → @tester
Implementation pattern:
// Component
export interface ButtonProps {
  variant?: 'primary' | 'secondary' | 'danger';
  size?: 'sm' | 'md' | 'lg';
  isLoading?: boolean;
}
 
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  ({ children, variant = 'primary', size = 'md', isLoading, ...props }, ref) => {
    const baseStyles = 'rounded-lg font-medium transition-colors';
    const variants = {
      primary: 'bg-blue-600 text-white hover:bg-blue-700',
      secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
    };
 
    return (
      <button
        ref={ref}
        disabled={isLoading}
        className={`${baseStyles} ${variants[variant]}`}
        {...props}
      >
        {isLoading ? 'Loading...' : children}
      </button>
    );
  }
);
 
// Custom Hook
export function useAuth() {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(true);
 
  useEffect(() => {
    fetch('/api/auth/me')
      .then(res => res.json())
      .then(data => setUser(data.user))
      .finally(() => setIsLoading(false));
  }, []);
 
  return { user, isLoading };
}

5. Tester Agent

Quality assurance specialist
Role: Write comprehensive unit, integration, and E2E tests
Model: Sonnet
Tools: Read, Write, Edit, Glob, Grep, Bash
Scope:
  • Unit Tests (functions, components, services)
  • Integration Tests (module interactions)
  • E2E Tests (full user flows)
  • Test fixtures (setup, teardown, mocks)
  • Coverage reports and improvement

Target: 80% coverage threshold

Implementation pattern:
describe('UserService', () => {
  let service: UserService;
  let mockRepo: UserRepository;
 
  beforeEach(() => {
    mockRepo = {
      findByEmail: vi.fn(),
      create: vi.fn(),
    } as any;
    service = new UserService(mockRepo);
  });
 
  it('should create a new user with hashed password', async () => {
    const input = {
      email: 'test@example.com',
      password: 'password123',
    };
 
    mockRepo.findByEmail = vi.fn().mockResolvedValue(null);
    mockRepo.create = vi.fn().mockResolvedValue({
      id: '1',
      email: input.email,
    });
 
    const result = await service.registerUser(input);
 
    expect(mockRepo.findByEmail).toHaveBeenCalledWith(input.email);
    expect(result.email).toBe(input.email);
  });
 
  it('should throw error if user already exists', async () => {
    mockRepo.findByEmail = vi.fn().mockResolvedValue({ id: '1' });
    await expect(service.registerUser(input)).rejects.toThrow('User already exists');
  });
});

6. Reviewer Agent

Code quality enforcer
Role: Review code, find dead code, validate production readiness
Model: Sonnet
Tools: Read, Glob, Grep, Bash, Write, Edit
Checks (runs all 8):
  1. TypeScript Check - npx tsc --noEmit
  2. Lint Check - npm run lint
  3. Dead Code Detection - Find unused exports, files, imports
  4. Test Check - npm test
  5. Coverage Check - Verify ≥ 80% coverage
  6. Security Check - Scan for secrets, vulnerabilities, debug logs
  7. Manual Code Review - Error handling, patterns, best practices
  8. Console Log Check - Find debug statements
Output format:
{
  "passed": false,
  "checks": {
    "typescript": { "passed": true },
    "lint": { "passed": true },
    "deadCode": {
      "passed": false,
      "issues": [
        "Unused export: formatDate in src/utils/date.ts",
        "Unused file: src/components/OldWidget.tsx"
      ]
    },
    "tests": { "passed": true },
    "coverage": {
      "passed": false,
      "actual": 72,
      "required": 80
    },
    "security": {
      "passed": false,
      "issues": [
        "console.log in src/auth/login.ts:45"
      ]
    }
  },
  "mustFix": [
    "Remove unused export formatDate from src/utils/date.ts",
    "Delete unused file src/components/OldWidget.tsx",
    "Add tests to reach 80% coverage (currently at 72%)",
    "Remove console.log from src/auth/login.ts:45"
  ]
}

7. Fixer Agent

Auto-fixer for validation failures
Role: Automatically fix validation failures identified by reviewer
Model: Sonnet
Tools: Read, Write, Edit, Glob, Grep, Bash
What it fixes:
  • Dead code (unused exports, files, imports)
  • Missing tests (adds tests to reach 80%)
  • Console.log statements
  • Hardcoded secrets
  • Type errors
  • Lint errors
What it NEVER does:
  • Comment out code (removes it)
  • Add @ts-ignore to silence errors
  • Leave // TODO: fix this comments
  • Make partial fixes
Fix strategy:
// Before (dead code)
export function formatDate(date: Date): string {  // ❌ Unused
  return date.toISOString();
}
export function parseDate(str: string): Date {  // ✅ Used
  return new Date(str);
}
 
// After - Fixer deletes unused function entirely
export function parseDate(str: string): Date {
  return new Date(str);
}

Agent Collaboration

How Agents Work Together

┌─────────────────────────────────────────────────────────────┐
│                        User                                 │
│                      "Build auth"                           │
└────────────────────────┬────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│                   Orchestrator                               │
│           "I'll coordinate, not implement"                  │
└─────────┬───────────────────────────────────────────────────┘

          ├──► Architect: "Analyze tech stack"
          │     └──► Generates nextjs-agent, prisma-agent

          ├──► Backend: "Implement JWT service"
          │     └──► Creates auth.service.ts

          ├──► Frontend: "Create login page"
          │     └──► Creates login-form.tsx

          ├──► Tester: "Write auth tests"
          │     └──► Creates auth.test.ts (target: 80%)

          ├──► Reviewer: "Check everything"
          │     └──► Finds: console.log, unused import

          └──► Fixer: "Fix the issues"
                └──► Removes console.log, unused import
                     └──► Reviewer: "All checks passed ✅"
                          └──► Orchestrator: "Update completion.json"

Communication Protocol

Agents never communicate directly. All communication flows through:

  1. State files - .agentful/state.json, .agentful/completion.json
  2. The orchestrator - Delegates via Task tool
  3. Artifacts - Code, tests, documentation

Example:

// Orchestrator delegates to backend
Task("backend", "Implement JWT authentication per PRODUCT.md")
 
// Backend completes and reports
// "Created auth.service.ts, login route, user repository"
 
// Orchestrator then delegates to reviewer
Task("reviewer", "Review all authentication changes")
 
// Reviewer reports issues to state file
// .agentful/last-review.json
 
// Orchestrator delegates to fixer
Task("fixer", "Fix issues from last-review.json")

Agent Boundaries

Clear Scope Separation

Each agent has explicit boundaries:

// Backend Agent - What it DOES
export class UserService {
  // ✅ Service layer logic
  async registerUser(input: RegisterInput): Promise<User> {
    const existing = await this.repo.findByEmail(input.email);
    if (existing) throw new ConflictError('User already exists');
    return this.repo.create(input);
  }
}
 
// Backend Agent - What it NEVER does
// ❌ Don't create UI components
// export function LoginForm() { ... }
 
// ❌ Don't write tests
// describe('UserService', () => { ... });
 
// ❌ Don't review code
// npx tsc --noEmit

Boundary Enforcement

Boundaries are enforced by:

  1. Agent instructions - Explicitly stated in agent definition
  2. Orchestrator delegation - Right agent for right task
  3. Reviewer validation - Checks for scope violations
  4. Tool limitations - Frontend agent doesn't get Bash for API routes

Why This Architecture Works

1. Focus = Quality

Each agent focuses on one domain:

  • Backend agent knows backend patterns deeply
  • Frontend agent knows UI patterns deeply
  • Tester agent knows testing strategies deeply

2. Parallel Work

Multiple agents can work simultaneously:

Orchestrator → Backend: "Build user API"
            → Frontend: "Build user profile UI"
            → Tester: "Write tests for previous feature"

3. Easy Debugging

When something goes wrong:

  • Know exactly which agent was responsible
  • Check agent's specific rules and patterns
  • Fix that agent without affecting others

4. Scalability

Need support for a new framework?

  • Architect generates a new specialized agent
  • Existing agents continue unchanged
  • Orchestrator can delegate to new agent

Creating Custom Agents

You can add your own agents in .claude/agents/:

---
name: mobile
description: Implements React Native mobile components and navigation
model: sonnet
tools: Read, Write, Edit, Glob, Grep, Bash
---
 
# Mobile Agent
 
You are the **Mobile Agent**. You implement React Native applications.
 
## Your Scope
- React Native components
- Navigation (React Navigation)
- Native modules
- Mobile-specific patterns
 
## NOT Your Scope
- Web UI → @frontend
- Backend APIs → @backend

The orchestrator will automatically discover and use your custom agent.

Summary

Agents are agentful's fundamental building blocks:

  • Specialized - Each has a specific domain
  • Collaborative - Work together through orchestrator
  • Boundaried - Clear scopes and responsibilities
  • Scalable - Easy to add new agents
  • Quality-focused - Enforce patterns and standards

Next: See how agents are coordinated