Claude API完全ガイド2026 - Messages API、ストリーミング、ツール使用、コンテキストウィンドウ、ベストプラクティス
Claude API完全ガイド2026
Anthropic Claude APIは、高度な推論能力を持つAI APIです。本記事では、Messages APIの基本からツール使用、最適化まで網羅的に解説します。
目次
- Claude APIとは
- セットアップと認証
- Messages API基本
- ストリーミングレスポンス
- ツール使用(Function Calling)
- コンテキストウィンドウ活用
- プロンプトキャッシング
- コスト最適化
- 実践パターン
Claude APIとは
特徴と強み
/**
* Claude API の特徴
*
* 1. 高度な推論能力
* - 複雑な指示の理解
* - 長文の要約と分析
* - コード生成と説明
*
* 2. 大きなコンテキストウィンドウ
* - Claude 3.5 Sonnet: 200K トークン
* - Claude 3 Opus: 200K トークン
*
* 3. ツール使用
* - Function Calling
* - 外部API連携
*
* 4. 安全性
* - Constitutional AI
* - 有害コンテンツフィルタリング
*/
// モデル一覧(2026年2月時点)
const CLAUDE_MODELS = {
// 最新モデル
sonnet35: 'claude-3-5-sonnet-20241022',
// Claude 3 シリーズ
opus3: 'claude-3-opus-20240229',
sonnet3: 'claude-3-sonnet-20240229',
haiku3: 'claude-3-haiku-20240307',
// レガシー
claude2: 'claude-2.1',
} as const
料金(2026年2月時点)
// 概算料金($USD per Million tokens)
const PRICING = {
'claude-3-5-sonnet-20241022': {
input: 3.00,
output: 15.00,
cachedInput: 0.30, // 90% off
},
'claude-3-opus-20240229': {
input: 15.00,
output: 75.00,
cachedInput: 1.50,
},
'claude-3-sonnet-20240229': {
input: 3.00,
output: 15.00,
},
'claude-3-haiku-20240307': {
input: 0.25,
output: 1.25,
cachedInput: 0.03,
},
} as const
// コスト計算関数
function calculateCost(
model: keyof typeof PRICING,
inputTokens: number,
outputTokens: number,
cachedInputTokens: number = 0
): number {
const pricing = PRICING[model]
const inputCost = (inputTokens / 1_000_000) * pricing.input
const outputCost = (outputTokens / 1_000_000) * pricing.output
const cachedCost = pricing.cachedInput
? (cachedInputTokens / 1_000_000) * pricing.cachedInput
: 0
return inputCost + outputCost + cachedCost
}
セットアップと認証
SDKインストール
# TypeScript/JavaScript
npm install @anthropic-ai/sdk
# Python
pip install anthropic
基本的な設定
import Anthropic from '@anthropic-ai/sdk'
// クライアント初期化
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
})
// 環境変数の設定
// .env
// ANTHROPIC_API_KEY=sk-ant-api03-...
// 型安全な設定
interface ClaudeConfig {
apiKey: string
maxRetries?: number
timeout?: number
baseURL?: string
}
function createClient(config: ClaudeConfig): Anthropic {
return new Anthropic({
apiKey: config.apiKey,
maxRetries: config.maxRetries ?? 2,
timeout: config.timeout ?? 60000,
baseURL: config.baseURL,
})
}
エラーハンドリング
import {
APIError,
APIConnectionError,
APITimeoutError,
RateLimitError,
AuthenticationError,
} from '@anthropic-ai/sdk'
async function safeAPICall<T>(
fn: () => Promise<T>,
retries = 3
): Promise<T> {
try {
return await fn()
} catch (error) {
if (error instanceof RateLimitError) {
// レート制限: リトライ
if (retries > 0) {
await new Promise(resolve => setTimeout(resolve, 1000))
return safeAPICall(fn, retries - 1)
}
}
if (error instanceof APITimeoutError) {
console.error('API timeout')
throw new Error('Request timed out')
}
if (error instanceof AuthenticationError) {
console.error('Authentication failed')
throw new Error('Invalid API key')
}
if (error instanceof APIConnectionError) {
console.error('Connection error')
throw new Error('Failed to connect to API')
}
throw error
}
}
Messages API基本
シンプルな呼び出し
// 基本的なメッセージ送信
async function simpleMessage() {
const message = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [
{
role: 'user',
content: 'Hello, Claude!'
}
],
})
console.log(message.content[0].text)
}
// システムプロンプト付き
async function withSystemPrompt() {
const message = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
system: 'あなたは親切なAIアシスタントです。常に丁寧に回答してください。',
messages: [
{
role: 'user',
content: 'TypeScriptについて教えてください'
}
],
})
return message.content[0].text
}
マルチターン会話
// 会話履歴を保持
class ConversationManager {
private messages: Anthropic.MessageParam[] = []
constructor(
private anthropic: Anthropic,
private systemPrompt?: string
) {}
async sendMessage(userMessage: string): Promise<string> {
// ユーザーメッセージを追加
this.messages.push({
role: 'user',
content: userMessage,
})
// API呼び出し
const response = await this.anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
system: this.systemPrompt,
messages: this.messages,
})
// アシスタントの返答を履歴に追加
const assistantMessage = response.content[0].text
this.messages.push({
role: 'assistant',
content: assistantMessage,
})
return assistantMessage
}
getHistory(): Anthropic.MessageParam[] {
return [...this.messages]
}
clearHistory(): void {
this.messages = []
}
}
// 使用例
const conversation = new ConversationManager(
anthropic,
'あなたはプログラミング教師です'
)
const response1 = await conversation.sendMessage('TypeScriptとは何ですか?')
console.log(response1)
const response2 = await conversation.sendMessage('具体例を教えてください')
console.log(response2)
マルチモーダル(画像入力)
import * as fs from 'fs'
// 画像を base64 エンコード
function encodeImage(imagePath: string): string {
const imageBuffer = fs.readFileSync(imagePath)
return imageBuffer.toString('base64')
}
// 画像付きメッセージ
async function analyzeImage(imagePath: string) {
const imageData = encodeImage(imagePath)
const mimeType = imagePath.endsWith('.png') ? 'image/png' : 'image/jpeg'
const message = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [
{
role: 'user',
content: [
{
type: 'image',
source: {
type: 'base64',
media_type: mimeType,
data: imageData,
},
},
{
type: 'text',
text: 'この画像について説明してください',
},
],
},
],
})
return message.content[0].text
}
// URLから画像を分析
async function analyzeImageFromURL(imageUrl: string) {
const response = await fetch(imageUrl)
const buffer = await response.arrayBuffer()
const base64 = Buffer.from(buffer).toString('base64')
const message = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [
{
role: 'user',
content: [
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/jpeg',
data: base64,
},
},
{
type: 'text',
text: 'この画像のテキストを抽出してください',
},
],
},
],
})
return message.content[0].text
}
ストリーミングレスポンス
基本的なストリーミング
// ストリーミングレスポンスを処理
async function streamMessage(userMessage: string) {
const stream = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [{ role: 'user', content: userMessage }],
stream: true,
})
for await (const event of stream) {
if (
event.type === 'content_block_delta' &&
event.delta.type === 'text_delta'
) {
process.stdout.write(event.delta.text)
}
}
console.log('\n')
}
// イベントハンドラー付き
async function streamWithHandlers(userMessage: string) {
let fullText = ''
const stream = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [{ role: 'user', content: userMessage }],
stream: true,
})
for await (const event of stream) {
switch (event.type) {
case 'message_start':
console.log('Message started')
break
case 'content_block_start':
console.log('Content block started')
break
case 'content_block_delta':
if (event.delta.type === 'text_delta') {
fullText += event.delta.text
process.stdout.write(event.delta.text)
}
break
case 'content_block_stop':
console.log('\nContent block stopped')
break
case 'message_delta':
console.log('Stop reason:', event.delta.stop_reason)
break
case 'message_stop':
console.log('Message stopped')
break
}
}
return fullText
}
React統合
// React用カスタムフック
import { useState, useCallback } from 'react'
interface UseClaudeStreamOptions {
apiKey: string
model?: string
systemPrompt?: string
}
export function useClaudeStream(options: UseClaudeStreamOptions) {
const [isStreaming, setIsStreaming] = useState(false)
const [response, setResponse] = useState('')
const [error, setError] = useState<Error | null>(null)
const sendMessage = useCallback(
async (message: string) => {
setIsStreaming(true)
setResponse('')
setError(null)
try {
const anthropic = new Anthropic({
apiKey: options.apiKey,
dangerouslyAllowBrowser: true, // クライアントサイド実行の場合
})
const stream = await anthropic.messages.create({
model: options.model ?? 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
system: options.systemPrompt,
messages: [{ role: 'user', content: message }],
stream: true,
})
for await (const event of stream) {
if (
event.type === 'content_block_delta' &&
event.delta.type === 'text_delta'
) {
setResponse(prev => prev + event.delta.text)
}
}
} catch (err) {
setError(err as Error)
} finally {
setIsStreaming(false)
}
},
[options]
)
return { response, isStreaming, error, sendMessage }
}
// 使用例
function ChatComponent() {
const { response, isStreaming, sendMessage } = useClaudeStream({
apiKey: process.env.NEXT_PUBLIC_ANTHROPIC_API_KEY!,
systemPrompt: 'あなたは親切なAIアシスタントです',
})
return (
<div>
<button
onClick={() => sendMessage('Hello!')}
disabled={isStreaming}
>
送信
</button>
<div>{response}</div>
</div>
)
}
ツール使用(Function Calling)
基本的なツール定義
// ツール定義
const tools: Anthropic.Tool[] = [
{
name: 'get_weather',
description: '指定された場所の天気情報を取得します',
input_schema: {
type: 'object',
properties: {
location: {
type: 'string',
description: '都市名(例: 東京、New York)',
},
unit: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
description: '温度の単位',
},
},
required: ['location'],
},
},
{
name: 'calculate',
description: '数式を計算します',
input_schema: {
type: 'object',
properties: {
expression: {
type: 'string',
description: '計算する数式(例: 2 + 2)',
},
},
required: ['expression'],
},
},
]
// ツール実行関数
async function executeTools(
toolName: string,
toolInput: Record<string, any>
): Promise<string> {
switch (toolName) {
case 'get_weather':
return JSON.stringify({
location: toolInput.location,
temperature: 22,
condition: 'Sunny',
unit: toolInput.unit ?? 'celsius',
})
case 'calculate':
try {
// 注意: eval は危険なので実際には安全な計算ライブラリを使用
const result = eval(toolInput.expression)
return JSON.stringify({ result })
} catch (error) {
return JSON.stringify({ error: 'Invalid expression' })
}
default:
return JSON.stringify({ error: 'Unknown tool' })
}
}
ツールを使った会話
async function chatWithTools(userMessage: string) {
let messages: Anthropic.MessageParam[] = [
{ role: 'user', content: userMessage },
]
// 最初のAPI呼び出し
let response = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
tools: tools,
messages: messages,
})
// ツール使用を繰り返し処理
while (response.stop_reason === 'tool_use') {
// アシスタントのメッセージを追加
messages.push({
role: 'assistant',
content: response.content,
})
// ツール実行結果を収集
const toolResults: Anthropic.MessageParam = {
role: 'user',
content: [],
}
for (const block of response.content) {
if (block.type === 'tool_use') {
console.log(`Executing tool: ${block.name}`)
console.log('Input:', block.input)
const result = await executeTools(block.name, block.input)
console.log('Result:', result)
toolResults.content.push({
type: 'tool_result',
tool_use_id: block.id,
content: result,
})
}
}
// ツール結果を追加
messages.push(toolResults)
// 次のAPI呼び出し
response = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
tools: tools,
messages: messages,
})
}
// 最終的なテキストレスポンスを抽出
const textBlock = response.content.find(block => block.type === 'text')
return textBlock?.text ?? ''
}
// 使用例
const answer = await chatWithTools('東京の天気は? ついでに 123 × 456 を計算して')
console.log(answer)
複雑なツールチェーン
// データベース操作ツール
const databaseTools: Anthropic.Tool[] = [
{
name: 'search_database',
description: 'データベースを検索します',
input_schema: {
type: 'object',
properties: {
query: { type: 'string', description: '検索クエリ' },
limit: { type: 'number', description: '結果の上限' },
},
required: ['query'],
},
},
{
name: 'insert_record',
description: 'データベースにレコードを挿入します',
input_schema: {
type: 'object',
properties: {
table: { type: 'string', description: 'テーブル名' },
data: { type: 'object', description: '挿入するデータ' },
},
required: ['table', 'data'],
},
},
{
name: 'update_record',
description: 'データベースのレコードを更新します',
input_schema: {
type: 'object',
properties: {
table: { type: 'string', description: 'テーブル名' },
id: { type: 'string', description: 'レコードID' },
data: { type: 'object', description: '更新するデータ' },
},
required: ['table', 'id', 'data'],
},
},
]
// ツール実行ハンドラー
class ToolExecutor {
async execute(
toolName: string,
toolInput: Record<string, any>
): Promise<string> {
console.log(`[Tool] ${toolName}`, toolInput)
// 実際のデータベース操作はここで実行
switch (toolName) {
case 'search_database':
return JSON.stringify([
{ id: 1, name: 'Sample 1' },
{ id: 2, name: 'Sample 2' },
])
case 'insert_record':
return JSON.stringify({
success: true,
id: 'new-id-123',
})
case 'update_record':
return JSON.stringify({
success: true,
updated: 1,
})
default:
throw new Error(`Unknown tool: ${toolName}`)
}
}
}
コンテキストウィンドウ活用
長文の処理
// 長文ドキュメントの要約
async function summarizeLongDocument(document: string) {
const message = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 2048,
system: '以下の文書を3つの要点にまとめてください',
messages: [
{
role: 'user',
content: document,
},
],
})
return message.content[0].text
}
// 複数ドキュメントの比較
async function compareDocuments(doc1: string, doc2: string) {
const message = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 2048,
messages: [
{
role: 'user',
content: `
以下の2つの文書を比較し、主な違いを説明してください。
【文書1】
${doc1}
【文書2】
${doc2}
`,
},
],
})
return message.content[0].text
}
コードベース分析
import * as fs from 'fs'
import * as path from 'path'
// ディレクトリ内の全ファイルを読み込み
function readDirectory(dirPath: string): string {
let content = ''
function traverse(currentPath: string) {
const files = fs.readdirSync(currentPath)
for (const file of files) {
const fullPath = path.join(currentPath, file)
const stat = fs.statSync(fullPath)
if (stat.isDirectory()) {
if (file !== 'node_modules' && file !== '.git') {
traverse(fullPath)
}
} else if (file.endsWith('.ts') || file.endsWith('.tsx')) {
const fileContent = fs.readFileSync(fullPath, 'utf-8')
content += `\n\n--- ${fullPath} ---\n${fileContent}`
}
}
}
traverse(dirPath)
return content
}
// コードベース分析
async function analyzeCodebase(projectPath: string) {
const codeContent = readDirectory(projectPath)
const message = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 4096,
system: 'あなたは経験豊富なコードレビュアーです',
messages: [
{
role: 'user',
content: `
以下のコードベースを分析し、以下の点を報告してください:
1. アーキテクチャの概要
2. 改善提案
3. セキュリティ上の懸念
4. パフォーマンスの問題
${codeContent}
`,
},
],
})
return message.content[0].text
}
プロンプトキャッシング
キャッシュの活用
// システムプロンプトをキャッシュ
async function withCaching() {
const longSystemPrompt = `
あなたは専門的なプログラミングアシスタントです。
【ルール】
1. コードは常にTypeScriptで書く
2. 型安全を重視する
3. エラーハンドリングを含める
4. テストコードも提供する
5. パフォーマンスを考慮する
【コーディング規約】
- インデント: 2スペース
- 命名: camelCase(変数・関数)、PascalCase(クラス・型)
- 必ずコメントを書く
- ...(さらに長い説明が続く)
`.trim()
// cache_control を使用
const message = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
system: [
{
type: 'text',
text: longSystemPrompt,
cache_control: { type: 'ephemeral' },
},
],
messages: [
{
role: 'user',
content: 'フィボナッチ数列を計算する関数を書いて',
},
],
})
console.log('Cache stats:', {
cacheCreationTokens: message.usage.cache_creation_input_tokens,
cacheReadTokens: message.usage.cache_read_input_tokens,
inputTokens: message.usage.input_tokens,
})
return message.content[0].text
}
長文コンテキストのキャッシュ
// ドキュメントをキャッシュして複数の質問
class CachedDocumentChat {
constructor(
private anthropic: Anthropic,
private document: string
) {}
async ask(question: string): Promise<string> {
const message = await this.anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
system: [
{
type: 'text',
text: '以下のドキュメントに基づいて回答してください',
},
{
type: 'text',
text: this.document,
cache_control: { type: 'ephemeral' },
},
],
messages: [
{
role: 'user',
content: question,
},
],
})
return message.content[0].text
}
}
// 使用例
const longDocument = fs.readFileSync('long-document.txt', 'utf-8')
const chat = new CachedDocumentChat(anthropic, longDocument)
// 最初の質問(キャッシュ作成)
const answer1 = await chat.ask('このドキュメントの要約は?')
// 2番目以降の質問(キャッシュ使用、コスト削減)
const answer2 = await chat.ask('主なトピックは?')
const answer3 = await chat.ask('結論は?')
コスト最適化
トークン数の最適化
import { encode } from 'gpt-tokenizer'
// トークン数をカウント
function countTokens(text: string): number {
// Claude は GPT のトークナイザーと近似
return encode(text).length
}
// 最適なモデル選択
function selectOptimalModel(
inputText: string,
expectedOutputLength: number
): string {
const inputTokens = countTokens(inputText)
// 簡単なタスクは Haiku
if (inputTokens < 1000 && expectedOutputLength < 500) {
return 'claude-3-haiku-20240307'
}
// 中程度のタスクは Sonnet
if (inputTokens < 50000) {
return 'claude-3-5-sonnet-20241022'
}
// 複雑なタスクは Opus
return 'claude-3-opus-20240229'
}
バッチ処理
// 複数のリクエストを効率的に処理
async function batchProcess(
items: string[],
processor: (item: string) => Promise<string>
): Promise<string[]> {
const batchSize = 5
const results: string[] = []
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize)
const batchResults = await Promise.all(
batch.map(item => processor(item))
)
results.push(...batchResults)
// レート制限を避けるため待機
if (i + batchSize < items.length) {
await new Promise(resolve => setTimeout(resolve, 1000))
}
}
return results
}
実践パターン
AIアシスタントチャットボット
// 完全なチャットボット実装
class ClaudeAssistant {
private conversation: ConversationManager
constructor(
anthropic: Anthropic,
systemPrompt: string
) {
this.conversation = new ConversationManager(
anthropic,
systemPrompt
)
}
async chat(message: string): Promise<string> {
return this.conversation.sendMessage(message)
}
async chatWithTools(
message: string,
tools: Anthropic.Tool[]
): Promise<string> {
return chatWithTools(message) // 前述の実装を使用
}
reset(): void {
this.conversation.clearHistory()
}
}
コード生成アシスタント
class CodeGenerator {
constructor(private anthropic: Anthropic) {}
async generateCode(
description: string,
language: string
): Promise<string> {
const message = await this.anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 4096,
system: `
あなたは${language}の専門家です。
常にベストプラクティスに従ったコードを生成してください。
`,
messages: [
{
role: 'user',
content: `${description}\n\nコードのみを出力してください。`,
},
],
})
return message.content[0].text
}
}
まとめ
Claude APIは、高度な推論能力と大きなコンテキストウィンドウを持つ強力なAI APIです。
主要ポイント:
- Messages API: シンプルで直感的なインターフェース
- ストリーミング: リアルタイムな応答表示
- ツール使用: Function Calling で外部システム連携
- 大規模コンテキスト: 200Kトークンで長文処理
- プロンプトキャッシング: コストを最大90%削減
2026年のベストプラクティス:
- 適切なモデル選択でコスト最適化
- プロンプトキャッシングを活用
- ストリーミングでUX向上
- ツール使用で機能拡張
- エラーハンドリングとリトライ
Claude APIを活用して、高度なAIアプリケーションを構築しましょう。