AIコーディング 2026.04.22

Claude Code廃止後の代替え案|月$2で自動コード生成AIを自作する手順【Python実装付き】

タグ:生成AI / Claude / 開発者 / コスト削減 / API活用

なぜAPIで自作する方が安いのか

Claude Code(CLI)はAnthropicのAPIを内部で呼んでいます。ProプランはClaude.aiのUI使用料込みの価格設定なので、APIを直接使えば同じモデルに安く直接アクセスできます。

方法月額目安制約
Claude Pro($20)$20固定Claude.ai UI込み
API直接(Haiku)$1〜$5従量課金、自分で実装
API直接(Sonnet)$5〜$20従量課金、自分で実装

Step 1:APIキーの取得

# 1. https://console.anthropic.com でアカウント作成
# 2. API Keys → Create Key でAPIキーを取得
# 3. .envファイルに保存

echo "ANTHROPIC_API_KEY=sk-ant-..." >> .env
echo ".env" >> .gitignore  # 必ずgitignoreに追加
# 依存関係のインストール
pip install anthropic python-dotenv

Step 2:最小限の自動コードループ

# coding_agent.py
import os
import subprocess
from pathlib import Path
from anthropic import Anthropic
from dotenv import load_dotenv

load_dotenv()
client = Anthropic()

SYSTEM_PROMPT = """あなたはPythonコードを生成・修正する専門のAIエージェントです。
コードのみを返し、説明は最小限にしてください。
コードブロックは```python ... ```の形式で返してください。"""

def extract_code(response_text: str) -> str | None:
    """レスポンスからコードブロックを抽出する"""
    import re
    pattern = r'```(?:python)?\n(.*?)```'
    matches = re.findall(pattern, response_text, re.DOTALL)
    return matches[0] if matches else None

def run_code(code: str) -> tuple[str, bool]:
    """コードを実行して結果を返す"""
    tmp_file = Path("/tmp/agent_code.py")
    tmp_file.write_text(code)
    
    result = subprocess.run(
        ["python", str(tmp_file)],
        capture_output=True,
        text=True,
        timeout=30
    )
    
    if result.returncode == 0:
        return result.stdout, True
    else:
        return result.stderr, False

def coding_loop(task: str, max_iterations: int = 3) -> str:
    """コード生成→実行→エラー修正のループ"""
    messages = [{"role": "user", "content": task}]
    
    for iteration in range(max_iterations):
        print(f"\n--- イテレーション {iteration + 1} ---")
        
        response = client.messages.create(
            model="claude-haiku-4-5-20251001",  # コスト削減のためHaikuを使用
            max_tokens=2048,
            system=SYSTEM_PROMPT,
            messages=messages
        )
        
        ai_response = response.content[0].text
        print(f"AI: {ai_response[:200]}...")
        
        code = extract_code(ai_response)
        if not code:
            print("コードが見つかりません。ループを終了します。")
            return ai_response
        
        print(f"生成コード:\n{code}")
        output, success = run_code(code)
        
        if success:
            print(f"✅ 実行成功:\n{output}")
            return code
        else:
            print(f"❌ エラー:\n{output}")
            # エラーをAIに返して修正を依頼
            messages.append({"role": "assistant", "content": ai_response})
            messages.append({
                "role": "user",
                "content": f"以下のエラーが発生しました。修正してください:\n{output}"
            })
    
    return "最大イテレーション回数に達しました"

# 使用例
if __name__ == "__main__":
    task = """
    CSVファイル(data.csv)を読み込んで、
    age列の平均・中央値・最大・最小を計算して表示するPythonコードを書いてください。
    ファイルが存在しない場合はサンプルデータを生成してください。
    """
    result = coding_loop(task)
    print(f"\n最終コード:\n{result}")

Step 3:ファイル読み書き付きの本格エージェント

# file_coding_agent.py
import os
from pathlib import Path
from anthropic import Anthropic
from dotenv import load_dotenv

load_dotenv()
client = Anthropic()

def read_file(filepath: str) -> str:
    """ファイルを読み込む(エージェントのツール)"""
    path = Path(filepath)
    if not path.exists():
        return f"エラー: {filepath} が見つかりません"
    return path.read_text(encoding='utf-8')

def write_file(filepath: str, content: str) -> str:
    """ファイルに書き込む(エージェントのツール)"""
    path = Path(filepath)
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding='utf-8')
    return f"✅ {filepath} に書き込みました({len(content)}文字)"

def agent_with_files(task: str, target_files: list[str]) -> None:
    """ファイルを読み込んでコードを修正するエージェント"""
    
    # 対象ファイルの内容を収集
    file_contents = {}
    for filepath in target_files:
        content = read_file(filepath)
        file_contents[filepath] = content
    
    # コンテキストを構築
    context = "\n\n".join([
        f"### {path}\n```\n{content}\n```"
        for path, content in file_contents.items()
    ])
    
    prompt = f"""以下のファイルを修正してください。

タスク: {task}

現在のファイル内容:
{context}

修正後の各ファイルの完全なコードを返してください。
形式:
### filepath
```python
コード

"""

response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=4096,
    messages=[{"role": "user", "content": prompt}]
)

result = response.content[0].text

# レスポンスから各ファイルのコードを抽出して書き込む
import re
pattern = r'### ([\w./]+)\n```(?:python)?\n(.*?)```'
matches = re.findall(pattern, result, re.DOTALL)

for filepath, code in matches:
    output = write_file(filepath, code.strip())
    print(output)

print(f"\nトークン使用量: {response.usage.input_tokens}入力 / {response.usage.output_tokens}出力")

使用例

agent_with_files( task=“main.pyのエラーハンドリングを改善して、全ての例外をlogger経由で記録するようにして”, target_files=[“main.py”, “utils/helpers.py”] )


## Step 4:コスト追跡

```python
# cost_tracker.py
from dataclasses import dataclass, field

PRICING = {
    "claude-haiku-4-5-20251001": {"input": 0.80, "output": 4.00},    # per 1M tokens
    "claude-sonnet-4-5": {"input": 3.00, "output": 15.00},
}

@dataclass
class CostTracker:
    model: str
    input_tokens: int = 0
    output_tokens: int = 0
    calls: int = 0
    
    def add(self, input_tokens: int, output_tokens: int) -> None:
        self.input_tokens += input_tokens
        self.output_tokens += output_tokens
        self.calls += 1
    
    @property
    def cost_usd(self) -> float:
        prices = PRICING.get(self.model, {"input": 3.0, "output": 15.0})
        return (
            self.input_tokens * prices["input"] / 1_000_000 +
            self.output_tokens * prices["output"] / 1_000_000
        )
    
    def report(self) -> None:
        print(f"モデル: {self.model}")
        print(f"呼び出し回数: {self.calls}")
        print(f"トークン: {self.input_tokens:,}入力 / {self.output_tokens:,}出力")
        print(f"コスト: ${self.cost_usd:.4f} USD")

# 使用例
tracker = CostTracker(model="claude-haiku-4-5-20251001")

response = client.messages.create(...)
tracker.add(response.usage.input_tokens, response.usage.output_tokens)

tracker.report()
# モデル: claude-haiku-4-5-20251001
# 呼び出し回数: 1
# トークン: 500入力 / 800出力
# コスト: $0.0036 USD

Step 5:GitHub Actionsで自動化

# .github/workflows/ai-code-fix.yml
name: AI Code Fix on Failure

on:
  workflow_run:
    workflows: ["CI"]
    types: [completed]
    branches: [main]

jobs:
  ai-fix:
    if: ${{ github.event.workflow_run.conclusion == 'failure' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      
      - name: Install dependencies
        run: pip install anthropic

      - name: Run AI fix agent
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          python - <<'EOF'
          import anthropic, subprocess, os
          
          client = anthropic.Anthropic()
          
          # テスト失敗ログを取得
          result = subprocess.run(['pytest', '--tb=short', '-q'], 
                                  capture_output=True, text=True)
          
          if result.returncode == 0:
              print("テストはパスしています")
              exit(0)
          
          error_log = result.stdout + result.stderr
          
          response = client.messages.create(
              model="claude-haiku-4-5-20251001",
              max_tokens=1024,
              messages=[{
                  "role": "user",
                  "content": f"テストが失敗しています。原因と修正方法を教えてください:\n{error_log[:2000]}"
              }]
          )
          
          print("AI の修正提案:")
          print(response.content[0].text)
          EOF

コスト比較(月間)

使用パターンClaude ProAPI(Haiku)API(Sonnet)
1日5タスク$20固定~$0.50~$2.50
1日20タスク$20固定~$2.00~$10.00
1日100タスク制限あり~$10.00~$50.00

月10〜20タスク程度ならHaiku APIが最安。重いタスクはSonnet、軽い自動化はHaikuと使い分けると費用対効果が高まります。


あわせて読みたい

参考ソース