
















When I onboard a new developer, I don't just point them at the codebase and say “go.” I walk them through our conventions. I show them examples of code we consider good. I explain why we made certain architectural choices—why we use Fastify instead of Express, why services are functional instead of class-based, why validation happens at the route level. Only after this context-setting do I expect them to contribute code that fits.
AI coding assistants need the same onboarding.
Many developers experience what might be called a “Frustration Loop” with AI assistants: generate code, find it doesn't fit the codebase, regenerate with corrections, repeat until giving up or accepting heavily-modified output. I have come to believe this friction stems not from AI capability, but from a missing step—we ask AI to contribute without first sharing the context it needs.
This article explores what I call Knowledge Priming—the practice of sharing curated project context with AI before asking it to generate code.
The core insight is simple: AI assistants are like highly capable but entirely contextless collaborators. They can work faster than any human, but they know nothing about a specific project's conventions, constraints, or history. Without context, they default to generic patterns that may or may not fit.
Here is what typically happens when asking AI to generate code without priming:
Request: “Create a UserService that handles authentication”
AI generates 200 lines of code using:
utils/auth.js helper (the convention is lib/services/) The code works. It is syntactically correct. It might even pass basic tests. But it is completely wrong for the codebase.
Why? Because AI defaults to its training data—a blend of millions of repositories, tutorials, and Stack Overflow answers. It generates the “average” solution from the internet, not the right solution for a specific team.
This is exactly what would happen if I asked a new hire to write code on Day 1 without any onboarding. They would draw on their prior experience—which may or may not match our conventions.
I find it helpful to think of AI knowledge in three layers, ordered by priority:
The hierarchy matters. When priming documents are provided, the instruction is essentially: “Ignore the generic internet patterns. Here is how this project works.” And in my experience, AI does listen.
Technically, this is manual RAG (Retrieval-Augmented Generation)—filling the context window with high-value project-specific tokens that override lower-priority training data. Just as a new hire's prior habits are overridden by explicit team conventions once explained, AI's training-data defaults yield to explicit priming.
There is a mechanistic reason this works. Transformer models process context through attention mechanisms that operate, in effect, as a finite budget—every token in the context window competes for influence over the model's output. When the window is filled with generic training-data patterns, the model draws on the average of everything it has seen. When it is filled with specific, high-signal project context, those tokens attract more attention weight and steer generation toward the patterns that matter. This is why curation matters more than volume: a focused priming document does not just *add* context, it shifts the balance of what the model pays attention to.
Knowledge Priming is the practice of sharing curated documentation, architectural patterns, and version information with AI before asking it to generate code.
Think of it as the onboarding packet for a new hire:
Without priming, a request for a UserService might yield Express.js, class-based code, wrong file paths, and outdated APIs—requiring 45 minutes of fixing or a complete rewrite.
With priming, the same request might yield Fastify, functional patterns, correct file paths, and current APIs—requiring only 5 minutes of review and minor tweaks.
I cannot claim this is a validated finding, but the reasoning seems sound: explicit context should override generic defaults. My own experiments have been encouraging.
A good priming document is not a brain dump. It is a curated, structured guide that gives AI exactly what it needs—no more, no less.
I propose seven sections. Each mirrors what I would walk through when onboarding a human colleague:
What I tell a new hire: “Let me explain the big picture first.”
The big picture. What kind of application is this? What are the major components? How do they interact?
## Architecture Overview
This is a microservices-based e-commerce platform.
- API Gateway: Handles routing, auth, rate limiting
- User Service: Authentication, profiles, preferences
- Order Service: Cart, checkout, order history
- Notification Service: Email, SMS, push notifications
Services communicate via async message queues (RabbitMQ).
Each service owns its database (PostgreSQL).
What I tell a new hire: “Here's our stack—and watch out for version-specific APIs.”
Specificity matters. Version numbers matter—APIs change between versions.
## Tech Stack
- **Runtime**: Node.js 20.x (LTS)
- **Framework**: Fastify 4.x (not Express)
- **Database**: PostgreSQL 15 with Prisma ORM 5.x
- **Auth**: JWT with httpOnly cookies (not localStorage)
- **Testing**: Vitest + Testing Library (not Jest)
- **Validation**: Zod schemas (not Joi)
What I tell a new hire: “Before you search the internet, here are the docs and blogs that shaped how we think. Start here.”
Every team has trusted sources: the official documentation they actually read, but also the blog posts that influenced their architecture, the tutorials that explained things clearly, the articles that captured lessons the docs never will. Together, these form the team's shared mental model.
When AI consults curated sources first—rather than its vast, generic training data—the output aligns faster. The team's thinking is already baked in.
## Curated Knowledge
### Official Documentation
| Topic | Source | Why We Trust It |
|-------|--------|-----------------|
| Fastify routing | https://fastify.dev/docs/latest/Guides/Getting-Started | Official, matches our v4.x |
| Prisma relations | https://www.prisma.io/docs/orm/prisma-schema/data-model/relations | Authoritative for schema patterns |
### Blogs and Articles We Follow
| Concept | Source | Why It Shaped Our Thinking |
|---------|--------|---------------------------|
| Error handling patterns | [team-vetted blog URL] | Clearer than official docs, practical examples |
| Testing strategies | [team-vetted blog URL] | Influenced our test architecture |
### Internal References
| Topic | Path | What It Captures |
|-------|------|------------------|
| Error conventions | docs/error-handling.md | Our specific patterns |
| API design decisions | docs/adr/003-api-versioning.md | Decision rationale |
Keep this curated—not comprehensive. Five to ten sources that genuinely shaped how the team works.
What I tell a new hire: “Here's where things live. File placement matters.”
Where things live. File placement matters.
src/
├── lib/
│ ├── services/ # Business logic (UserService, OrderService)
│ ├── repositories/ # Database access layer
│ ├── schemas/ # Zod validation schemas
│ └── utils/ # Pure utility functions
├── routes/ # Fastify route handlers
├── middleware/ # Auth, logging, error handling
├── types/ # TypeScript type definitions
└── config/ # Environment-specific config
What I tell a new hire: “Here are the naming conventions. Consistency matters more than personal preference.”
Explicit conventions prevent style drift.
## Naming Conventions
- **Files**: kebab-case (`user-service.ts`, not `UserService.ts`)
- **Functions**: camelCase, verb-first (`createUser`, `validateToken`)
- **Types/Interfaces**: PascalCase with descriptive suffixes (`UserCreateInput`, `AuthResponse`)
- **Constants**: SCREAMING_SNAKE_CASE (`MAX_RETRY_COUNT`)
- **Boolean variables**: is/has/can prefix (`isActive`, `hasPermission`)
What I tell a new hire: “Here's an example of code we consider good. Follow this pattern.”
Show, do not just tell. Include 2-3 examples of “good code” from the codebase.
// lib/services/user-service.ts
import { prisma } from '../db/client'
import { UserCreateInput, UserResponse } from '../types/user'
import { hashPassword } from '../utils/crypto'
export async function createUser(input: UserCreateInput): Promise<UserResponse> {
const hashedPassword = await hashPassword(input.password)
const user = await prisma.user.create({
data: {
...input,
password: hashedPassword,
},
select: {
id: true,
email: true,
createdAt: true,
// Never return password
},
})
return user
}
Note: Services are pure functions, not classes. They receive dependencies via parameters when needed.
What I tell a new hire: “Here's what NOT to do. We've learned these lessons the hard way.”
Tell AI what NOT to do. This prevents common mistakes.
## Anti-patterns (Do NOT use)
- Class-based services (use functional approach)
- Express.js patterns (this project uses Fastify)
- Storing JWT in localStorage (use httpOnly cookies)
- Using any type (always define proper types)
- Putting business logic in route handlers (use services)
- Raw SQL queries (use Prisma ORM)
The most powerful approach, I believe, is treating priming as infrastructure rather than habit.
Instead of manually pasting context at the start of each session (a habit that fades), store the priming document in the repository where it applies automatically:
# Cursor
.cursor/
├── rules # Always-on project context (auto-loaded)
└── commands/
└── priming.md # Referenceable with @priming
# GitHub Copilot
.github/
└── copilot-instructions.md # Workspace-level instructions
# Claude Projects
Upload priming doc to Project Knowledge
Why infrastructure beats copy-paste:
This transforms priming from a “personal productivity hack” into “team infrastructure.” The difference between a habit that fades and a practice that persists.
Just as onboarding materials for new hires are maintained as organizational assets—not improvised each time—priming documents should be treated as first-class artifacts.
In my own experimentation, I have observed several failure modes:
| Pitfall | Alternative |
|---|---|
| Too much information: 20+ page docs overwhelm AI and dilute focus | Keep it to 1-3 pages of essential context |
| Too vague: “Modern best practices” tells AI nothing | Be specific: “Fastify 4.x, Prisma 5.x, functional services” |
| No examples: Describing patterns without showing them | Include 2-3 real code snippets from the codebase |
| Outdated content: Priming doc from 6 months ago | Review and update monthly, or when major changes happen |
| Missing anti-patterns: Telling AI what TO do but not what to AVOID | Explicitly list patterns not wanted |
One mistake is treating the priming document like comprehensive documentation. It is not. It is a cheat sheet for AI—the minimum context needed to generate aligned code.
If a priming doc is longer than 3 pages, consider:
AI can always ask follow-up questions. Start focused, expand only when needed.
Documentation rots. Every team has a graveyard of outdated wikis and stale READMEs. How to prevent a priming doc from joining them?
Treat it as code, not docs:
docs/ai-priming.mdReference, do not duplicate:
/api/schema.yaml“Update triggers:
| Trigger | Action |
|---|---|
| New framework version | Update stack section |
| New architectural pattern | Add code example |
| Repeated AI mistakes | Add anti-pattern |
| Major refactor | Review structure section |
A stale priming doc is worse than none—it teaches AI outdated patterns. But a priming doc that lives in the repo, reviewed like code, stays current by design.
Here is a condensed priming document from a project I worked on:
# Acme API - Priming Context
## Quick Overview
B2B SaaS API for inventory management. Multi-tenant, event-driven.
## Stack
- Node.js 20, Fastify 4, TypeScript 5
- PostgreSQL 15 + Prisma 5 (multi-tenant via tenantId)
- Auth: Clerk (external), JWT validation middleware
- Queue: BullMQ + Redis for async jobs
- Testing: Vitest
## Trusted Sources
### Docs
- Fastify: https://fastify.dev/docs/latest
- Prisma multi-tenancy: https://www.prisma.io/docs/orm/prisma-client/queries/multi-tenancy
### Blogs We Follow
- BullMQ patterns: [team-vetted blog on queue handling]
### Internal
- ADRs: docs/adr/ (architecture decisions)
- Error handling: docs/error-conventions.md
## Structure
src/
├── modules/ # Feature modules (users/, products/, orders/)
│ └── [module]/
│ ├── service.ts # Business logic
│ ├── routes.ts # HTTP handlers
│ ├── schema.ts # Zod schemas
│ └── types.ts # TypeScript types
├── shared/ # Cross-cutting (db, auth, queue)
└── config/ # Env config
## Patterns
- Functional services (no classes)
- All queries include `where: { tenantId }` (multi-tenant)
- Validation at route level with Zod
- Errors thrown as `AppError` with status codes
## Anti-patterns
- No classes for services
- No raw SQL (use Prisma)
- No business logic in routes
- No hardcoded tenantId
## Example Service
[Include one short example from the codebase]
Notice: It is under 50 lines. That is the target. Focused, specific, actionable.
This approach is not without costs:
I hypothesize that the payoff is greatest for non-trivial work—especially work that spans multiple sessions or involves team coordination. For a quick utility function, manual correction may be faster than maintaining context infrastructure.
Knowledge Priming is, in essence, manual RAG: filling the AI's context window with high-value, project-specific information before asking for code generation. The hypothesis is straightforward—explicit context should override generic defaults, resulting in output that fits the codebase rather than “the average of the internet.”
My current thinking is that the key shift is treating context as infrastructure (versioned files in the repo) rather than habit (copy-pasting at session start). Infrastructure persists; habits fade.
This is the foundation for everything else. Design-first conversations are more productive when AI already understands the architecture. Custom commands work better when AI knows the conventions. The investment in priming compounds.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。