# Closer Code - Anthropic SDK
> Closer Code `@anthropic-ai/sdk` AI API
---
##
1. [](#1-)
2. [](#2-)
3. [](#3-)
4. [API ](#4-api-)
5. [ (Extended Thinking)](#5--extended-thinking)
6. [](#6-)
7. [](#7-)
8. [](#8-)
---
## 1.
### 1.1
```bash
npm install @anthropic-ai/sdk
```
### 1.2 5
#### closer_code
```javascript
// fetch...
const response = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey,
'anthropic-version': '2023-06-01'
},
body: JSON.stringify(requestBody)
});
// ...
```
#### SDK
```typescript
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY
});
const message = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
messages: [{ role: 'user', content: 'Hello, Claude!' }]
});
console.log(message.content);
```
****
- HTTP
-
-
- 80%
---
## 2.
### 2.1
| | | SDK |
|------|---------|---------|
| **** | ~40 | ~5 |
| **SSE ** | | |
| **** | | |
| **** | | |
#### closer_code
```javascript
// ai-client.js: streamFetch
async function streamFetch(url, options, onChunk) {
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.text();
throw new Error(`API error: ${response.status} - ${error}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.trim().startsWith('data: ')) {
const data = line.trim().slice(6);
if (data === '[DONE]') continue;
try {
const parsed = JSON.parse(data);
onChunk(parsed);
} catch (e) {
//
}
}
}
}
}
```
#### SDK
```typescript
const stream = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
messages: [{ role: 'user', content: 'Hello!' }],
stream: true
});
for await (const event of stream) {
console.log(event.type);
}
```
**87.5%**
### 2.2 Tool Use
| | | SDK |
|------|---------|---------|
| **** | schema | schema |
| **** | | |
| **** | | |
| **** | ~100 | ~20 |
#### closer_code
```javascript
//
async function executeTools(aiClient, messages, tools) {
let currentMessages = [...messages];
while (true) {
const response = await aiClient.chat(currentMessages, { tools });
const toolResults = [];
for (const block of response.content) {
if (block.type === 'tool_use') {
const result = await executeTool(block.name, block.input);
toolResults.push({
role: 'tool',
toolUseId: block.id,
content: result
});
}
}
if (toolResults.length === 0) {
return response;
}
currentMessages.push({
role: 'assistant',
content: response.content
});
currentMessages.push(...toolResults);
}
}
```
#### SDK toolRunner
```typescript
import { z } from 'zod';
import { betaZodTool } from '@anthropic-ai/sdk/helpers/beta/zod';
const weatherTool = betaZodTool({
name: 'get_weather',
description: '',
inputSchema: z.object({
location: z.string().describe('')
}),
run: async (input) => {
//
return `${input.location} 20C`;
}
});
const finalMessage = await client.beta.messages.toolRunner({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
messages: [{ role: 'user', content: '' }],
tools: [weatherTool]
});
```
**80%**
### 2.3
| | | SDK |
|------|---------|---------|
| **** | | |
| **** | | |
| **** | | |
#### closer_code
```javascript
// ai-client.js:
const formattedMessages = messages.map(m => {
if (m.role === 'tool') {
return {
role: 'user',
content: [{
type: 'tool_result',
tool_use_id: m.toolUseId,
content: m.content
}]
};
}
return {
role: m.role,
content: m.content
};
});
```
#### SDK
```typescript
import Anthropic from '@anthropic-ai/sdk';
// IDE
const message: Anthropic.MessageParam = {
role: 'user',
content: 'Hello'
};
//
const toolResult: Anthropic.ToolResultBlockParam = {
type: 'tool_result',
tool_use_id: 'toolu_xxx',
content: ''
};
```
---
## 3.
### 3.1 AnthropicClient
#### 1 SDK
```bash
npm install @anthropic-ai/sdk
```
#### 2
**src/ai-client.js**
```javascript
export class AnthropicClient {
constructor(config) {
this.apiKey = config.apiKey;
this.baseURL = config.baseURL || 'https://api.anthropic.com';
this.model = config.model || 'claude-sonnet-4-5-20250929';
this.maxTokens = config.maxTokens || 8192;
}
async chat(messages, options = {}) {
// ...
}
}
```
**src/ai-client-sdk.js**
```typescript
import Anthropic from '@anthropic-ai/sdk';
export class AnthropicClientSDK {
private client: Anthropic;
private model: string;
private maxTokens: number;
constructor(config: { apiKey: string; model?: string; maxTokens?: number }) {
this.client = new Anthropic({
apiKey: config.apiKey
});
this.model = config.model || 'claude-sonnet-4-5-20250929';
this.maxTokens = config.maxTokens || 8192;
}
async chat(messages: Anthropic.MessageParam[], options?: {
system?: string;
tools?: Anthropic.Tool[];
temperature?: number;
}) {
return await this.client.messages.create({
model: this.model,
max_tokens: this.maxTokens,
system: options?.system,
messages,
tools: options?.tools,
temperature: options?.temperature
});
}
async chatStream(
messages: Anthropic.MessageParam[],
options?: { system?: string; tools?: Anthropic.Tool[] },
onChunk: (event: Anthropic.RawMessageStreamEvent) => void
) {
const stream = await this.client.messages.create({
model: this.model,
max_tokens: this.maxTokens,
system: options?.system,
messages,
tools: options?.tools,
stream: true
});
for await (const event of stream) {
onChunk(event);
}
}
}
```
**70%**
### 3.2
#### 11-2
- `AnthropicClient`
- `AnthropicClientSDK`
- SDK
#### 22-4
-
- SDK
-
#### 31-2
-
-
-
---
## 4. API
### 4.1
```typescript
import Anthropic from '@anthropic-ai/sdk';
//
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
baseURL: 'https://api.anthropic.com', //
timeout: 60000 // 10
});
//
const models = await client.models.list();
console.log(models.data);
```
### 4.2
####
```typescript
const message = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{
role: 'user',
content: ''
}]
});
console.log(message.content[0].type); // 'text'
console.log(message.content[0].text); //
```
#### /PDF
```typescript
const message = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{
role: 'user',
content: [
{
type: 'text',
text: ''
},
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/png',
data: 'iVBORw0KGgoAAAANSUhEUg...' // base64
}
}
]
}]
});
```
### 4.3
####
```typescript
const stream = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{ role: 'user', content: '' }],
stream: true
});
for await (const event of stream) {
switch (event.type) {
case 'text_block':
console.log('');
break;
case 'content_block_delta':
console.log(':', event.delta.text);
break;
case 'message_stop':
console.log('');
break;
}
}
```
#### Stream Helper
```typescript
const stream = client.messages.stream({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{ role: 'user', content: '' }]
})
.on('text', (text) => {
console.log(':', text);
})
.on('error', (error) => {
console.error(':', error);
})
.on('finalMessage', (message) => {
console.log(':', message);
});
await stream.finalMessage();
```
### 4.4 Tool Use
####
```typescript
import { z } from 'zod';
import { betaZodTool } from '@anthropic-ai/sdk/helpers/beta/zod';
// 1 Zod
const searchTool = betaZodTool({
name: 'search_code',
description: '',
inputSchema: z.object({
query: z.string().describe(''),
file_type: z.string().optional().describe('')
}),
run: async (input) => {
//
const results = await searchInCodebase(input.query, input.file_type);
return JSON.stringify(results);
}
});
// 2 JSON Schema
const searchTool2: Anthropic.Tool = {
name: 'search_code',
description: '',
input_schema: {
type: 'object',
properties: {
query: {
type: 'string',
description: ''
},
file_type: {
type: 'string',
description: ''
}
},
required: ['query']
}
};
```
####
```typescript
// 1
const finalMessage = await client.beta.messages.toolRunner({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
messages: [{ role: 'user', content: ' TypeScript "API" ' }],
tools: [searchTool]
});
// 2
const response = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
messages: [{ role: 'user', content: '' }],
tools: [searchTool]
});
//
let currentMessages = [{ role: 'user', content: '' }];
for (const block of response.content) {
if (block.type === 'tool_use') {
//
const result = await executeTool(block.name, block.input);
//
const toolResponse = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
messages: [
...currentMessages,
{ role: 'assistant', content: response.content },
{
role: 'user',
content: [{
type: 'tool_result',
tool_use_id: block.id,
content: result
}]
}
]
});
}
}
```
### 4.5 Token
```typescript
// token
const tokenCount = await client.messages.countTokens({
model: 'claude-sonnet-4-5-20250929',
messages: [
{ role: 'user', content: '...' }
]
});
console.log(' tokens:', tokenCount.input_tokens);
//
const message = await client.messages.create({...});
console.log(' tokens:', message.usage.input_tokens);
console.log(' tokens:', message.usage.output_tokens);
```
### 4.6 (Extended Thinking)
#### Extended Thinking
Extended Thinking Claude
- token
- `thinking`
-
####
```typescript
const message = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 3200,
//
thinking: {
type: 'enabled',
budget_tokens: 1600 // token
},
messages: [{
role: 'user',
content: '...'
}]
});
//
for (const block of message.content) {
if (block.type === 'thinking') {
console.log(':', block.thinking);
console.log(':', block.signature);
} else if (block.type === 'text') {
console.log(':', block.text);
}
}
```
****
- `budget_tokens`: token
- 1024 tokens
- `max_tokens`
- `max_tokens`
- `type`: `'enabled'`
#### Thinking
```typescript
const stream = client.messages.stream({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 3200,
thinking: {
type: 'enabled',
budget_tokens: 1600
},
messages: [{
role: 'user',
content: ''
}]
})
.on('thinking', (thinking) => {
//
process.stdout.write(thinking);
})
.on('text', (text) => {
//
process.stdout.write(text);
})
.on('signature', (signature) => {
//
console.log('\n:', signature);
})
.on('error', (error) => {
console.error(':', error);
});
const finalMessage = await stream.finalMessage();
console.log('\n:', finalMessage);
```
####
```typescript
let thinkingState = 'not-started';
const stream = client.messages.stream({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 3200,
thinking: { type: 'enabled', budget_tokens: 1600 },
messages: [{ role: 'user', content: '' }]
})
.on('thinking', (thinking) => {
if (thinkingState === 'not-started') {
console.log(':\n---------');
thinkingState = 'started';
}
process.stdout.write(thinking);
})
.on('text', (text) => {
if (thinkingState !== 'finished') {
console.log('\n\n:\n-----');
thinkingState = 'finished';
}
process.stdout.write(text);
});
await stream.finalMessage();
```
####
** Extended Thinking **
1. ****
2. ****
3. ****
4. **** bug
5. ****
****
1.
2.
3.
####
```typescript
// thinking budget
function calculateThinkingBudget(complexity: 'low' | 'medium' | 'high'): number {
const budgets = {
low: 1024, //
medium: 2048, //
high: 4096 //
};
return budgets[complexity];
}
const message = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
thinking: {
type: 'enabled',
budget_tokens: calculateThinkingBudget('high')
},
messages: [{ role: 'user', content: complexQuestion }]
});
```
#### Thinking
```typescript
// thinking
const message = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{ role: 'user', content: '' }]
});
//
const message2 = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
thinking: { type: 'disabled' },
messages: [{ role: 'user', content: '' }]
});
```
---
## 6.
### 6.1
```typescript
import {
APIError,
APIConnectionError,
RateLimitError,
AuthenticationError
} from '@anthropic-ai/sdk';
try {
const message = await client.messages.create({...});
} catch (error) {
if (error instanceof APIConnectionError) {
console.error(':', error.message);
} else if (error instanceof RateLimitError) {
console.error('');
} else if (error instanceof AuthenticationError) {
console.error('API ');
} else if (error instanceof APIError) {
console.error('API :', error.message);
console.error(':', error.status);
console.error(':', error.error);
}
}
```
### 6.2
SDK
```typescript
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
maxRetries: 3, // 2
timeout: 60000
});
```
### 6.3
#### 1.
```typescript
const message = await client.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
system: '',
messages: [
{
role: 'user',
content: ''
}
],
//
cache_control: {
type: 'ephemeral',
ttl: '5m'
}
});
```
#### 2.
```typescript
// Message Batches API
const batch = await client.messages.batches.create({
requests: [
{
custom_id: 'request-1',
params: {
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{ role: 'user', content: ' 1' }]
}
},
{
custom_id: 'request-2',
params: {
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{ role: 'user', content: ' 2' }]
}
}
]
});
//
const results = await client.messages.batches.results(batch.id);
for await (const result of results) {
console.log(result);
}
```
### 6.4
#### 1. API
```typescript
//
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY
});
//
const client = new Anthropic({
apiKey: 'sk-ant-xxx...' //
});
```
#### 2.
```typescript
//
function sanitizeUserInput(input: string): string {
//
return input
.replace(/ {
const fs = await import('fs/promises');
await fs.writeFile(input.filePath, input.content, 'utf-8');
return '';
}
});
//
async function codeAssistant(userRequest: string) {
const finalMessage = await client.beta.messages.toolRunner({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
system: '',
messages: [{ role: 'user', content: userRequest }],
tools: [readFileTool, writeFileTool]
});
return finalMessage;
}
//
const result = await codeAssistant(' src/index.js ');
console.log(result.content);
```
### 8.2
```typescript
async function streamingCodeAssistant(userRequest: string) {
const stream = client.messages.stream({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
system: '',
messages: [{ role: 'user', content: userRequest }],
tools: [readFileTool, writeFileTool]
})
.on('text', (text) => {
process.stdout.write(text);
})
.on('toolUse', (toolUse) => {
console.log('\n[]', toolUse.name, toolUse.input);
})
.on('error', (error) => {
console.error('\n[]', error);
});
const finalMessage = await stream.finalMessage();
return finalMessage;
}
```
### 8.3
```typescript
import * as readline from 'readline';
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
async function askQuestion(query: string): Promise {
return new Promise(resolve => {
rl.question(query, (answer) => {
resolve(answer);
});
});
}
async function interactiveChat() {
const messages: Anthropic.MessageParam[] = [];
console.log('=== Closer Code ===');
console.log(' "quit" \n');
while (true) {
const userInput = await askQuestion(': ');
if (userInput.toLowerCase() === 'quit') {
break;
}
messages.push({
role: 'user',
content: userInput
});
const stream = client.messages.stream({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 8192,
messages
})
.on('text', (text) => {
process.stdout.write(text);
})
.on('finalMessage', (msg) => {
messages.push({
role: 'assistant',
content: msg.content
});
});
await stream.finalMessage();
console.log('\n');
}
rl.close();
}
interactiveChat();
```
### 8.4 Extended Thinking
Extended Thinking
```typescript
import Anthropic from '@anthropic-ai/sdk';
import { betaZodTool } from '@anthropic-ai/sdk/helpers/beta/zod';
import { z } from 'zod';
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY
});
//
const analyzeFileTool = betaZodTool({
name: 'analyze_file',
description: '',
inputSchema: z.object({
filePath: z.string().describe(''),
analysisType: z.enum(['security', 'performance', 'readability', 'all'])
.describe('')
}),
run: async (input) => {
const fs = await import('fs/promises');
try {
const content = await fs.readFile(input.filePath, 'utf-8');
return {
success: true,
file: input.filePath,
content: content.slice(0, 5000), //
analysisType: input.analysisType
};
} catch (error) {
return {
success: false,
error: (error as Error).message
};
}
}
});
//
class CodeReviewAssistant {
private client: Anthropic;
private model: string;
constructor() {
this.client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY
});
this.model = 'claude-sonnet-4-5-20250929';
}
// Extended Thinking
async deepAnalysis(userRequest: string, complexity: 'low' | 'medium' | 'high' = 'high') {
const thinkingBudgets = {
low: 1024,
medium: 2048,
high: 4096
};
console.log(`\n=== (Thinking Budget: ${thinkingBudgets[complexity]} tokens) ===\n`);
let thinkingState = 'not-started';
let thinkingContent = '';
const stream = this.client.messages.stream({
model: this.model,
max_tokens: 8192,
thinking: {
type: 'enabled',
budget_tokens: thinkingBudgets[complexity]
},
system: `
1.
2.
3.
4.
5. `,
messages: [{ role: 'user', content: userRequest }],
tools: [analyzeFileTool]
})
.on('thinking', (thinking) => {
if (thinkingState === 'not-started') {
console.log(' ...\n---');
thinkingState = 'started';
}
thinkingContent += thinking;
process.stdout.write(thinking);
})
.on('text', (text) => {
if (thinkingState !== 'finished') {
console.log('\n\n---\n :\n---');
thinkingState = 'finished';
}
process.stdout.write(text);
})
.on('toolUse', (toolUse) => {
console.log('\n\n :', toolUse.name);
console.log(':', JSON.stringify(toolUse.input, null, 2));
})
.on('error', (error) => {
console.error('\n :', error);
});
const finalMessage = await stream.finalMessage();
console.log('\n\n=== ===');
console.log(`: ${thinkingContent.length} `);
console.log(`Token : =${finalMessage.usage.input_tokens}, =${finalMessage.usage.output_tokens}`);
return {
finalMessage,
thinkingContent
};
}
// Extended Thinking
async quickAnalysis(userRequest: string) {
console.log('\n=== ===\n');
const finalMessage = await this.client.beta.messages.toolRunner({
model: this.model,
max_tokens: 4096,
system: '',
messages: [{ role: 'user', content: userRequest }],
tools: [analyzeFileTool]
});
console.log(' ');
console.log(`Token : =${finalMessage.usage.input_tokens}, =${finalMessage.usage.output_tokens}`);
return finalMessage;
}
}
//
async function main() {
const assistant = new CodeReviewAssistant();
// 1:
console.log('\n 1: ');
await assistant.deepAnalysis(
' src/auth/login.ts SQLXSS',
'high'
);
//
await new Promise(resolve => setTimeout(resolve, 2000));
// 2:
console.log('\n\n 2: ');
await assistant.quickAnalysis(' src/utils/helpers.ts ');
// 3:
console.log('\n\n 3: ');
const result = await assistant.deepAnalysis(
'',
'high'
);
//
if (result.thinkingContent) {
console.log('\n : result.thinkingContent');
}
}
//
if (require.main === module) {
main().catch(console.error);
}
export { CodeReviewAssistant };
```
####
```bash
$ npm run code-review
=== (Thinking Budget: 4096 tokens) ===
...
---
...
1.
2.
3.
-
-
-
...
---
:
---
1. **SQL **: 45 ...
2. ****: HTTP-only cookies...
3. ****: ...
=== ===
: 1243
Token : =3456, =789
```
####
1. ****: thinking budget
2. ****:
3. ****:
4. ****:
####
- ****: `high` thinking budget (4096+)
- ****: `medium` (2048 tokens)
- ****:
---
`@anthropic-ai/sdk`
1. ** 70-80%**
2. **** TypeScript
3. ****
4. **** SSE
5. ****toolRunner
6. ****
7. **Extended Thinking **
8. ****
- SDK
-
-
-
---
****: 1.1.0
****: 2025-01-18
****: Closer Code
****:
- v1.1.0 (2025-01-18): Extended Thinking
- v1.0.0 (2025-01-17): API
****:
- [Anthropic TypeScript SDK ](../ref_repo/anthropic-sdk-typescript/api.md)
- [Messages API ](https://docs.anthropic.com/claude/reference/messages-post)
- [Closer Code README](./README.md)