Claude APIの使い方:VPSで動くPythonアプリ開発
Ubuntu 24.04のVPS上で、Claude APIを使ったログ解析ツールをPythonで構築する手順を解説します。API keyの安全な管理方法から、streaming処理、型定義によるエラーハンドリング、systemdによるバックグラウンド実行まで、実用的な実装方法を網羅しています。
作成するもの
新規の Ubuntu 24.04 VPS 上で動作するコマンドラインツールです。エラーメッセージやログの一部をパイプで渡すと、平易な英語で診断結果を返します:journalctl -u nginx -n 50 | explain。コード量は Python で約 60 行です。このプロジェクトでは、実用的な Claude API アプリケーションに必要な要素をすべて網羅しています。具体的には、適切なキーの保存、virtualenv の使用、SDK のレスポンス構造、ストリーミング、型定義された例外チェーン、そしてバックグラウンド実行のための systemd ユニットです。
このプロジェクトをあえて選んだ理由があります。一般的な「最初の API アプリ」のチュートリアルでは、二度と開かないようなチャットボットを作らせることが多いからです。ログ解析ツールは、初日からサーバー上で実用的な価値を発揮します。また、初心者が陥りやすい「レスポンスオブジェクトの正しい読み取り」と「コスト管理」の2点を習得できます。API の料金はトークン単位で発生し、設定次第で上限がなくなるため、コスト管理は後付けの要素ではなく、設計段階からの必須事項です。これは、この VPS 上の tmux で Claude Code を実行する 際にも同様に重要な規律となります。
ConsoleからAPI keyを取得する
APIアクセスは platform.claude.com の Anthropic Console で管理されます。サインアップ後、Settings → API Keys からキーを作成してください(ドキュメントのリンクは直接 platform.claude.com/settings/keys へ飛びます)。キーは一度しか表示されません。sk-ant- で始まり、再取得は不可能です。すぐにコピーするか、削除して再発行してください。
料金について:2026年7月現在、APIに継続的な無料枠はありません。Anthropicの料金ドキュメントによると、新規ユーザーにはテスト用の少額の無料クレジットが付与されます。正確な金額はサインアップ時にConsoleに表示される通りです。クレジットを使い切ると、リクエストを成功させるにはアカウントへの入金が必要です。これは claude.ai のサブスクリプションとは別物です。ProプランやMaxプランにAPIクレジットは含まれません。また、API key を持っているからといってチャットアプリが使えるわけではありません。サブスクリプションとAPIのどちらを選ぶべきかについては、必要なClaudeプランの選択 を参照してください。
キーを作成する際は、特定のプロジェクトまたはサーバーにスコープを限定してください。キーが漏洩した場合(長期的には必ず発生します)、他のシステムに影響を与えずに、そのキーだけを無効化できるようにするためです。
.bashrc に key を書き込まない
~/.bashrc で export ANTHROPIC_API_KEY=sk-ant-... を行う手法は避けてください。理由は以下の3点です。
- すべてのプロセスが継承するため。 ログインシェルで export された環境変数は、Web app、バグ報告に環境変数を出力する crash reporter、そして誰かが有効にしたままの
phpinfo()ページなど、起動するすべてのプロセスに伝播します。key の露出範囲が「このユーザーが実行するすべてのもの」に広がります。 - 入力すると
~/.bash_historyに残るため。 手動で export を実行すると、key は plaintext ファイルとして永続的に残り、home directory のすべてのバックアップに同期されます。 - systemd が必要とする時に読み込めないため。 サービスは
.bashrcを読み込みません。そのため、スクリプトを unit に昇格させた際、通常は早朝 6 時に謎の 401 エラーが発生して失敗します。
サーバーにおける正しいパターンは、600 権限を持つ専用の environment file を作成し、必要なプロセスのみに読み込ませることです。
sudo mkdir -p /opt/explain
sudo install -m 600 -o root -g root /dev/null /etc/claude-explain.env
printf 'ANTHROPIC_API_KEY=sk-ant-YOUR-KEY-HERE\n' | sudo tee /etc/claude-explain.env >/dev/nulleditor の swap file に key を残したくない場合は、editor ではなく printf から tee を使用してください。いずれの場合も、ls -l /etc/claude-explain.env を使用して、-rw------- を読み込み、所有者が root であることを確認してください。インタラクティブな shell には wrapper (下記参照) を介して実行ごとに key を渡し、systemd には EnvironmentFile= を介して渡します。root が権限を放棄する前にファイルを読み込むため、service user に読み取り権限を与える必要はありません。key は code、git、ps の出力、または shell history に決して現れません。
venvにSDKをインストールする
Ubuntu 24.04ではPEP 668が適用されたPython 3.12が提供されています。そのため、システムインタープリタに対して直接 pip install anthropic を実行すると error: externally-managed-environment が発生します。このエラーはOSの仕様通りの動作です。代わりに virtualenv を使用してください。
sudo apt update && sudo apt install -y python3-venv
sudo python3 -m venv /opt/explain/venv
sudo /opt/explain/venv/bin/pip install anthropicサーバー上では activation は不要です。/opt/explain/venv/bin/python を直接呼び出すことで、常に venv のパッケージが使用されます。
初回の呼び出しとレスポンスの正しい読み取り
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from the environment
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1000,
messages=[{"role": "user", "content": "Explain what a systemd unit file is in three sentences."}],
)
for block in response.content:
if block.type == "text":
print(block.text)これら12行のうち、2つの要素がAPIの設計思想の核心です。1つ目は、引数なしの anthropic.Anthropic() です。これは環境変数からキーを読み取ります。文字列リテラルとして渡さないでください。2つ目は、response.content が文字列ではなく、content blocks のリストである点です。これをそのまま出力すると、初心者がよく遭遇する以下の出力になります。
[TextBlock(citations=None, text='A systemd unit file is...', type='text')]これはバグではなく、オブジェクトの repr です。レスポンスには複数のブロックタイプ(text, tool calls, thinking)が含まれる可能性があるため、.text にアクセスする前に、ループで block.type == "text" を確認してください。初日からこのループ処理を実装しておけば、「出力が正しく表示されない」という混乱を回避できます。
モデルID には必ず claude-opus-4-8 を使用してください。現行世代の ID に日付は含まれません。日付のサフィックスを付与するように指示する古いブログ記事などの情報に惑わされないでください。日付を付けると 404 エラーが発生します(詳細は後述)。
実際のツール:解説
以下は、stdinから入力を受け取り、診断結果をストリーム出力し、エラーを処理する完全なプログラムです。
#!/usr/bin/env python3
"""explain: pipe an error or log excerpt in, get a diagnosis out."""
import sys
import anthropic
MODEL = "claude-opus-4-8"
def main() -> int:
text = sys.stdin.read().strip()
if not text:
print("usage: journalctl -u nginx -n 50 | explain", file=sys.stderr)
return 1
client = anthropic.Anthropic()
try:
with client.messages.stream(
model=MODEL,
max_tokens=1500,
system=(
"You are a senior Linux sysadmin. The user pipes you server "
"logs or error output. Name the most likely cause outright, "
"then give the commands to confirm and fix it. Be terse."
),
messages=[{"role": "user", "content": text}],
) as stream:
for chunk in stream.text_stream:
print(chunk, end="", flush=True)
print()
except anthropic.RateLimitError as e:
retry_after = e.response.headers.get("retry-after", "60")
print(f"rate limited; retry in {retry_after}s", file=sys.stderr)
return 2
except anthropic.APIStatusError as e:
print(f"API error {e.status_code}: {e.message}", file=sys.stderr)
return 2
except anthropic.APIConnectionError:
print("network error reaching the API", file=sys.stderr)
return 2
return 0
if __name__ == "__main__":
sys.exit(main())これを/opt/explain/explain.pyとして保存してください。その後、対話的な使用のためにキーをロードするラッパーを追加します。
sudo tee /usr/local/bin/explain >/dev/null <<'EOF'
#!/bin/sh
set -a; . /etc/claude-explain.env; set +a
exec /opt/explain/venv/bin/python /opt/explain/explain.py "$@"
EOF
sudo chmod 755 /usr/local/bin/explain(ラッパーはsudo経由で実行するか、環境変数ファイルに管理者ユーザーが所属するグループを追加する必要があります。ファイルの権限を644に緩めるのではなく、どちらか一方を適切に選択してください。)
ストリーミングを採用する理由。 client.messages.streamは、生成が完了するまで待機するのではなく、トークンが到着するたびに表示します。これにより、長い出力によるHTTPタイムアウトを回避できます。SDKは、まさにこの理由から、非ストリーミング呼び出しにおける非常に大きなmax_tokensの値を受け付けません。生成後のオブジェクトが必要な場合は、withブロック内でstream.get_final_message()を呼び出してください。
例外の順序について。 SDKは、最も具体的なものから順に型付き例外をスローします。RateLimitErrorは429エラーであり、待ち時間を示すretry-afterヘッダーを含みます。APIStatusErrorはその他の非2xxレスポンスをカバーします(サーバー側の問題についてはe.status_code >= 500を確認してください)。APIConnectionErrorは、リクエストに対してレスポンスが全く返されなかったことを意味します。リトライループを構築する前に注意してください。SDKは、429エラーと5xxエラーに対して、デフォルトで2回、指数バックオフを用いて自動的にリトライを行います(クライアント側でmax_retries)。 exceptが実行される頃には、リトライは既に終了しています。そのため、CLIにおける正しい動作は、スリープしてリクエストを送り続けることではなく、エラーを報告して終了することです。
コスト管理
APIには設定値以外の月間上限が組み込まれていないため、このセクションは重要です。設定ミスは、気づかないうちにコストを増大させます。
max_tokens は、1コールあたりの支出上限です。 出力トークンはコストが高くなります。Opus 4.8では、入力価格の5倍です。max_tokens は、モデルが生成できるトークン数のハードキャップです。プロンプトが暴走しても、設定した出力上限を超えることはありません。用途に合わせて設定してください。ログ診断なら1,500で十分です。分類タスクなら100が必要です。stop_reason: "max_tokens" で回答が途中で止まる場合は、上限が低すぎます。大きな値にデフォルト設定するのではなく、意図的に上限を引き上げてください。
送信前にカウントしてください。 入力にもコストがかかります。ログはデータ量が大きくなりがちです。APIには、無料で使用できるカウント用エンドポイントがあります(メッセージ作成とは別のレート制限があります)。
count = client.messages.count_tokens(
model="claude-opus-4-8",
messages=[{"role": "user", "content": big_log_text}],
)
print(count.input_tokens)これを使用して、2 GBのログを誤ってツールに流し込むのを防いでください。この目的には tiktoken を使用しないでください。これはOpenAIのtokenizerであり、一般的なテキストではClaudeのトークン数を約15–20%少なく、コードではそれ以上に少なくカウントします。
忠誠心ではなく、タスクに基づいてモデルを選択してください。 2026年7月時点で、Opus 4.8 (claude-opus-4-8) は入力100万トークンあたり5ドル、出力100万トークンあたり25ドルです。Haiku 4.5 (claude-haiku-4-5) は200Kのコンテキストで1ドル/5ドルです。Sonnet 5 (claude-sonnet-5) はその中間で3ドル/15ドルですが、2026年8月31日までは導入価格として2ドル/10ドルが適用されます。具体例:2,000トークンのログ抜粋と500トークンの回答の場合、Opusでは約0.0225ドル、Haikuでは約0.0045ドルかかります。出力の品質を確認する段階ではOpusを使用し、その後に同じプロンプトをHaikuで試してください。大量の単純な変換タスクでは、Haikuは5分の1のコストでOpusと遜色ない結果を出すことが多いです。予算に組み込む前に、必ず料金ページで最新の数値を確認してください。
待機可能なタスクにはBatchesを使用してください。 Batches APIは、標準価格の50%で非同期にリクエストを処理します。ほとんどのバッチは1時間以内に完了します。夜間の集計、データのバックフィル、一括分類など、人間が待機する必要のないタスクに最適です。
繰り返されるコンテキストにはPrompt cachingを使用してください。 すべてのコールで同じ大きなシステムプロンプトやランブックを再送する場合、キャッシュ可能としてマークしてください。
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1000,
system=[{
"type": "text",
"text": RUNBOOK_TEXT, # the same 30K tokens on every call
"cache_control": {"type": "ephemeral"},
}],
messages=[{"role": "user", "content": question}],
)
print(response.usage.cache_read_input_tokens) # non-zero from the second call onキャッシュの書き込みコストは入力価格の約1.25倍、キャッシュの読み取りコストは約0.1倍です(5分間のTTLの場合)。そのため、ウィンドウ内の2回目のコールは、1回目のコストで済みます。注意点が2つあります。キャッシュされる接頭辞(prefix)は、モデルごとの最小要件(Opusでは数千トークン)を満たす必要があります。短いシステムプロンプトは、キャッシュされません。また、同一のコールで cache_read_input_tokens がゼロのままの場合、リクエストごとに接頭辞の内容が変化しています(タイムスタンプが原因であることが一般的です)。
何が入力としてカウントされるかを理解してください。 システムプロンプト、ツールの定義、そしてマルチターン会話における、毎ターン再送される会話履歴のすべてが、入力トークンとして課金されます。履歴を削減しないチャットループは、コストが二次関数的に増大します。会話型アプリケーションを構築する前に、Claudeのトークン使用量と課金の仕組み を理解しておくことを推奨します。
systemd での実行
environment-file を使用するメリットは、毎朝前日のエラーを要約する timer を作成できることです。
# /etc/systemd/system/log-digest.service
[Unit]
Description=Daily error-log digest via the Claude API
[Service]
Type=oneshot
User=explain
Group=systemd-journal
EnvironmentFile=/etc/claude-explain.env
ExecStart=/bin/sh -c 'journalctl -p err --since yesterday | /opt/explain/venv/bin/python /opt/explain/explain.py >> /var/log/log-digest.txt'# /etc/systemd/system/log-digest.timer
[Unit]
Description=Run the log digest every morning
[Timer]
OnCalendar=06:15
Persistent=true
[Install]
WantedBy=timers.targetsudo useradd -r -s /usr/sbin/nologin explain
sudo touch /var/log/log-digest.txt && sudo chown explain /var/log/log-digest.txt
sudo systemctl daemon-reload
sudo systemctl enable --now log-digest.timer
sudo systemctl start log-digest.service # test it once, right nowEnvironmentFile= の利点を確認してください。systemd は、root 所有で mode-600 のファイルを、権限のない explain ユーザーに切り替える 前 に読み込みます。そのため、プロセスは変数を受け取れますが、ユーザーは key ファイルを読み取れません。systemd-journal グループはログへのアクセス権を付与します。手動で systemctl start を実行して journalctl -u log-digest.service を確認してください。タイポを見つけるために 06:15 まで待つ必要はありません。このパターンが shell pipeline の規模を超えた場合も、同じ key-in-env-file の手法を、同一マシン上の Claude を活用した n8n workflow にそのまま適用できます。
発生するエラーと表示される文字列
有効なキーでの401エラー。 例外メッセージは以下の通りです:
anthropic.AuthenticationError: Error code: 401 - {'type': 'error', 'error': {'type': 'authentication_error', 'message': 'invalid x-api-key'}, 'request_id': 'req_011CSHoEeqs5C35K2UUqR7Fy'}シェルではキーが機能するのにサービスが401を返す場合、サービスにキーが届いていません。systemdは.bashrcを読み取らないことに注意してください。EnvironmentFile=が正しいパスを指しているか確認してください。その他の原因:envファイル内に引用符が含まれている(ANTHROPIC_API_KEY="sk-ant-..." — systemdは引用符を除去しますが、シェルラッパーの. fileは引用符を値として保持します)、末尾の空白、または先週Consoleで失効させたキー。
モデルの入力ミスによる404エラー。 最も一般的なケースは、現在のモデルIDに日付のサフィックスを付けてしまうことです:
anthropic.NotFoundError: Error code: 404 - {'type': 'error', 'error': {'type': 'not_found_error', 'message': 'model: claude-opus-4-8-20260115'}, 'request_id': 'req_011CSJqymAvNw4bT3qmDdMbA'}現行世代のIDは、記載されている通り正確である必要があります — claude-opus-4-8, claude-haiku-4-5, claude-sonnet-5。モデルのドキュメントからコピーしてください。記憶や古いチュートリアルから入力しないでください。
429 rate_limit_error。 エラータイプ文字列はrate_limit_errorであり、レスポンスには待機秒数を示すretry-afterヘッダーが含まれます。SDKは例外を出す前に、バックオフを伴うリトライをすでに2回実行しています。継続的な429エラーは、リクエスト頻度が実際にティアの制限を超えていることを意味します。リトライループを短縮するのではなく、処理をバッチ化するか、間隔を広げてください。
テキストではなくオブジェクトが出力される。 出力は[TextBlock(citations=None, text='...', type='text')]のようになります。ブロックを反復処理して、block.type == "text"である各ブロックから.textを読み取るのではなく、response.contentをそのまま出力しています。上記のSDKの例はすべて正しく実装されています。そのループをコピーして使用してください。
error: externally-managed-environment。 Ubuntu 24.04のシステムPythonに対してpip installを実行しています。venvを使用してください。重要なサーバーで--break-system-packagesを行わないでください。
回答の切り捨て。 response.stop_reason == "max_tokens"は、モデルが生成の途中で出力上限に達したことを意味します。これは仕様通りの動作です。必要に応じて上限を引き上げてください。
最初のアプリが動作したら、ClaudeでAIエージェントを構築するで、それらのAPIコールをツールを使用するエージェントへと進化させることができます。
FAQ
Claude API の試用コストはどのくらいですか?
このようなツールとしては、極めて低コストです。2026年7月時点で、Opus 4.8 は入力 100万トークンあたり $5、出力 100万トークンあたり $25 です。一般的なログ診断(入力数千トークン、出力数百トークン)であれば、約2セント程度です。Haiku 4.5 ($1/$5) を使用すれば、0.5セント未満に収まります。1ヶ月間、毎日ダイジェストを作成しても、コーヒー1杯の代金より安く済みます。懸念すべきはリクエストごとの価格ではなく、無限ループや無制限の max_tokens です。そのため、本ガイドではこれらを明示的に設定する方法を説明します。
Claude API に無料枠はありますか?
2026年7月現在、継続的な無料枠はありません。Anthropic の価格ドキュメントによると、新規ユーザーには API テスト用の少額の無料クレジットが付与されます。これは初回のみの試用であり、正確な金額はサインアップ時の Console に表示されます。その後はアカウントに資金をチャージする必要があります。最先端の品質よりも、リクエストあたりの限界費用をゼロにすることを目的とする場合は、Ollama でオープンウェイトモデルをセルフホストし、トークンの代わりに RAM を消費する方法があります。
サーバー上で API key を安全に管理するにはどうすればよいですか?
コード内、git 内、.bashrc からのエクスポート、および履歴が残るシェルへの直接入力は絶対に避けてください。root 所有のファイルに 600 権限で保存してください。プロセスごとに読み込むようにします。対話的な使用にはラッパースクリプトを、systemd には EnvironmentFile= を使用してください。また、漏洩した際の被害を最小限に抑えるため、1つの key は1つのサーバーまたはプロジェクトに限定してください。もし key が paste site や git commit に露出した場合は、直ちに Console で無効化してください。commit を削除しても、漏洩した事実は消えません。
どの Claude モデルから始めるべきですか?
出力が構築に十分な品質であるかを確認する段階では、まず claude-opus-4-8 を使用してください。アイデアを最高品質で評価すべきであり、趣味程度の利用量であればコスト差はわずかです。プロンプトが確定したら、実際の入力を claude-haiku-4-5 で再実行してください。要約、分類、ログのトリアージにおいては、claude-haiku-4-5 は 5分の1 のコストで同等の性能を発揮することがよくあります。デフォルトではなく、測定結果に基づいて Haiku または Sonnet に移行してください。