c function runSecurityAudit(request: AuditRequest) {
// Operator-level directive: Higher authority than user messages.
// Enforces JSON output and restricts scope.
const operatorDirectives = You are the SecurityAuditor. Your sole purpose is to analyze code for vulnerabilities. CONSTRAINTS: - Output ONLY valid JSON matching the schema. - Do not include markdown formatting or prose. - If the input is not code, return {"error": "Invalid input"}. ;
const response = await apiClient.messages.create({
model: 'claude-3-5-sonnet-20241022',
system: operatorDirectives,
max_tokens: 1024,
messages: [
{
role: 'user',
content: Analyze this ${request.language} code:\n${request.codeSnippet},
},
],
});
if (response.stop_reason === 'end_turn') {
const textContent = response.content.find(
(block) => block.type === 'text'
);
return textContent ? JSON.parse(textContent.text) : null;
}
throw new Error(Unexpected stop reason: ${response.stop_reason});
}
#### 2. Tool Orchestration Loop
Anthropic's tool use requires a deterministic loop based on `stop_reason`. The model returns `tool_use` when it requires external data, allowing the application to execute the tool and feed results back via `tool_result` blocks.
```typescript
interface ToolDefinition {
name: string;
description: string;
input_schema: {
type: 'object';
properties: Record<string, any>;
required: string[];
};
}
const availableTools: ToolDefinition[] = [
{
name: 'fetch_inventory',
description: 'Retrieve stock levels for a product SKU.',
input_schema: {
type: 'object',
properties: {
sku: { type: 'string', description: 'Product SKU code.' },
},
required: ['sku'],
},
},
];
async function executeToolCall(toolName: string, input: any): Promise<any> {
// Mock executor
if (toolName === 'fetch_inventory') {
return { sku: input.sku, quantity: 42, status: 'in_stock' };
}
return { error: 'Unknown tool' };
}
async function runAgentLoop(userQuery: string) {
let messages: Anthropic.MessageParam[] = [
{ role: 'user', content: userQuery },
];
let maxIterations = 5;
for (let i = 0; i < maxIterations; i++) {
const response = await apiClient.messages.create({
model: 'claude-3-5-sonnet-20241022',
system: 'You are an InventoryAssistant. Use tools to answer queries.',
messages,
tools: availableTools,
max_tokens: 1024,
});
if (response.stop_reason === 'end_turn') {
const text = response.content.find((b) => b.type === 'text');
return text?.text || 'No response generated.';
}
if (response.stop_reason === 'tool_use') {
messages.push({
role: 'assistant',
content: response.content,
});
const toolResults: Anthropic.ToolResultBlockParam[] = [];
for (const block of response.content) {
if (block.type === 'tool_use') {
const result = await executeToolCall(block.name, block.input);
toolResults.push({
type: 'tool_result',
tool_use_id: block.id,
content: JSON.stringify(result),
});
}
}
messages.push({ role: 'user', content: toolResults });
}
}
return 'Agent loop exceeded maximum iterations.';
}
3. Long-Context Strategy: The Sandwich Technique
With a 200K token context window, you can pass entire codebases or lengthy documents. However, models exhibit a "lost in the middle" phenomenon where attention degrades for content in the center of long contexts. The solution is the Sandwich Technique: place critical instructions at the beginning and end of the prompt.
async function analyzeCodebase(repoContent: string) {
const systemPrompt = `
You are an ArchitectReviewer.
CRITICAL: Identify the primary entry point and list all public APIs.
Output format: Markdown list.
`;
// Sandwich: Instructions at start and end.
const userContent = `
[START OF REPOSITORY]
${repoContent}
[END OF REPOSITORY]
REMINDER: As instructed, list the entry point and public APIs.
Do not summarize the code; focus only on the architectural structure.
`;
const response = await apiClient.messages.create({
model: 'claude-3-5-sonnet-20241022',
system: systemPrompt,
messages: [{ role: 'user', content: userContent }],
max_tokens: 2048,
});
return response.content[0].type === 'text'
? response.content[0].text
: '';
}
4. Vision Integration
For image analysis, encode images as base64 and include them in the message content array. This allows multimodal reasoning without external retrieval steps.
import fs from 'fs';
import path from 'path';
async function analyzeDiagram(imagePath: string) {
const imageBuffer = fs.readFileSync(path.resolve(imagePath));
const base64Image = imageBuffer.toString('base64');
const response = await apiClient.messages.create({
model: 'claude-3-5-sonnet-20241022',
system: 'You are a DiagramParser. Describe the flow and components.',
messages: [
{
role: 'user',
content: [
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/png',
data: base64Image,
},
},
{
type: 'text',
text: 'Explain the data flow shown in this diagram.',
},
],
},
],
max_tokens: 1024,
});
return response.content[0].type === 'text'
? response.content[0].text
: '';
}
Pitfall Guide
-
The "Middle Void" Trap
- Explanation: When passing massive context, critical instructions placed in the middle of the text are often ignored due to attention dilution.
- Fix: Always use the Sandwich Technique. Repeat key constraints at the end of the user message.
-
Token Budget Blowouts
- Explanation: Setting
max_tokens too high can cause the model to ramble, increasing latency and cost without adding value.
- Fix: Estimate output length based on the task. Use
max_tokens: 1024 for analysis and max_tokens: 256 for classification. Monitor usage.output_tokens to tune budgets.
-
Tool Schema Rigidity Errors
- Explanation: Defining tool inputs without strict types or descriptions leads to malformed arguments and execution failures.
- Fix: Use JSON Schema with explicit
type and description fields. Validate tool inputs in your executor before calling external services.
-
System Prompt Leakage
- Explanation: Placing system instructions inside the
messages array with role: 'user' or role: 'assistant' breaks the hierarchy and reduces adherence.
- Fix: Always use the dedicated
system parameter. Treat it as the operator contract, not part of the conversation history.
-
Streaming State Loss
- Explanation: Failing to accumulate text chunks correctly during streaming results in fragmented output or missing final tokens.
- Fix: Use a string accumulator. Listen for
content_block_delta events and append text. Ensure you handle message_stop to finalize usage stats.
-
Model Mismatch for Task Complexity
- Explanation: Using Opus for simple extraction or Haiku for complex reasoning wastes resources or degrades quality.
- Fix: Route tasks dynamically. Use Haiku for classification/extraction, Sonnet for general coding/analysis, and Opus only for high-stakes reasoning.
-
Ignoring stop_reason
- Explanation: Assuming the response always ends with
end_turn can cause crashes when the model stops due to max_tokens or tool_use.
- Fix: Always switch on
stop_reason. Handle tool_use by executing tools, and handle max_tokens by warning the user or retrying with a higher limit.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Model | Why | Cost Impact |
|---|
| Real-time Chat / Classification | claude-3-5-haiku | Fastest latency; sufficient for simple tasks. | Lowest cost ($0.80/$4 per 1M). |
| Code Generation / Analysis | claude-3-5-sonnet | Best balance of capability and speed. | Moderate cost ($3/$15 per 1M). |
| Legal Review / Research | claude-3-opus | Highest reasoning capability for nuanced tasks. | Highest cost ($15/$75 per 1M). |
| Full Repo Analysis | claude-3-5-sonnet | 200K context handles large inputs; strong coding skills. | Moderate cost; avoids chunking overhead. |
Configuration Template
Use this TypeScript interface to standardize Anthropic configurations across your codebase.
export interface AnthropicConfig {
apiKey: string;
defaultModel: 'claude-3-5-sonnet-20241022' | 'claude-3-5-haiku-20241022' | 'claude-3-opus-20240229';
maxTokens: number;
temperature: number;
systemPrompt: string;
tools?: Array<{
name: string;
description: string;
input_schema: any;
}>;
retryConfig?: {
maxRetries: number;
backoffMs: number;
};
}
export const defaultConfig: AnthropicConfig = {
apiKey: process.env.ANTHROPIC_API_KEY || '',
defaultModel: 'claude-3-5-sonnet-20241022',
maxTokens: 1024,
temperature: 0.0,
systemPrompt: 'You are a helpful assistant.',
retryConfig: {
maxRetries: 3,
backoffMs: 1000,
},
};
Quick Start Guide
- Install SDK: Run
npm install @anthropic-ai/sdk.
- Set Environment: Export
ANTHROPIC_API_KEY with your API key.
- Initialize Client: Create a new
Anthropic instance with your key.
- Run Sonnet Call: Execute a
messages.create request with claude-3-5-sonnet-20241022 to verify connectivity.
- Add System Prompt: Refine your system prompt to enforce constraints and test hierarchy adherence.