I Built a 3-Tier AI Coding Context Protocol That Cut My Rejection Rate by 60% — Here’s the Exact Setup
You’ve been there. You ask your AI coding tool to refactor a function, and it spits back something that looks right but feels… wrong. The variable names don’t match your codebase. The error handling pattern is inconsistent. It imports a library nobody on your team uses.
I was seeing this constantly. 34% of AI-generated PRs were getting rejected in code review. Not because the logic was broken, but because the code didn’t *fit*.
Why You Should Hire Vietnamese Developers: A CTO’s Guide to Offshore Success
4. What time zone is best for collaboration with Vietnam? If your team is in the US, the… ...
So I built a context protocol. Three tiers. It dropped my rejection rate to 13% in six weeks. Here’s exactly how it works.
Why Your AI Coding Tool Writes Alien Code
Most developers feed their AI tool a single prompt. Maybe they paste a function signature. Maybe they reference a file.
Agentic AI for Developers: When AI Stops Answering and Starts Acting for You
Agentic AI for developers is changing how we build software. Instead of just chatting and answering, these agents… ...
That’s not enough.
Your codebase has unwritten rules. The way you handle nulls. The logging framework you standardized on six months ago. The exact import style your linter enforces. Your AI tool doesn’t know any of this unless you *tell* it.
And here’s the kicker: telling it once isn’t enough. You need a system.
The 3-Tier Context Protocol
I split context into three layers. Each layer has a specific purpose and a specific lifespan.
| Tier | Scope | Lifespan | Content |
|---|---|---|---|
| Global | Entire codebase | Permanent | Architecture, conventions, tech stack |
| Module | Single directory | Per-session | Module-specific patterns, data models |
| Task | Single function | Per-request | Exact spec, edge cases, constraints |
Let me walk through each one.
Tier 1: Global Context — The Constitution
This is your codebase’s constitution. It lives in a single Markdown file checked into your repo. Every AI coding tool reads it first.
Here’s the file I use. It’s called `CONTEXT_GLOBAL.md`:
markdown
# Global Development Context
## Architecture
- Monorepo with pnpm workspaces
- Next.js 14 app router for frontend
- Fastify for backend API services
- PostgreSQL with Prisma ORM
## Code Conventions
- TypeScript strict mode enabled
- Prefer `const` over `let` and `function`
- Use `zod` for runtime validation
- All functions must have explicit return types
- Error handling: return `Result` union types, never throw
- Logging: use `pino` via shared logger instance
## Testing
- Vitest for unit tests
- Playwright for e2e
- Minimum 80% coverage on new code
- Test files co-located with source files
## Git Workflow
- Conventional commits enforced
- Feature branches off `main`
- PRs require 1 approval and passing CI
Don’t overthink this. Start with 15-20 rules. You’ll add more as you catch your AI tool making the same mistake twice.
Tier 2: Module Context — The Neighborhood Rules
Global context is too broad for specific modules. The database layer has different patterns than the UI layer. The payment module has its own validation quirks.
I create `CONTEXT_MODULE.md` files in each major directory. Here’s an example from our payment module:
markdown
# Payment Module Context
## Patterns
- All payment amounts stored as integers (cents)
- Currency codes in ISO 4217 format
- Stripe SDK v5, never v4 patterns
- Webhook handlers must be idempotent
## Data Models
- Payment: { id, amount, currency, status, userId, createdAt }
- Refund: links to Payment via paymentId
- Status transitions: pending -> processing -> completed|failed
## Edge Cases
- Zero-amount payments are valid for trials
- Refunds cannot exceed original payment amount
- Duplicate webhooks must return 200 without reprocessing
Pro tip: Write these after a code review where you rejected AI-generated code. The pattern of what you rejected tells you exactly what to document.
Tier 3: Task Context — The Exact Spec
This is where most developers fail. They ask the AI tool to “add a payment method” without specifying the exact shape of the input, the error messages, or the loading states.
I use a structured prompt template:
## Task: [Brief description]
## Input
- Type: [exact TypeScript type]
- Validation rules: [zod schema or list]
## Output
- Return type: [exact type]
- Success response shape: [JSON]
- Error response shape: [JSON]
## Constraints
- Must handle: [list of edge cases]
- Must NOT: [list of forbidden patterns]
- Performance: [latency, memory limits]
## Context files
- [Links to relevant files in codebase]
Honestly, this tier alone cut my rejection rate by 40%. The other two tiers handle the remaining 20%.
The Workflow That Makes It Stick
A protocol is useless if nobody follows it. Here’s how I integrated this into our team’s workflow — including our developers in Vietnam.
Step 1: Bootstrap the AI session
Every time I start a new AI coding session, I paste the global context file first. Then the module context. Then the task spec.
It takes 30 seconds. It saves hours.
Step 2: Use a pre-commit hook
I wrote a simple pre-commit hook that checks if `CONTEXT_GLOBAL.md` exists in the repo root. If it doesn’t, the commit fails. This forces everyone to maintain it.
bash
#!/bin/bash
# .git/hooks/pre-commit
if [ ! -f CONTEXT_GLOBAL.md ]; then
echo "ERROR: CONTEXT_GLOBAL.md is required"
exit 1
fi
Step 3: Review the AI’s output against the context
During code review, I check three things:
- Does the code follow global conventions?
- Does it respect module-specific patterns?
- Does it handle all task-level edge cases?
If any fail, I update the context files instead of just fixing the code. This prevents the same mistake from happening again.
Real Results from Our Vietnam-Based Team
We’ve been running this protocol for three months with our team in Ho Chi Minh City and Can Tho. The numbers speak for themselves:
- PR rejection rate: 34% → 13%
- Average review time: 45 minutes → 18 minutes
- AI-generated code acceptance: 66% → 87%
- Context file updates: 23 total (across 4 modules)
But here’s the metric that matters most: our junior developers in Vietnam are now writing context files for their own modules. They understand the codebase’s DNA better than the AI ever could.
The One Thing Most Developers Get Wrong
I see teams spend weeks crafting the perfect global context file, then never update it. Your codebase evolves. Your context must evolve with it.
Set a monthly review reminder. Go through each `CONTEXT_MODULE.md` and ask: “Is this still accurate? What patterns have changed? What edge cases did we discover?”
If you don’t update the context, your AI tool will keep writing last quarter’s code.
Why This Beats Prompt Engineering
There’s a lot of noise about “prompt engineering” — crafting the perfect one-shot prompt. I’ve tried it. It doesn’t scale.
A context protocol is repeatable, version-controlled, and team-shareable. Your new hire reads `CONTEXT_GLOBAL.md` and understands your codebase in 10 minutes. Your AI tool reads it and produces code that looks like *your* team wrote it.
Prompt engineering is art. Context engineering is infrastructure.
Frequently Asked Questions
How do I handle conflicting context between modules?
Use the nearest `CONTEXT_MODULE.md` as the source of truth. If a module doesn’t have one, fall back to global context. We also have a `CONTEXT_OVERRIDE.md` for rare cases where a module needs to break a global rule — but we limit this to 3 overrides max.
What if my AI coding tool doesn’t support reading files?
Most modern tools (Claude Code, Cursor, Copilot Chat) can read files if you reference them. I use a simple `cat CONTEXT_GLOBAL.md | pbcopy` command to copy the content. For tools that support custom instructions, I paste the global context into the settings.
Should I include the context files in my repo’s `.gitignore`?
No. Keep them in version control. They’re documentation. When someone asks “why did we do it this way?” the context file has the answer. We keep ours in a `docs/context/` directory at the repo root.
How often should I update the global context file?
Monthly minimum. But honestly, update it whenever you reject AI-generated code during review. That’s a signal that your context is incomplete. We’ve averaged 8 updates per month during our first quarter.
Related reading: Vietnam Outsourcing: The Smartest Offshore Play for Tech Leaders in 2025
Related reading: Outsourcing Software Development: Why Vietnam is the Smartest Bet in 2025