Skip to content

Agent Project Structure

Use a skill when…Use an agent when…
The workflow is sequential stepsThe task requires independent judgment
You always want the same procedureYou want specialized domain knowledge
You invoke it manually with /nameYou want automatic delegation by Claude
It’s a project-specific processIt’s a reusable capability (code review, research)
No special tool restrictions neededYou want to restrict which tools it can use
my-ai-project/
β”œβ”€β”€ .claude/
β”‚ β”œβ”€β”€ settings.json ← team permissions, hooks, env
β”‚ β”œβ”€β”€ settings.local.json ← personal overrides (gitignored)
β”‚ β”œβ”€β”€ CLAUDE.md ← project instructions and context
β”‚ β”‚
β”‚ β”œβ”€β”€ rules/ ← path-scoped instructions
β”‚ β”‚ β”œβ”€β”€ api.md ← applies to src/api/**
β”‚ β”‚ β”œβ”€β”€ tests.md ← applies to **/*.test.ts
β”‚ β”‚ β”œβ”€β”€ migrations.md ← applies to migrations/**
β”‚ β”‚ └── frontend.md ← applies to src/ui/**
β”‚ β”‚
β”‚ β”œβ”€β”€ skills/ ← repeatable workflows
β”‚ β”‚ β”œβ”€β”€ deploy/
β”‚ β”‚ β”‚ └── SKILL.md
β”‚ β”‚ β”œβ”€β”€ new-feature/
β”‚ β”‚ β”‚ └── SKILL.md
β”‚ β”‚ β”œβ”€β”€ hotfix/
β”‚ β”‚ β”‚ └── SKILL.md
β”‚ β”‚ └── release/
β”‚ β”‚ └── SKILL.md
β”‚ β”‚
β”‚ └── agents/ ← specialized Claude instances
β”‚ β”œβ”€β”€ researcher.md ← reads docs, never edits
β”‚ β”œβ”€β”€ code-reviewer.md ← reviews, suggests, never edits
β”‚ β”œβ”€β”€ test-writer.md ← writes tests only
β”‚ └── security-auditor.md ← security-focused read-only
β”‚
β”œβ”€β”€ .mcp.json ← MCP server config (shared)
β”œβ”€β”€ CLAUDE.md ← project overview
└── src/

This is your project’s β€œbriefing document.” Claude reads it at the start of every session.

.claude/CLAUDE.md:

# Project: Payments API
## What This Is
A REST API for processing payments. Built with Node.js + TypeScript + Postgres.
Deployed to AWS Lambda via Serverless Framework.
## Stack
- Runtime: Node.js 20, TypeScript 5
- Framework: Express 4
- Database: PostgreSQL 15, Prisma ORM
- Tests: Vitest, Supertest
- Deploy: Serverless Framework, AWS Lambda
## Critical Rules
- NEVER commit secrets or API keys
- NEVER modify migration files once they are applied
- NEVER skip tests when deploying to production
- ALWAYS run `npm run lint && npm test` before committing
## Build & Run
- Install: `npm install`
- Dev: `npm run dev`
- Test: `npm test`
- Test (watch): `npm run test:watch`
- Lint: `npm run lint`
- Build: `npm run build`
- Deploy staging: `npm run deploy:staging`
- Deploy prod: `npm run deploy:prod`
## Project Layout
- `src/handlers/` β€” Lambda handler functions
- `src/services/` β€” Business logic layer
- `src/repositories/` β€” Database access layer
- `src/middleware/` β€” Express middleware
- `src/types/` β€” Shared TypeScript types
- `prisma/` β€” Prisma schema and migrations
- `tests/` β€” All tests (mirrors src/ structure)
## Common Patterns
- All business logic goes in services/, not handlers/
- Repositories handle all DB access; services never use Prisma directly
- Use `AppError` class for all user-facing errors (see `src/types/errors.ts`)
- Validate all input with Zod schemas in `src/validators/`

These inject domain context automatically when Claude edits those files.

.claude/rules/migrations.md:

---
paths:
- "prisma/migrations/**"
- "prisma/schema.prisma"
---
# Database Migration Rules
CRITICAL: Never modify an existing migration file. They are immutable once applied.
To make database changes:
1. Edit `prisma/schema.prisma`
2. Run: `npx prisma migrate dev --name <description>`
3. The generated migration file is what gets committed
When reviewing schema changes:
- Check for missing indexes on foreign keys
- Verify NOT NULL columns have defaults for existing rows
- Test with `npx prisma migrate deploy --preview-feature` on staging first

.claude/rules/api-handlers.md:

---
paths:
- "src/handlers/**"
- "src/routes/**"
---
# API Handler Rules
All handlers must:
- Accept input validated by a Zod schema
- Call service layer (never access DB directly)
- Return responses using `formatResponse()` helper
- Use `asyncHandler()` wrapper for async functions
- Have a corresponding test in `tests/handlers/`
Error handling:
- Throw `AppError` for client errors (4xx)
- Let unknown errors bubble to the global error handler
- Never catch errors silently

Each agent should have a single clear responsibility and minimal tool access.

.claude/agents/researcher.md:

---
name: "researcher"
description: "Research documentation, APIs, and technical questions. Never modifies files."
model: "claude-sonnet-4-6"
tools:
- Read
- Grep
- Glob
- WebSearch
- WebFetch
---
You are a technical researcher. Your only job is to find and summarize information.
You NEVER edit files, write code, or run commands.
When researching:
1. Search existing code and docs first before going to the web
2. Cite specific file paths and line numbers when referencing code
3. Summarize findings concisely β€” focus on what the caller needs to act on
4. Flag any contradictions or ambiguities you find

.claude/agents/code-reviewer.md:

---
name: "code-reviewer"
description: "Review code changes for bugs, security issues, and best practices. Read-only."
model: "claude-opus-4-8"
tools:
- Read
- Grep
- Glob
- Bash(git diff *)
- Bash(git log *)
---
You are a senior code reviewer. You NEVER modify files β€” only review and report.
Review checklist:
- [ ] Logic errors and edge cases
- [ ] Security vulnerabilities (injection, auth bypass, data exposure)
- [ ] Performance issues (N+1 queries, missing indexes, memory leaks)
- [ ] Error handling (uncaught errors, silent failures)
- [ ] Missing or inadequate tests
- [ ] Deviation from project conventions (see CLAUDE.md)
Format each finding:
**Issue:** clear description
**Severity:** critical / high / medium / low
**File:** path:line
**Why it matters:** one sentence
**Fix:** specific suggestion

.claude/agents/test-writer.md:

---
name: "test-writer"
description: "Write comprehensive tests for existing code. Only writes test files."
model: "claude-sonnet-4-6"
tools:
- Read
- Grep
- Glob
- Write
- Edit
- Bash(npm test)
- Bash(npm run test:*)
---
You write tests. You NEVER modify source files β€” only create or edit test files in `tests/`.
Before writing tests:
1. Read the source file thoroughly
2. Read any existing tests for context
3. Identify: happy paths, edge cases, error cases, boundary conditions
Test conventions for this project:
- Framework: Vitest
- One test file per source file: `tests/services/payment.test.ts` for `src/services/payment.ts`
- Use `describe` blocks to group related tests
- Test behavior, not implementation details
- Mock external dependencies (Stripe, SendGrid) but NOT internal services
Run `npm test` after writing to confirm all tests pass.

.claude/settings.json:

{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(npm test)",
"Bash(npm install)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git checkout *)",
"Bash(git push *)",
"Bash(npx prisma *)",
"Bash(gh pr *)",
"Read",
"Edit",
"Write",
"Glob",
"Grep"
],
"deny": [
"Bash(rm -rf *)",
"Bash(sudo *)",
"Edit(prisma/migrations/**)",
"Edit(.env*)",
"Bash(git push --force *)"
]
},
"hooks": [
{
"event": "PostToolUse",
"if": { "tool": "Edit", "path": "src/**/*.ts" },
"run": "sh",
"args": ["-c", "npx tsc --noEmit 2>&1 | head -5 || true"],
"continueOnError": true
}
],
"env": {
"NODE_ENV": "test"
}
}

Now Claude can use your agent structure automatically:

"Review my changes to the payment service, write missing tests, then open a PR"

Claude will:

  1. Delegate to @code-reviewer to review src/services/payment.ts
  2. Delegate to @test-writer to write missing tests
  3. Run /open-pr skill after tests pass
  • read-only vs read-write β€” research agents never edit; implementation agents do
  • domain-specific β€” frontend-specialist knows React/CSS, db-specialist knows SQL/Prisma
  • risk-based β€” risky agents (deploy, delete) have require-approval: true
  • tool-restricted β€” give each agent only the tools it legitimately needs
  • Too fine-grained: an agent per function is overhead, not value
  • Overlapping responsibilities: two agents that both β€œfix bugs”
  • No clear trigger: if Claude can’t tell when to use an agent, it won’t

For complex tasks, describe what you need and let Claude coordinate:

I need to ship the new Stripe webhook feature:
1. Review all changes in src/handlers/webhook.ts
2. Write tests for every webhook event type
3. Run lint and tests β€” fix any failures
4. Open a PR with a good description

Claude will dispatch to @code-reviewer, then @test-writer, then run the /open-pr skill β€” all in the right order.

  • Trick: β€œDesign agents like an org chart: narrow roles, clear handoffs.”
  • Do: design a 3-agent layout for the learner’s real project, together.
  • They’ll trip on: creating 10 agents nobody maintains β€” start with 2 that earn their keep.

Learning path: β¬… 29-subagents.md Β· Index Β· ➑ 31-worktrees.md

Written by Fenil Patel