8 Agentic Coding Patterns That Ship 10x Faster (Cursor, Windsurf, Claude Code)
AI coding tools evolved.
In 2024, we got autocomplete. In 2025, we got inline chat. In 2026, we have autonomous agents that read your codebase, plan multi-file changes, run tests, and iterate until things work.
But here's the thing — most developers are still using these tools like fancy autocomplete. They type a prompt, get a suggestion, accept or reject, repeat.
That's like buying a Formula 1 car and driving it in first gear.
Agentic coding means giving the AI enough context, constraints, and autonomy to handle entire tasks end-to-end. The difference isn't the tool — it's the patterns you use.
In this article, I'll share 8 battle-tested agentic coding patterns with real configurations, prompt templates, and workflows that work across Cursor, Windsurf, Claude Code, and Copilot Workspace.
The Agentic Coding Spectrum
Not all AI coding is equal. Here's where the tools sit in March 2026:
Manual Autonomous
| |
| Copilot Cursor Windsurf Claude Code |
| (suggest) (compose) (cascade) (agent mode) |
| |
└──────────────────────────────────────────────────┘
Tab-complete → Multi-file → Full autonomy
The patterns in this article work across the spectrum, but they shine brightest in compose/cascade/agent modes where the tool can autonomously execute multi-step plans.
Pattern 1: The AGENTS.md Convention
The single most impactful pattern in agentic coding: give your AI agent a mission briefing file at the root of your project.
# AGENTS.md
## Project Context
This is a Next.js 14 SaaS application for invoice management.
- Framework: Next.js 14 (App Router)
- Database: PostgreSQL via Prisma
- Auth: NextAuth.js v5
- Styling: Tailwind CSS + shadcn/ui
- State: Zustand for client, React Query for server
- Testing: Vitest + Playwright
## Architecture Rules
- All API routes go in `app/api/` — NO pages router
- Database queries ONLY through Prisma — no raw SQL
- All forms use react-hook-form + zod validation
- Server components by default, "use client" only when needed
- Error boundaries on every route segment
## Coding Standards
- TypeScript strict mode — no `any` types
- All functions must have JSDoc comments
- Max file length: 300 lines — split if longer
- Imports: external first, then internal, then relative
- No barrel exports (index.ts re-exports)
## Common Patterns
### Creating a new feature
1. Schema first: `prisma/schema.prisma`
2. Migration: `npx prisma migrate dev`
3. Server action: `app/actions/feature.ts`
4. UI component: `components/feature/`
5. Page: `app/(dashboard)/feature/page.tsx`
6. Tests: `tests/feature.test.ts`
### API Error Handling
typescript
// Always use this pattern for API routes
export async function POST(req: Request) {
try {
const body = await req.json();
const validated = schema.parse(body);
// ... logic
return Response.json({ data: result });
} catch (error) {
if (error instanceof z.ZodError) {
return Response.json(
{ error: "Validation failed", details: error.issues },
{ status: 400 }
);
}
console.error("[API_ERROR]", error);
return Response.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
}
## What NOT to Do
- Don't add new dependencies without checking existing ones first
- Don't modify the auth flow without explicit approval
- Don't use `console.log` — use the structured logger
- Don't skip TypeScript types — ever
markdown
Why it works: Every AI coding tool reads project files for context. AGENTS.md gives the agent your team's knowledge upfront — architecture decisions, conventions, patterns, anti-patterns. Without it, the agent makes reasonable but wrong guesses.
Pro tip: Put AGENTS.md in your .cursorrules or .windsurfrules file for automatic inclusion, or keep it as a standalone file that Claude Code and other tools will discover.
Pattern 2: Task Decomposition Prompts
Don't ask the AI to "build a feature." Ask it to decompose first, then execute each step:
# Task Decomposition Template
## Phase 1: Plan (don't write code yet)
Analyze this requirement and create a step-by-step implementation plan:
**Requirement:** [paste requirement]
For each step, specify:
1. Files to create or modify
2. Dependencies on other steps
3. Test criteria (how do we know this step works?)
Output the plan as a numbered checklist. Do NOT write any code yet.
## Phase 2: Execute (one step at a time)
Now implement step [N] from the plan above.
Before writing code:
- Re-read the plan
- Check if previous steps are complete
- List any assumptions
After writing code:
- Verify it compiles (run the appropriate check)
- Run related tests
- Note any issues for the next step
## Phase 3: Verify
All steps are implemented. Now:
1. Run the full test suite
2. Check for TypeScript errors
3. Review all changed files for consistency
4. List any remaining TODOs or known issues
Here's a real-world example using this pattern in Cursor Composer:
@plan Create a Stripe webhook handler that:
- Validates the webhook signature
- Handles checkout.session.completed
- Updates the user's subscription in our DB
- Sends a welcome email for new subscribers
- Handles subscription.deleted for cancellations
- Has idempotency protection (don't process same event twice)
Output a numbered plan with files and test criteria. Don't code yet.
The agent produces a plan. You review it. Then:
@execute Implement step 1 from the plan: webhook signature validation.
Run the test after implementing.
Why this matters: Agents that try to build everything at once produce worse code than agents that plan first. The plan creates a checkpoint you can review before expensive code generation.
Pattern 3: Context Window Management
The biggest performance killer in agentic coding isn't the model — it's what's in the context window. Here's a .cursorrules file optimized for context management:
# .cursorrules — Context Window Optimization
# Include only what's relevant per task
context_rules:
# Always include for every task
always:
- AGENTS.md
- tsconfig.json
- package.json (dependencies section only)
- prisma/schema.prisma (model definitions only)
# Include based on task type
patterns:
api_route:
- app/api/**/*.ts
- lib/auth.ts
- lib/db.ts
- types/api.ts
ui_component:
- components/**/*.tsx
- lib/hooks/*.ts
- styles/globals.css
- tailwind.config.ts
database:
- prisma/schema.prisma
- prisma/migrations/
- lib/db.ts
- app/actions/*.ts
# Never include (saves tokens, avoids confusion)
exclude:
- node_modules/
- .next/
- "*.test.ts" # unless task is about testing
- "*.stories.tsx"
- coverage/
- dist/
And here's a prompt pattern that explicitly manages context:
## Context-Aware Task Prompt
**Task:** [description]
**Relevant files (read these):**
- `src/lib/auth.ts` — current auth implementation
- `src/types/user.ts` — User type definition
- `prisma/schema.prisma` — lines 45-80 (User model)
**Reference files (for patterns, don't modify):**
- `src/app/api/invoices/route.ts` — follow this API pattern
**Out of scope (don't touch):**
- Anything in `src/components/`
- The auth flow
- Database schema changes
**Expected output:**
- Modified: `src/app/api/users/route.ts`
- New: `src/app/api/users/[id]/route.ts`
- Modified: `src/lib/validators/user.ts`
Pattern 4: Test-Driven Agent Development (TDAD)
Write the tests first. Then let the agent implement until tests pass. This is the highest-confidence agentic coding pattern:
// tests/invoice-service.test.ts
// Write these FIRST, then let the agent implement
import { describe, it, expect, beforeEach } from "vitest";
import { InvoiceService } from "../src/services/invoice";
import { mockDb } from "./helpers/mock-db";
describe("InvoiceService", () => {
let service: InvoiceService;
beforeEach(() => {
service = new InvoiceService(mockDb());
});
describe("createInvoice", () => {
it("should create an invoice with line items", async () => {
const invoice = await service.createInvoice({
customerId: "cust_123",
lineItems: [
{ description: "Consulting", quantity: 10, unitPrice: 150 },
{ description: "Development", quantity: 20, unitPrice: 200 },
],
dueDate: new Date("2026-04-30"),
});
expect(invoice.id).toBeDefined();
expect(invoice.subtotal).toBe(5500); // 10*150 + 20*200
expect(invoice.status).toBe("draft");
expect(invoice.lineItems).toHaveLength(2);
});
it("should calculate tax correctly", async () => {
const invoice = await service.createInvoice({
customerId: "cust_123",
lineItems: [
{ description: "Service", quantity: 1, unitPrice: 1000 },
],
taxRate: 0.19,
dueDate: new Date("2026-04-30"),
});
expect(invoice.subtotal).toBe(1000);
expect(invoice.tax).toBe(190);
expect(invoice.total).toBe(1190);
});
it("should reject invoices with no line items", async () => {
await expect(
service.createInvoice({
customerId: "cust_123",
lineItems: [],
dueDate: new Date("2026-04-30"),
})
).rejects.toThrow("Invoice must have at least one line item");
});
it("should reject negative quantities", async () => {
await expect(
service.createInvoice({
customerId: "cust_123",
lineItems: [
{ description: "Bad", quantity: -1, unitPrice: 100 },
],
dueDate: new Date("2026-04-30"),
})
).rejects.toThrow("Quantity must be positive");
});
});
describe("sendInvoice", () => {
it("should change status from draft to sent", async () => {
const invoice = await service.createInvoice({
customerId: "cust_123",
lineItems: [
{ description: "Work", quantity: 1, unitPrice: 500 },
],
dueDate: new Date("2026-04-30"),
});
const sent = await service.sendInvoice(invoice.id);
expect(sent.status).toBe("sent");
expect(sent.sentAt).toBeDefined();
});
it("should not send an already-sent invoice", async () => {
const invoice = await service.createInvoice({
customerId: "cust_123",
lineItems: [
{ description: "Work", quantity: 1, unitPrice: 500 },
],
dueDate: new Date("2026-04-30"),
});
await service.sendInvoice(invoice.id);
await expect(
service.sendInvoice(invoice.id)
).rejects.toThrow("Invoice already sent");
});
});
});
Now the prompt to the agent:
## TDAD Prompt
I've written failing tests in `tests/invoice-service.test.ts`.
Your task:
1. Read the tests carefully
2. Implement `src/services/invoice.ts` to make ALL tests pass
3. Create any necessary types in `src/types/invoice.ts`
4. Run `npx vitest tests/invoice-service.test.ts` after each change
5. Iterate until all tests are green
6. Do NOT modify the test file
Constraints from AGENTS.md:
- Use Prisma for DB operations
- Zod for input validation
- Follow the service pattern in `src/services/customer.ts`
Why TDAD is powerful: The tests are an unambiguous specification. The agent can't "hallucinate" its way past a failing assertion. It either works or it doesn't.
Pattern 5: Incremental Migration Agent
Large refactors are where agentic coding shines. This pattern migrates code file-by-file with verification at each step:
# Migration Agent Prompt Template
## Objective
Migrate from [OLD_PATTERN] to [NEW_PATTERN] across the codebase.
## Rules
1. Migrate ONE file at a time
2. After each file:
- Run type checker: `npx tsc --noEmit`
- Run related tests: `npx vitest [file]`
- If either fails, fix before moving on
3. Commit after each successful file migration
4. Keep a migration log in `docs/migration-log.md`
## Migration Spec
### Before (Old Pattern)
typescript
// Old: class-based services with manual DI
class UserService {
private db: Database;
constructor(db: Database) {
this.db = db;
}
async getUser(id: string): Promise {
return this.db.users.findUnique({ where: { id } });
}
}
### After (New Pattern)
typescript
// New: functional with dependency injection via closure
import { type Database } from "@/lib/db";
export function createUserService(db: Database) {
return {
getUser: async (id: string): Promise => {
return db.users.findUnique({ where: { id } });
},
} as const;
}
// Type helper
export type UserService = ReturnType;
## File Order (migrate in this sequence)
1. `src/services/base.ts` — foundation
2. `src/services/user.ts` — simple, good test case
3. `src/services/invoice.ts` — medium complexity
4. `src/services/payment.ts` — complex, has events
5. `src/services/notification.ts` — has side effects
6. Update all imports in `src/app/` routes
7. Remove old `ServiceBase` class
## Migration Log Format
markdown
| # | File | Status | Tests | Notes |
|---|------|--------|-------|-------|
| 1 | base.ts | ✅ Done | 3/3 | Removed class, exported types |
| 2 | user.ts | ✅ Done | 8/8 | Added return type |
| 3 | invoice.ts | 🔄 In Progress | - | - |
markdown
Key insight: The agent can handle the mechanical work of refactoring, but it needs explicit rules about verification, order, and how to handle failures. Without these constraints, it'll try to change everything at once and break the build.
Pattern 6: Error Recovery Loops
When the agent hits an error, most developers intervene manually. Instead, teach the agent to self-recover:
# Error Recovery Protocol
When you encounter an error, follow this protocol:
## Level 1: Self-Fix (try 3 times)
1. Read the full error message and stack trace
2. Identify the root cause (not the symptom)
3. Apply the fix
4. Run the check again
5. If still failing after 3 attempts → escalate to Level 2
## Level 2: Context Expansion
1. Read related files that might contain the answer
2. Check if this is a known pattern in AGENTS.md
3. Search for similar patterns in the codebase: `grep -r "pattern" src/`
4. Try the fix with expanded context
5. If still failing → escalate to Level 3
## Level 3: Simplify
1. Revert to the last working state
2. Break the task into smaller sub-tasks
3. Implement the simplest version that could work
4. Add a TODO comment for the full implementation
5. Report what you couldn't complete and why
## NEVER do:
- Suppress errors with try/catch without logging
- Skip tests to "make it work"
- Add `@ts-ignore` or `any` types to bypass type errors
- Delete tests that are failing
- Change the requirement to match your implementation
Here's how this looks in a Claude Code workflow:
# claude-code-config.yaml
agent:
name: "feature-builder"
error_recovery:
max_self_fix_attempts: 3
escalation_strategy: "simplify"
verification:
after_each_change:
- "npx tsc --noEmit"
- "npx vitest --reporter=verbose"
guardrails:
forbidden_patterns:
- "@ts-ignore"
- "as any"
- "eslint-disable"
- "console.log"
max_files_changed: 10
require_test_for_new_files: true
Pattern 7: Multi-Agent Code Review
Use one agent to write code and another to review it. This catches issues that a single agent misses:
# multi_agent_review.py
# A simple multi-agent code review pipeline
import subprocess
import json
from pathlib import Path
def get_diff() -> str:
"""Get the current git diff of staged changes."""
result = subprocess.run(
["git", "diff", "--staged"],
capture_output=True, text=True
)
return result.stdout
def agent_review_prompt(diff: str, role: str) -> str:
"""Generate a review prompt for a specific reviewer role."""
roles = {
"security": """You are a security reviewer. Examine this diff for:
- SQL injection, XSS, CSRF vulnerabilities
- Hardcoded secrets or credentials
- Insecure deserialization
- Missing input validation
- Auth/authz bypasses
- Information leakage in error messages
For each issue found, specify:
- Severity (critical/high/medium/low)
- File and line number
- Description of the vulnerability
- Suggested fix
If no issues found, say "LGTM — no security issues detected."
""",
"performance": """You are a performance reviewer. Examine this diff for:
- N+1 query patterns
- Missing database indexes (infer from query patterns)
- Unnecessary re-renders in React components
- Large bundle imports (could be tree-shaken)
- Missing pagination on list endpoints
- Synchronous operations that should be async
- Memory leaks (unclosed connections, missing cleanup)
For each issue, estimate the impact and suggest a fix.
""",
"architecture": """You are an architecture reviewer. Examine this diff for:
- Violations of the patterns in AGENTS.md
- Tight coupling between modules
- Missing abstractions or leaky abstractions
- Inconsistency with existing codebase patterns
- Business logic in the wrong layer
- Missing error handling
- Proper separation of concerns
Reference existing code patterns when suggesting improvements.
""",
}
return f"""{roles[role]}
## Diff to Review
diff
{diff}
## Project Context
{Path("AGENTS.md").read_text() if Path("AGENTS.md").exists() else "No AGENTS.md found."}
"""
def run_review_pipeline():
"""Run all reviewers and aggregate results."""
diff = get_diff()
if not diff.strip():
print("No staged changes to review.")
return
results = {}
for role in ["security", "performance", "architecture"]:
prompt = agent_review_prompt(diff, role)
# Send to your preferred LLM API
# response = llm.complete(prompt, model="claude-sonnet")
# results[role] = response.text
print(f"--- {role.upper()} REVIEW ---")
print(f"Prompt ready ({len(prompt)} chars)")
print()
# Aggregate
blocking_issues = [
issue for role_results in results.values()
for issue in role_results
if issue.get("severity") in ("critical", "high")
]
if blocking_issues:
print(f"❌ {len(blocking_issues)} blocking issues found!")
print("Fix these before merging.")
else:
print("✅ All reviews passed. Ready to merge.")
if __name__ == "__main__":
run_review_pipeline()
shell
The power of multi-agent review: A single agent reviewing its own code has blind spots. Using different "reviewer personas" catches security issues that a performance reviewer misses, and vice versa.
Pattern 8: Autonomous Feature Branches
The ultimate agentic coding pattern: the agent creates a branch, implements the feature, writes tests, and opens a PR — all autonomously:
#!/bin/bash
# autonomous-feature.sh
# Fully autonomous feature implementation pipeline
set -euo pipefail
FEATURE_DESC="$1"
BRANCH_NAME="$2"
echo "🚀 Starting autonomous feature implementation"
echo "Feature: $FEATURE_DESC"
echo "Branch: $BRANCH_NAME"
# Step 1: Create branch
git checkout main
git pull origin main
git checkout -b "$BRANCH_NAME"
# Step 2: Plan (using your CLI agent tool)
echo "📋 Phase 1: Planning..."
PLAN=$(cat <<EOF
Read AGENTS.md for project context.
Create a detailed implementation plan for this feature:
$FEATURE_DESC
Output a JSON array of steps, each with:
- "description": what to do
- "files": array of files to create/modify
- "tests": how to verify this step
Do NOT write code yet. Planning only.
EOF
)
# Step 3: Execute each step
echo "⚡ Phase 2: Implementation..."
# The agent executes each planned step
# Step 4: Verify
echo "✅ Phase 3: Verification..."
# Run type checker
if ! npx tsc --noEmit; then
echo "❌ TypeScript errors found. Attempting auto-fix..."
# Agent fixes type errors
fi
# Run tests
if ! npx vitest --run; then
echo "❌ Tests failing. Attempting auto-fix..."
# Agent fixes failing tests (max 3 attempts)
fi
# Run linter
if ! npx eslint src/ --fix; then
echo "⚠️ Linting issues found."
fi
# Step 5: Commit and push
echo "📦 Phase 4: Commit..."
git add -A
git commit -m "feat: $FEATURE_DESC
Implemented by autonomous agent pipeline.
- Plan: [N] steps executed
- Tests: all passing
- Types: clean
- Lint: clean"
git push origin "$BRANCH_NAME"
# Step 6: Create PR
echo "🔀 Phase 5: Creating PR..."
# Use GitHub CLI or API to create PR
gh pr create \
--title "feat: $FEATURE_DESC" \
--body "## Summary
Autonomous implementation of: $FEATURE_DESC
## Changes
$(git diff main..HEAD --stat)
## Verification
- ✅ TypeScript: clean
- ✅ Tests: all passing
- ✅ Lint: clean
## Review Notes
This PR was autonomously generated. Please review carefully:
- [ ] Business logic correctness
- [ ] Edge cases covered
- [ ] No hardcoded values
- [ ] Error handling appropriate" \
--base main \
--head "$BRANCH_NAME"
echo "🎉 Done! PR created for review."
Important: Always require human review before merging autonomous PRs. The agent does the implementation work; a human validates the decisions.
The Configuration Files That Make It Work
Here's a complete setup for the major tools:
Cursor (.cursorrules)
# .cursorrules
You are an expert TypeScript/Next.js developer.
## Rules
1. Read AGENTS.md before every task
2. Plan before coding — decompose complex tasks
3. Run tests after every change
4. One file at a time for complex changes
5. Never skip types or error handling
## On Error
- Read the full error
- Check if AGENTS.md has guidance
- Fix root cause, not symptoms
- Max 3 self-fix attempts before asking
## Code Style
- Functional over class-based
- Composition over inheritance
- Explicit over implicit
- Small functions (<30 lines)
Windsurf (.windsurfrules)
# .windsurfrules
## Cascade Mode Configuration
### Context Loading
Always read these files first:
- AGENTS.md (project rules)
- relevant test files for the feature
### Execution Mode
- Use "Write" mode for new features
- Use "Edit" mode for refactors
- Always run verification after changes
### Iteration Protocol
When tests fail:
1. Read the test carefully
2. Read the error message
3. Fix the implementation (not the test)
4. Run again
5. After 3 failures, explain the issue
Claude Code (CLAUDE.md)
# CLAUDE.md
## Project
Next.js 14 SaaS — see AGENTS.md for full context.
## Commands
- Type check: `npx tsc --noEmit`
- Test: `npx vitest`
- Test single: `npx vitest path/to/test`
- Lint: `npx eslint src/`
- Dev server: `npm run dev`
- Build: `npm run build`
## Rules
- Follow AGENTS.md strictly
- Run type check + tests after every change
- Commit atomic changes with conventional commit messages
- Ask before adding new dependencies
Real-World Results
Here's what these patterns look like in practice:
| Metric | Without Patterns | With Patterns | Improvement |
|---|---|---|---|
| Feature implementation time | 4-8 hours | 30-90 min | 5-10x faster |
| First-attempt test pass rate | ~40% | ~85% | 2x better |
| Code review rounds | 3-5 | 1-2 | 60% fewer |
| Agent token waste | ~50% of budget | ~15% of budget | 70% savings |
| Post-merge hotfixes | 1 per 3 PRs | 1 per 10 PRs | 3x fewer |
The key insight: the patterns, not the models, determine your productivity. A well-configured Cursor with good AGENTS.md will outperform raw GPT-5 without structure.
Getting Started Checklist
If you want to adopt agentic coding patterns today:
- [ ] Create
AGENTS.mdin your project root (Pattern 1) — 30 minutes - [ ] Set up
.cursorrulesor equivalent for your tool — 15 minutes - [ ] Write tests before prompting for your next feature (Pattern 4) — already part of your workflow
- [ ] Use task decomposition prompts instead of "build X" (Pattern 2) — immediate
- [ ] Add error recovery rules to your agent config (Pattern 6) — 10 minutes
- [ ] Try multi-agent review on your next PR (Pattern 7) — 30 minutes
Start with Patterns 1 and 4. They have the highest impact-to-effort ratio.
Key Takeaways
AGENTS.mdis the highest-ROI file in your codebase. It turns a generic AI into your team's expert. Every coding agent reads it.Plan first, code second. Task decomposition prompts prevent the agent from going down rabbit holes.
Context management is a skill. What you exclude from the context window matters as much as what you include.
TDAD (Test-Driven Agent Development) is the gold standard. Tests are an unambiguous spec. Agents can't hallucinate past a failing assertion.
Teach your agent to recover from errors. Most developers intervene too early. A good error recovery protocol lets the agent fix itself.
Multi-agent review catches blind spots. One agent writes, multiple agents review from different angles.
Autonomous pipelines need human checkpoints. Full autonomy for implementation, human review before merge.
Patterns beat models. A well-structured workflow with a good model beats a frontier model with no structure.
The era of "type prompt, accept suggestion" is over. Agentic coding is about designing workflows where AI handles execution and humans handle judgment.
These 8 patterns are your starting kit. Adapt them to your stack, refine them with your team, and watch your shipping velocity transform.
Which pattern are you most excited to try? Share your AGENTS.md setup in the comments — I'd love to see how different teams structure their AI coding workflows.
Top comments (0)