Claudeのコードを自作する方法

Ashley Innocent

Ashley Innocent

2 4月 2026

Claudeのコードを自作する方法

TL;DR(手短に言うと)

Claude Codeのソースコード流出により、2026年3月31日に512,000行のTypeScriptコードベースが公開されました。そのアーキテクチャは、Claude APIを呼び出し、ツール呼び出しをディスパッチし、結果をフィードバックするというwhileループに集約されます。Python、Anthropic SDK、および約200行のコードで、このコアロジックを自分で構築できます。このガイドでは、各コンポーネントを分解し、それらを再作成する方法を示します。

はじめに

2026年3月31日、Anthropicは、@anthropic-ai/claude-code npmパッケージのバージョン2.1.88内に59.8 MBのソースマップファイルを公開しました。ソースマップは、縮小されたJavaScriptを元のソースコードに逆変換するためのデバッグ成果物です。Anthropicのビルドツール(Bunのバンドラー)がこれらをデフォルトで生成するため、TypeScriptコードベース全体が復元可能でした。

数時間以内に、開発者たちはそのコードを数十のGitHubリポジトリにミラーリングしました。コミュニティは、マスターエージェントループから「undercover mode(覆面モード)」や偽のツールインジェクションといった隠れた機能まで、あらゆるモジュールを素早く分析しました。

反応は二分されました。Anthropicのセキュリティ対策を批判する者もいれば、そのアーキテクチャに魅了される者もいました。しかし、最も建設的な反応は、「これを自分で作れるか?」と問いかけた開発者たちから来ました。

答えは「はい」です。コアとなるパターンはシンプルです。このガイドでは、各アーキテクチャレイヤーを順を追って説明し、Anthropicがなぜそのような選択をしたのかを解説し、出発点として使える動作するコードを提供します。また、カスタムエージェントのAPIインタラクションをApidogでテストする方法も学びます。これにより、複数ターンのAPI対話をデバッグすることが、生のcurlコマンドよりもはるかに簡単になります。

button

Claude Codeのアーキテクチャについて流出が明らかにしたこと

コードベースの概要

Claude Codeは、内部では「Tengu」というコードネームで呼ばれ、約1,900のファイルにまたがっています。モジュール構成は明確な層に分かれています。

cli/          - ターミナルUI (React + Ink)
tools/        - 40以上のツール実装
core/         - システムプロンプト、パーミッション、定数
assistant/    - エージェントのオーケストレーション
services/     - API呼び出し、圧縮、OAuth、テレメトリー

CLI自体は、Ink(ターミナル出力用のReactレンダラー)を介してレンダリングされるReactアプリです。レイアウトにはYoga(CSS flexboxエンジン)、スタイリングにはANSIエスケープコードを使用しています。すべての会話ビュー、入力エリア、ツール呼び出し表示、パーミッションダイアログはReactコンポーネントです。

これは、ほとんどのDIYプロジェクトでは過剰な設計です。動作するコーディングエージェントを構築するために、ReactベースのターミナルUIは必要ありません。シンプルなREPLループで十分です。

マスターエージェントループ

UI、テレメトリー、機能フラグを取り除くと、Claude Codeの核はwhileループです。Anthropicは内部でこれを「nO」と呼んでいます。これは以下のことを行います。

  1. Claude APIにメッセージを送信する(システムプロンプト+ツール定義)
  2. テキストおよび/またはtool_useブロックを含む応答を受信する
  3. 要求された各ツールを名前-ハンドラーディスパッチマップを介して実行する
  4. ツール結果をメッセージリストに追加する
  5. 応答にさらにツール呼び出しが含まれている場合、ステップ1に戻る
  6. 応答がツール呼び出しを含まないプレーンテキストである場合、ユーザーにそれを返す

「ターン」とは、一連の完全な往復です。Claudeがツール呼び出しのないテキストを生成するまで、ターンは続行されます。これがエージェントパターンのすべてです。

以下は、コアを捉えた最小限のPythonバージョンです。

import anthropic

client = anthropic.Anthropic()
MODEL = "claude-sonnet-4-6"

def agent_loop(system_prompt: str, tools: list, messages: list) -> str:
    """The core agent loop - keep calling until no more tool use."""
    while True:
        response = client.messages.create(
            model=MODEL,
            max_tokens=16384,
            system=system_prompt,
            tools=tools,
            messages=messages,
        )

        # Add assistant response to conversation
        messages.append({"role": "assistant", "content": response.content})

        # If the model stopped without requesting tools, we're done
        if response.stop_reason != "tool_use":
            # Extract the final text
            return "".join(
                block.text for block in response.content
                if hasattr(block, "text")
            )

        # Execute each tool call and collect results
        tool_results = []
        for block in response.content:
            if block.type == "tool_use":
                result = execute_tool(block.name, block.input)
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": result,
                })

        # Feed results back as a user message
        messages.append({"role": "user", "content": tool_results})

これは約30行です。Claude Codeの残りの複雑さは、ツール自体、パーミッションシステム、コンテキスト管理、およびメモリから来ています。

ツールシステムの構築

なぜ専用ツールが単一のbashコマンドより優れているのか

流出で最も明確なアーキテクチャの決定の一つは、Claude Codeが、すべてをbash経由でルーティングする代わりに、ファイル操作に専用ツールを使用していることです。

Readツール(catではない)、Editツール(sedではない)、Grepツール(grepではない)、Globツール(findではない)があります。システムプロンプトは、モデルにbashの同等機能よりもこれらを優先するよう明示的に指示しています。

なぜでしょうか?3つの理由があります。

必須のツールセット

流出によると、Claude Codeはデフォルトで20未満のツールを公開しており、60以上のツールは機能フラグの裏にあります。DIYエージェントには、次の5つが必要です。

TOOLS = [
    {
        "name": "read_file",
        "description": "Read a file from the filesystem. Returns contents with line numbers.",
        "input_schema": {
            "type": "object",
            "properties": {
                "file_path": {
                    "type": "string",
                    "description": "Absolute path to the file"
                },
                "offset": {
                    "type": "integer",
                    "description": "Line number to start reading from (0-indexed)"
                },
                "limit": {
                    "type": "integer",
                    "description": "Max lines to read. Defaults to 2000."
                }
            },
            "required": ["file_path"]
        }
    },
    {
        "name": "write_file",
        "description": "Write content to a file. Creates the file if it doesn't exist.",
        "input_schema": {
            "type": "object",
            "properties": {
                "file_path": {"type": "string", "description": "Absolute path"},
                "content": {"type": "string", "description": "File content to write"}
            },
            "required": ["file_path", "content"]
        }
    },
    {
        "name": "edit_file",
        "description": "Replace a specific string in a file. The old_string must be unique.",
        "input_schema": {
            "type": "object",
            "properties": {
                "file_path": {"type": "string", "description": "Absolute path"},
                "old_string": {"type": "string", "description": "Text to find"},
                "new_string": {"type": "string", "description": "Replacement text"}
            },
            "required": ["file_path", "old_string", "new_string"]
        }
    },
    {
        "name": "run_command",
        "description": "Execute a shell command and return stdout/stderr.",
        "input_schema": {
            "type": "object",
            "properties": {
                "command": {"type": "string", "description": "Shell command to run"},
                "timeout": {"type": "integer", "description": "Timeout in seconds. Default 120."}
            },
            "required": ["command"]
        }
    },
    {
        "name": "search_code",
        "description": "Search for a regex pattern across files in a directory.",
        "input_schema": {
            "type": "object",
            "properties": {
                "pattern": {"type": "string", "description": "Regex pattern"},
                "path": {"type": "string", "description": "Directory to search"},
                "file_glob": {"type": "string", "description": "File pattern filter, e.g. '*.py'"}
            },
            "required": ["pattern"]
        }
    }
]

ツールハンドラーのディスパッチ

ツール実行関数は、ツール名をハンドラー関数にマッピングします。

import subprocess
import os
import re

def execute_tool(name: str, params: dict) -> str:
    """Dispatch tool calls to their handlers."""
    handlers = {
        "read_file": handle_read_file,
        "write_file": handle_write_file,
        "edit_file": handle_edit_file,
        "run_command": handle_run_command,
        "search_code": handle_search_code,
    }

    handler = handlers.get(name)
    if not handler:
        return f"Error: Unknown tool '{name}'"

    try:
        return handler(params)
    except Exception as e:
        return f"Error: {str(e)}"


def handle_read_file(params: dict) -> str:
    path = params["file_path"]
    offset = params.get("offset", 0)
    limit = params.get("limit", 2000)

    with open(path, "r") as f:
        lines = f.readlines()

    selected = lines[offset:offset + limit]
    numbered = [f"{i + offset + 1}\t{line}" for i, line in enumerate(selected)]
    return "".join(numbered)


def handle_write_file(params: dict) -> str:
    path = params["file_path"]
    os.makedirs(os.path.dirname(path), exist_ok=True)
    with open(path, "w") as f:
        f.write(params["content"])
    return f"Successfully wrote to {path}"


def handle_edit_file(params: dict) -> str:
    path = params["file_path"]
    with open(path, "r") as f:
        content = f.read()

    old = params["old_string"]
    if content.count(old) == 0:
        return f"Error: '{old[:50]}...' not found in {path}"
    if content.count(old) > 1:
        return f"Error: '{old[:50]}...' matches {content.count(old)} locations. Be more specific."

    new_content = content.replace(old, params["new_string"], 1)
    with open(path, "w") as f:
        f.write(new_content)
    return f"Successfully edited {path}"


def handle_run_command(params: dict) -> str:
    cmd = params["command"]
    timeout = params.get("timeout", 120)

    # Basic safety: block dangerous patterns
    blocked = ["rm -rf /", "mkfs", "> /dev/"]
    for pattern in blocked:
        if pattern in cmd:
            return f"Error: Blocked dangerous command pattern: {pattern}"

    result = subprocess.run(
        cmd, shell=True, capture_output=True, text=True,
        timeout=timeout, cwd=os.getcwd()
    )

    output = ""
    if result.stdout:
        output += result.stdout
    if result.stderr:
        output += f"\nSTDERR:\n{result.stderr}"
    if not output.strip():
        output = f"Command completed with exit code {result.returncode}"

    # Truncate large outputs to save context tokens
    if len(output) > 30000:
        output = output[:15000] + "\n\n... [truncated] ...\n\n" + output[-15000:]

    return output


def handle_search_code(params: dict) -> str:
    pattern = params["pattern"]
    path = params.get("path", os.getcwd())
    file_glob = params.get("file_glob", "")

    cmd = ["grep", "-rn", "--include", file_glob, pattern, path] if file_glob else \
          ["grep", "-rn", pattern, path]

    result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)

    if not result.stdout.strip():
        return f"No matches found for pattern: {pattern}"

    lines = result.stdout.strip().split("\n")
    if len(lines) > 50:
        return "\n".join(lines[:50]) + f"\n\n... ({len(lines) - 50} more matches)"
    return result.stdout

コンテキスト管理:難しい問題

なぜコンテキストはプロンプトエンジニアリングよりも重要なのか

流出したソースコードは、Claude Codeがシステムプロンプト自体よりもコンテキスト管理に多くのエンジニアリング労力を費やしていることを示しています。コンテキストコンプレッサー(内部では「wU2」と呼ばれています)には5つの戦略があります。

DIYビルドの場合、次の2つが必要です。

自動圧縮(Auto-compaction)は、会話がコンテキストウィンドウの制限に近づいたときにトリガーされます。Claude Codeは、約92%の使用率でトリガーされ、サマリー自体に13,000トークンのバッファを確保します。

CLAUDE.mdの再注入(re-injection)は、長いセッション中にプロジェクトのガイドラインが逸脱しないようにします。Claude Codeは、初期化時ではなく、すべてのターンでプロジェクト設定を再注入します。これは、コーディングエージェントを軌道に乗せるための最も影響力のあるパターンです。

シンプルなコンプレッサーの構築

def maybe_compact(messages: list, system_prompt: str, max_tokens: int = 180000) -> list:
    """Compact conversation when it gets too long."""
    # Rough estimate: 4 chars per token
    total_chars = sum(
        len(str(m.get("content", ""))) for m in messages
    )
    estimated_tokens = total_chars // 4

    if estimated_tokens < max_tokens * 0.85:
        return messages  # Not yet at the limit

    # Ask the model to summarize the conversation so far
    summary_response = client.messages.create(
        model=MODEL,
        max_tokens=4096,
        system="Summarize this conversation. Keep all file paths, decisions made, errors encountered, and current task state. Be specific about what was changed and why.",
        messages=messages,
    )

    summary_text = summary_response.content[0].text

    # Replace conversation with summary + recent messages
    compacted = [
        {"role": "user", "content": f"[Conversation summary]\n{summary_text}"},
        {"role": "assistant", "content": "I have the context from our previous conversation. What should I work on next?"},
    ]

    # Keep the last 4 messages for immediate context
    compacted.extend(messages[-4:])

    return compacted

プロジェクトコンテキストの再注入

Claude Codeは.claude/CLAUDE.mdを読み込み、各ターンにそれを注入します。これを再現する方法は以下の通りです。

def build_system_prompt(project_dir: str) -> str:
    """Build system prompt with project context re-injection."""
    base_prompt = """You are a coding assistant that helps with software engineering tasks.
You have access to tools for reading, writing, editing files, running commands, and searching code.
Always read files before modifying them. Prefer edit_file over write_file for existing files.
Keep responses concise. Focus on the code, not explanations."""

    # Look for project guidelines
    claude_md_path = os.path.join(project_dir, ".claude", "CLAUDE.md")
    if os.path.exists(claude_md_path):
        with open(claude_md_path, "r") as f:
            project_context = f.read()
        base_prompt += f"\n\n# Project guidelines\n{project_context}"

    # Also check for a root CLAUDE.md
    root_md = os.path.join(project_dir, "CLAUDE.md")
    if os.path.exists(root_md):
        with open(root_md, "r") as f:
            root_context = f.read()
        base_prompt += f"\n\n# Repository guidelines\n{root_context}"

    return base_prompt

3層メモリシステム

流出したソースコードは、Claude Codeが3層メモリアーキテクチャを使用していることを示しています。これは、このシステムの中で最も過小評価されている部分の一つです。

レイヤー1:MEMORY.md(常にロードされる)

システムプロンプトに常に存在する軽量なインデックス。各エントリは1行で、150文字未満です。より深い知識を指し示す目次として機能します。200行/25KBに制限されています。

- [User preferences](memory/user-prefs.md) - prefers TypeScript, uses Vim keybindings
- [API conventions](memory/api-conventions.md) - REST with JSON:API spec, snake_case
- [Deploy process](memory/deploy.md) - uses GitHub Actions, deploys to AWS EKS

レイヤー2:トピックファイル(オンデマンドでロードされる)

インデックスが関連性を示唆した場合にロードされる詳細な知識ファイル。これらには、プロジェクトの慣習、アーキテクチャの決定、学習されたパターンが含まれます。

レイヤー3:セッショントランスクリプト(検索されるが、読み込まれない)

全体がロードされることのない完全なセッションログ。エージェントは特定の識別子をgrepで検索します。これにより、検索性を維持しながらコンテキストの肥大化を防ぎます。

最小限のメモリシステムの構築

import json

MEMORY_DIR = ".agent/memory"

def load_memory_index() -> str:
    """Load the memory index for system prompt injection."""
    index_path = os.path.join(MEMORY_DIR, "MEMORY.md")
    if os.path.exists(index_path):
        with open(index_path, "r") as f:
            return f.read()
    return ""


def save_memory(key: str, content: str, description: str):
    """Save a memory entry and update the index."""
    os.makedirs(MEMORY_DIR, exist_ok=True)

    # Write the memory file
    filename = f"{key.replace(' ', '-').lower()}.md"
    filepath = os.path.join(MEMORY_DIR, filename)
    with open(filepath, "w") as f:
        f.write(f"---\nname: {key}\ndescription: {description}\n---\n\n{content}")

    # Update the index
    index_path = os.path.join(MEMORY_DIR, "MEMORY.md")
    index_lines = []
    if os.path.exists(index_path):
        with open(index_path, "r") as f:
            index_lines = f.readlines()

    # Add or update entry
    new_entry = f"- [{key}]({filename}) - {description}\n"
    updated = False
    for i, line in enumerate(index_lines):
        if filename in line:
            index_lines[i] = new_entry
            updated = True
            break
    if not updated:
        index_lines.append(new_entry)

    with open(index_path, "w") as f:
        f.writelines(index_lines)

エージェントがセッション間で知識を永続化できるように、ツールリストにsave_memoryツールを追加してください。

パーミッションシステムの追加

流出により、5つのパーミッションモードが明らかになりました。default(対話型プロンプト)、auto(MLベースの承認)、bypassyolo(すべて承認)、denyです。すべてのツールアクションは、LOW、MEDIUM、HIGHリスクに分類されます。

DIYエージェントの場合、シンプルな3層システムで機能します。

# Risk levels for operations
RISK_LEVELS = {
    "read_file": "low",
    "search_code": "low",
    "edit_file": "medium",
    "write_file": "medium",
    "run_command": "high",
}

def check_permission(tool_name: str, params: dict, auto_approve_low: bool = True) -> bool:
    """Check if the user approves this tool call."""
    risk = RISK_LEVELS.get(tool_name, "high")

    if risk == "low" and auto_approve_low:
        return True

    # Show the user what's about to happen
    print(f"\n--- Permission check ({risk.upper()} risk) ---")
    print(f"Tool: {tool_name}")
    for key, value in params.items():
        display = str(value)[:200]
        print(f"  {key}: {display}")

    response = input("Allow? [y/n/always]: ").strip().lower()
    if response == "always":
        RISK_LEVELS[tool_name] = "low"  # Auto-approve this tool going forward
        return True
    return response == "y"

ApidogでエージェントのAPI呼び出しをテストする

コーディングエージェントを構築するということは、Claudeに対する何百ものAPI呼び出しを行うことを意味します。これらのインタラクション、特にツール使用を伴うマルチターンの会話をデバッグすることは、生ログだけでは困難です。

ApidogのAPIインタラクションとテスト画面

Apidogは、エージェントが送信する正確なAPIリクエストを検査およびテストするのに役立ちます。開発中にそれを使用する方法は次のとおりです。

APIリクエストのキャプチャとリプレイ

Apidogをプロキシとして設定し、エージェントのAnthropic APIへの呼び出しを傍受します。

  1. Apidogを開き、エージェント用の新しいプロジェクトを作成します。
  2. Anthropic Messages APIエンドポイントをインポートします:POST https://api.anthropic.com/v1/messages
  3. システムプロンプト、ツール配列、メッセージを含むリクエストボディを設定します。
  4. 変更されたパラメータでキャプチャされたリクエストをリプレイすることにより、個々のターンをテストします。

これにより、完全なエージェントループを実行せずに、特定のツール使用ターンを分離できます。モデルが予期しないツール呼び出しや幻覚的なパラメータを返した場合、Apidogのビジュアルエディタでリクエストボディを変更し、再送信して、異なる入力が応答をどのように変更するかを確認できます。

マルチターンの会話をデバッグする

エージェントのデバッグで最も難しいのは、会話の状態を再現することです。Apidogの環境変数を使用すると、会話のスナップショットを保存できます。

ツールスキーマを検証する

あなたのツール定義(APIに渡すJSONスキーマ)は、モデルが何を要求できるかを決定します。不正なスキーマは、モデルがツールをスキップしたり、間違ったパラメータを渡したりするサイレントな失敗を引き起こします。

ツールスキーマをApidogにインポートし、そのJSONスキーマバリデーターを使用して、問題がAPIに到達する前に問題を捕捉します。Apidogをダウンロードして、エージェントのAPIインタラクションのデバッグを開始してください。

button

すべてをまとめる:完全なREPL

以下は、すべてをまとめた、動作するREPLとしての完全なエージェントです。

#!/usr/bin/env python3
"""A minimal Claude Code-style coding agent."""

import anthropic
import os
import sys

client = anthropic.Anthropic()
MODEL = "claude-sonnet-4-6"
PROJECT_DIR = os.getcwd()


def main():
    system_prompt = build_system_prompt(PROJECT_DIR)
    memory = load_memory_index()
    if memory:
        system_prompt += f"\n\n# Memory\n{memory}"

    messages = []
    print("Coding agent ready. Type 'quit' to exit.\n")

    while True:
        user_input = input("> ").strip()
        if user_input.lower() in ("quit", "exit"):
            break
        if not user_input:
            continue

        messages.append({"role": "user", "content": user_input})

        # Compact if needed
        messages = maybe_compact(messages, system_prompt)

        # Re-inject project context (Claude Code does this every turn)
        current_system = build_system_prompt(PROJECT_DIR)
        memory = load_memory_index()
        if memory:
            current_system += f"\n\n# Memory\n{memory}"

        # Run the agent loop
        result = agent_loop(current_system, TOOLS, messages)
        print(f"\n{result}\n")


if __name__ == "__main__":
    main()

これにより、300行未満のPythonで動作するコーディングエージェントが提供されます。ファイルを読み込み、コードを編集し、コマンドを実行し、コードベースを検索し、コンテキストを管理し、セッション間でメモリを永続化します。

次に追加すべきこと

流出したソースコードは、コアループが動作した後で構築する価値のあるいくつかの機能を示しています。

並列作業のためのサブエージェント

Claude Codeは、独立したタスクのためにサブエージェント(「フォークされた」エージェントと呼ばれる)を生成します。サブエージェントは親コンテキストのコピーを受け取り、そのタスクを実行し、結果を返します。これにより、メインの会話が探索的な作業で汚染されるのを防ぎます。

パターン:集中したタスク記述とツールのサブセットを持つ新しいagent_loop()を生成します。結果を文字列として返します。

ファイル読み込みの重複排除

Claude Codeは、どのファイルが読み込まれたか、およびその変更時刻を追跡します。ファイルが最後に読み込まれてから変更されていない場合、読み込みをスキップし、モデルに「ファイルは前回読み込まれてから変更されていません」と伝えます。これにより、長いセッション中の再読み込みでトークンを節約できます。

出力の切り詰めとサンプリング

ツールが大量の出力(例えば、grep結果の10,000行以上)を返す場合、Claude Codeはそれを切り詰め、省略された結果の数をモデルに伝えます。これがないと、1つの大きなツール結果がコンテキストウィンドウ全体を消費してしまう可能性があります。

ファイル再注入による自動圧縮

流出したコンプレッサーは、ファイルの内容を破棄しません。会話を要約した後、最近アクセスしたファイルのコンテンツ(1ファイルあたり最大5,000トークン)を再注入します。これは、モデルが圧縮後もコードベースの作業知識を保持することを意味します。

流出から学んだこと

Claude Codeの流出は、AIエージェントコミュニティが理論化していたいくつかのパターンを確認しました。

コアループはシンプルである。エージェントパターン全体は30行に収まります。複雑さは、プロンプトエンジニアリングではなく、ツールとコンテキスト管理にあります。

専用ツールはbashよりも優れている。構造化された目的別ツールは、bashコマンドをパイプ処理するよりも、トークンあたりの情報密度が高い情報をモデルに提供します。

メモリにはレイヤーが必要である。常にロードされるインデックス、オンデマンドのトピックファイル、およびgrepのみのトランスクリプトは、コンテキストコストとリコール性のバランスを取ります。

コンテキスト管理こそが真の製品である。自動圧縮、プロジェクトガイドラインの再注入、および出力の切り詰めが、長いコーディングセッションを可能にするものです。

モデルではなくハーネスが製品である。モデルは知能を提供します。ハーネスは知覚(ファイル読み込み、コード検索)、アクション(ファイル書き込み、コマンド実行)、およびメモリを提供します。コーディングエージェントを構築することは、ハーネスを構築することです。

マルチターンのツール利用会話、複雑なリクエストスキーマ、応答検証など、カスタムエージェントのAPIインタラクションをテストおよびデバッグしたい場合は、Apidogを無料で試してください。ApidogがAPIデバッグを処理してくれるので、あなたはエージェントのロジックに集中できます。

FAQ(よくある質問)

Claude Codeの流出からのパターンを法的に使用できますか?

この流出は、独自のアルゴリズムではなく、アーキテクチャパターンを公開しました。ツールディスパッチを備えたwhileループを使用するコーディングエージェントを構築することは、Anthropic自身のAPIドキュメントに記載されている標準的なパターンです。Anthropicのコードをそのままコピーすべきではありませんが、独自のコードでアーキテクチャを再現することは標準的な慣行です。

DIYコーディングエージェントにはどのモデルを使用すべきですか?

Claude Sonnet 4.6は、コーディングタスクに適切な速度と能力のバランスを提供します。Claude Opus 4.6は、複雑なアーキテクチャの決定においてより良い結果を生み出しますが、コストが高く、実行速度が遅いです。シンプルなファイルの編集や検索には、Claude Haiku 4.5が機能し、コストは90%低くなります。

独自のコーディングエージェントを実行するにはどれくらいの費用がかかりますか?

Claude Sonnet 4.6を使った典型的なコーディングセッション(30~50ターン)のAPI料金は1~5ドルです。主なコストドライバーはコンテキストウィンドウのサイズであり、積極的な圧縮によってコストを抑えることができます。Claude Codeの流出したソースコードを見ると、コンテキスト使用率が92%に達すると圧縮がトリガーされ、これを制御していることがわかります。

Claude CodeがターミナルアプリにReactを使用する理由は何ですか?

Ink(ターミナル用のReact)を使用することで、チームはReactのコンポーネントモデルと状態管理を、パーミッションダイアログ、ストリーミング出力、ツール呼び出し表示などの複雑なUIインタラクションに再利用できます。DIYプロジェクトの場合、シンプルなinput() / print()のREPLで十分です。

コアループの次に構築すべき最も重要な機能は何ですか?

パーミッションシステムです。これがないと、モデルはユーザーの監視なしにファイルを上書きしたり、任意のコマンドを実行したりする可能性があります。簡単な「書き込み/実行前の確認」ゲートだけでも、ほとんどの偶発的な損害を防ぐことができます。

Claude Codeはツール呼び出しからのエラーをどのように処理しますか?

ツールエラーは、tool_resultメッセージ内のテキストコンテンツとして返されます。モデルはエラーを見て、再試行するか、別のアプローチを試すか、ユーザーに尋ねるかを決定します。特別なエラー処理はなく、モデルの推論が回復を処理します。

Claude以外のモデルでもこれを使用できますか?

はい。このツール利用パターンは、関数呼び出しをサポートするどのモデルでも機能します。GPT-4、Gemini、Llamaなどです。API呼び出しの形式を調整する必要がありますが、エージェントループ、ツール、およびメモリシステムはモデルに依存しません。

エージェントが危険なコマンドを実行するのを防ぐにはどうすればよいですか?

危険なパターン(rm -rf /mkfsなど)のブロックリストから始め、すべてのrun_command呼び出しに明示的な承認を要求します。Claude Codeは、すべての操作をLOW、MEDIUM、HIGHリスクに分類し、その分類に基づいてブロックまたはプロンプトを表示します。あなたのツールにも同様のシステムを構築してください。

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる