AI & Agentic Coding
AI coding assistants have fundamentally changed how software is written. This guide covers how to work effectively with AI agents โ from prompting strategies to building production AI systems.
What Are AI Coding Agents?โ
An AI coding agent is an AI model that can:
- Read and write code
- Execute commands and tests
- Browse documentation
- Use tools (file search, web search, code execution)
- Iterate autonomously on a task
Unlike a simple chatbot, an agent can take actions โ editing files, running tests, making API calls โ and reason about the results.
Current State of the Field (2025)โ
| Tool | Provider | Best For |
|---|---|---|
| Claude Code | Anthropic | Full codebase understanding, complex refactors, agentic tasks |
| GitHub Copilot | GitHub/OpenAI | Inline code completion in IDEs |
| Cursor | Cursor AI | AI-first IDE experience |
| Devin | Cognition | Fully autonomous software engineering |
| Gemini Code Assist | Google Cloud integration |
Claude Code: The CLI Agentโ
Claude Code is Anthropic's official CLI tool that runs in your terminal and has access to your entire codebase.
Getting Startedโ
# Install Claude Code
npm install -g @anthropic-ai/claude-code
# Run in your project directory
cd your-project
claude
What Claude Code Can Doโ
- Understand your entire codebase โ reads all files, understands relationships
- Edit files โ makes precise changes, not just suggestions
- Run commands โ executes tests, builds, linters
- Git operations โ commits, creates branches, PRs
- Web search โ looks up documentation and APIs
- Multi-step tasks โ works autonomously on complex features
Effective Prompting for Code Agentsโ
The quality of your output depends heavily on how you communicate.
โ Good Promptsโ
Refactor the authentication module in src/auth/ to use JWT tokens
instead of sessions. The current implementation is in src/auth/session.ts.
Make sure to:
1. Update the login endpoint to return a JWT
2. Add a token refresh endpoint
3. Update the middleware in src/middleware/auth.ts
4. Keep backward compatibility for 30 days (feature flag)
5. Add tests for the new endpoints
I'm getting this error when running `npm test`:
[paste error]
Look at the failing test in src/__tests__/user.test.ts and fix the
underlying issue in the code (not just the test).
โ Weak Promptsโ
Fix my code.
Make it better.
Add authentication.
Key Principles for Agent Promptingโ
- Be specific about scope โ Tell the agent exactly which files/functions to touch
- Define success criteria โ "Tests should pass", "The API should return X"
- Provide context โ Error messages, expected behavior, relevant code snippets
- Break down complex tasks โ Multiple focused prompts > one vague prompt
- Iterate โ Start with a small piece, verify it works, then expand
Prompt Engineering for Codeโ
Zero-Shot vs Few-Shotโ
Zero-shot: Just describe the task
Write a function that validates an email address.
Few-shot: Show examples
Write a function that validates common inputs.
Examples:
- validateEmail('a@b.com') โ true
- validateEmail('not-an-email') โ false
- validatePhone('+1-555-1234') โ true
- validatePhone('abc') โ false
Now implement both validation functions.
Few-shot prompting consistently produces better, more aligned outputs.
Chain-of-Thought Promptingโ
Ask the model to reason step-by-step before writing code:
Before implementing this function, think through:
1. What edge cases might break this?
2. What's the time complexity of the naive approach?
3. Can we do better?
Then implement: a function to find the kth largest element in an array.
Structured Output Requestsโ
Review this code and respond in this format:
## Bugs Found
[list any bugs]
## Security Issues
[list any security concerns]
## Performance Issues
[list any performance concerns]
## Suggested Improvements
[list improvements, with code examples]
Code to review:
[paste code]
Building with the Claude APIโ
Setupโ
npm install @anthropic-ai/sdk
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
Basic Messageโ
const message = await client.messages.create({
model: 'claude-opus-4-6',
max_tokens: 1024,
messages: [
{
role: 'user',
content: 'Explain closures in JavaScript with an example.',
},
],
});
console.log(message.content[0].text);
System Promptโ
const message = await client.messages.create({
model: 'claude-opus-4-6',
max_tokens: 2048,
system: `You are an expert JavaScript teacher. You explain concepts clearly
with practical examples. Always include runnable code snippets.`,
messages: [
{ role: 'user', content: 'How does the event loop work?' },
],
});
Streaming Responsesโ
const stream = await client.messages.stream({
model: 'claude-opus-4-6',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Write a React todo app.' }],
});
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta') {
process.stdout.write(chunk.delta.text);
}
}
Tool Use (Function Calling)โ
Tool use lets Claude call external functions โ search the web, query a database, execute code, etc.
const tools = [
{
name: 'search_code',
description: 'Search the codebase for a function or class name',
input_schema: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'The search query (function name, class name, etc.)',
},
file_pattern: {
type: 'string',
description: 'Optional glob pattern like "src/**/*.ts"',
},
},
required: ['query'],
},
},
{
name: 'run_tests',
description: 'Run the test suite and return the results',
input_schema: {
type: 'object',
properties: {
test_file: {
type: 'string',
description: 'Optional specific test file to run',
},
},
required: [],
},
},
];
// Agentic loop
async function agentLoop(initialMessage) {
const messages = [{ role: 'user', content: initialMessage }];
while (true) {
const response = await client.messages.create({
model: 'claude-opus-4-6',
max_tokens: 4096,
tools,
messages,
});
messages.push({ role: 'assistant', content: response.content });
if (response.stop_reason === 'end_turn') {
// Claude is done โ extract final text response
return response.content.find(b => b.type === 'text')?.text;
}
if (response.stop_reason === 'tool_use') {
// Claude wants to use a tool
const toolResults = [];
for (const block of response.content) {
if (block.type !== 'tool_use') continue;
let result;
if (block.name === 'search_code') {
result = await searchCodebase(block.input.query, block.input.file_pattern);
} else if (block.name === 'run_tests') {
result = await runTestSuite(block.input.test_file);
}
toolResults.push({
type: 'tool_result',
tool_use_id: block.id,
content: JSON.stringify(result),
});
}
messages.push({ role: 'user', content: toolResults });
}
}
}
// Usage
const result = await agentLoop(
'Find all places where we make API calls without error handling, then fix them.'
);
Model Context Protocol (MCP)โ
MCP is an open standard (created by Anthropic) that lets AI agents connect to any data source or tool using a unified protocol.
What MCP Doesโ
[Claude] โโ [MCP Client] โโ [MCP Server] โโ [Your Tool/Database/API]
MCP servers expose:
- Tools โ actions Claude can take (run a query, send an email, create a file)
- Resources โ data Claude can read (database contents, API responses, files)
- Prompts โ pre-built prompt templates
Setting Up MCP with Claude Codeโ
In your Claude Code settings (~/.claude/settings.json):
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"POSTGRES_URL": "postgresql://localhost/mydb"
}
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "your-token"
}
},
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/path/to/your/project"
]
}
}
}
Popular MCP Serversโ
| MCP Server | What It Does |
|---|---|
@modelcontextprotocol/server-filesystem | Read/write local files |
@modelcontextprotocol/server-github | GitHub repos, issues, PRs |
@modelcontextprotocol/server-postgres | Query PostgreSQL |
@modelcontextprotocol/server-sqlite | Query SQLite |
@modelcontextprotocol/server-brave-search | Web search |
@modelcontextprotocol/server-puppeteer | Browser automation |
Building a Custom MCP Serverโ
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new Server(
{ name: 'my-api-server', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
// Register a tool
server.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'get_user',
description: 'Fetch a user by ID from the API',
inputSchema: {
type: 'object',
properties: {
userId: { type: 'string', description: 'The user ID' },
},
required: ['userId'],
},
},
],
}));
// Handle tool calls
server.setRequestHandler('tools/call', async (request) => {
if (request.params.name === 'get_user') {
const { userId } = request.params.arguments;
const user = await fetchUserFromAPI(userId);
return {
content: [{ type: 'text', text: JSON.stringify(user) }],
};
}
});
// Start the server
const transport = new StdioServerTransport();
await server.connect(transport);
Agentic Workflows: Patterns & Best Practicesโ
Pattern 1: Plan โ Execute โ Verifyโ
async function codeFeature(featureDescription) {
// Step 1: Plan
const plan = await claude.message(`
Create a detailed implementation plan for: ${featureDescription}
Format as:
1. Files to create/modify
2. Step-by-step implementation order
3. Test cases to add
4. Potential edge cases
`);
// Step 2: Execute each step
for (const step of parseSteps(plan)) {
await claude.message(`
Execute this step: ${step}
Context: ${featureDescription}
Previous work: ${getWorkSummary()}
`);
}
// Step 3: Verify
const testResult = await runTests();
if (!testResult.passed) {
await claude.message(`
Tests failed. Error: ${testResult.error}
Fix the issue without breaking other tests.
`);
}
}
Pattern 2: Parallel Sub-Agentsโ
For large tasks, spawn multiple agents working in parallel:
async function codeReview(files) {
// Review multiple files in parallel
const reviews = await Promise.all(
files.map(file =>
claude.message(`
Review ${file.path} for:
- Bugs
- Security issues
- Performance problems
- Code style
Content:
${file.content}
`)
)
);
// Synthesize findings
return claude.message(`
Summarize these code reviews and prioritize issues:
${reviews.join('\n\n---\n\n')}
`);
}
Pattern 3: Human-in-the-Loopโ
For risky operations, pause and confirm before proceeding:
async function deployment(environment) {
const plan = await generateDeploymentPlan(environment);
// Show plan to human
console.log('Deployment plan:', plan);
const confirmed = await promptUser('Proceed with deployment? (yes/no)');
if (confirmed === 'yes') {
await executeDeployment(plan);
}
}
AI-Assisted Interview Prepโ
You can use AI to prepare for your own technical interviews:
Mock Coding Interviewโ
I'm preparing for a technical interview. Act as a senior engineer
interviewer at a top tech company. Give me a medium-difficulty
LeetCode-style problem, then guide me through the solution if I
get stuck. Evaluate my approach and give feedback at the end.
Mock System Design Interviewโ
Act as a system design interviewer. Give me a system design
question (e.g., "Design Uber"). Ask me clarifying questions as
I explain my design, push back on weak areas, and evaluate my
final design. Start the interview.
Code Review Practiceโ
Here's a piece of code I wrote [paste code].
Review it as if you're a senior engineer in a code review.
Be direct about issues. Don't just say "good job."
Behavioral Interview Coachโ
I'm practicing behavioral interviews for a senior engineer role.
Ask me 5 behavioral questions that companies like Google and Meta
commonly ask. After each answer, give me specific feedback using
the STAR framework and tell me what was strong and what needs work.
Resourcesโ
- Claude API Documentation โ Official API docs
- Model Context Protocol โ MCP standard and server registry
- Claude Code Documentation โ CLI tool docs
- Anthropic Cookbook โ Code recipes and patterns
- Building Effective Agents โ Anthropic's guide