Anatomy of System Prompts
Context Injection & Dynamic Prompts
Static prompts are templates; dynamic prompts are living systems. Context injection transforms generic instructions into situation-aware assistants.
What is Context Injection?
Context injection is the practice of inserting runtime information into system prompts:
Static: "You are a coding assistant."
Dynamic: "You are a coding assistant working on {{project_name}},
a {{framework}} project in {{language}}. The user is
{{username}} with {{permission_level}} access."
Context Categories
1. Environment Context
Information about the execution environment:
<environment>
<working_directory>/Users/dev/my-project</working_directory>
<platform>darwin</platform>
<os_version>Darwin 24.6.0</os_version>
<shell>zsh</shell>
<node_version>20.10.0</node_version>
<python_version>3.12.1</python_version>
</environment>
2. User Context
Information about the current user:
<user>
<id>user_12345</id>
<name>Alice Developer</name>
<role>senior_engineer</role>
<preferences>
<language>typescript</language>
<style>functional</style>
<verbosity>concise</verbosity>
</preferences>
</user>
3. Project Context
Information about the codebase:
<project>
<name>my-saas-app</name>
<framework>Next.js 15</framework>
<language>TypeScript</language>
<package_manager>pnpm</package_manager>
<structure>
- src/app (App Router)
- src/components
- src/lib
- prisma/schema.prisma
</structure>
</project>
4. Conversation Context
Information about the current interaction:
<conversation>
<message_count>12</message_count>
<current_task>implementing user authentication</current_task>
<files_modified>
- src/lib/auth.ts
- src/app/api/auth/route.ts
</files_modified>
<pending_actions>
- Run tests
- Update documentation
</pending_actions>
</conversation>
Real-World Context Patterns
Cursor's Context Injection
Cursor injects rich codebase context:
<codebase_context>
Recently opened files:
- src/components/Button.tsx (modified 2 min ago)
- src/hooks/useAuth.ts (modified 5 min ago)
Symbols in scope:
- Button: React.FC<ButtonProps>
- useAuth: () => AuthContext
- api: AxiosInstance
Related files (by import graph):
- src/types/auth.ts
- src/lib/api-client.ts
</codebase_context>
Claude Code's Context Injection
Claude Code includes execution state:
<session_context>
<git_status>
branch: feature/auth
staged: 2 files
unstaged: 1 file
untracked: 0 files
</git_status>
<recent_commands>
- npm test (exit: 1, 3 failures)
- npm run lint (exit: 0)
</recent_commands>
<active_todos>
- Fix test failures in auth.test.ts
- Update README with new API docs
</active_todos>
</session_context>
Windsurf's Memory Context
Windsurf injects learned preferences:
<memories>
<memory importance="high">
User prefers Tailwind CSS for styling
</memory>
<memory importance="medium">
Project uses PostgreSQL with Prisma ORM
</memory>
<memory importance="low">
User likes detailed commit messages
</memory>
</memories>
Context Injection Patterns
Pattern 1: Structured XML/JSON
<context type="environment">
<key>value</key>
</context>
Pros: Easy to parse, clear boundaries Cons: Verbose, consumes tokens
Pattern 2: Natural Language
The user is working on a Next.js project called "my-app"
located at /Users/dev/my-app. They prefer TypeScript and
use pnpm as their package manager.
Pros: Model-friendly, flexible Cons: Harder to update programmatically
Pattern 3: Key-Value Pairs
PROJECT_NAME: my-app
FRAMEWORK: Next.js 15
LANGUAGE: TypeScript
PACKAGE_MANAGER: pnpm
Pros: Compact, scannable Cons: Limited structure
Dynamic Prompt Assembly
Production systems assemble prompts programmatically:
function buildSystemPrompt(context: Context): string {
const sections = [
buildIdentity(context.model),
buildCapabilities(context.tools),
buildEnvironment(context.env),
buildProjectContext(context.project),
buildUserContext(context.user),
buildGuidelines(context.rules),
buildConstraints(context.limits),
];
return sections.join('\n\n');
}
Token Budget Management
Context injection requires careful token management:
| Context Type | Typical Tokens | Priority |
|---|---|---|
| Core Identity | 200-500 | Critical |
| Tool Definitions | 1,000-3,000 | Critical |
| Environment | 100-300 | High |
| Project Structure | 500-2,000 | High |
| Recent Files | 1,000-5,000 | Medium |
| Conversation History | Variable | Medium |
| Memories | 200-1,000 | Low |
Pro Tip: Use tiered context loading—inject essential context always, and add detailed context only when relevant to the task.
Context Freshness
Stale context causes errors. Production systems implement refresh strategies:
const contextRefreshRules = {
environment: 'on_session_start',
git_status: 'before_each_command',
file_contents: 'on_file_change',
memories: 'on_session_start',
conversation: 'always_current',
};
Next module: We'll dive into specific patterns from AI coding assistants like Cursor, Windsurf, and Claude Code. :::