Claude Code SDK ではじめる 定額 AI Agent 開発入門

こちらは LayerX AI Agentブログリレー 7日目の記事です。

こんにちは。バクラク勤怠のソフトウェアエンジニアの @upamune です。
最近は社内のいろんなリソースをMarkdownに変換する怪物になっています。

1. はじめに:定額で始めるAI Agent開発

皆さんAI Agent開発していますか?AI Agentを開発する時の障壁の一つとして、LLMを呼び出す際のAPIコールが従量課金のため、なかなか個人で気軽に試せないというのがあると思います。
そこで、今回はClaude Code SDKを利用してAI Agentを作成することで、Pro/Maxプランに加入することで定額でAI Agentを開発できる選択肢があることを紹介します。

2. なぜClaude Code SDKなのか

Claude Codeを利用している方は多いと思いますが、Claude Code SDKを利用したことはありますでしょうか。Claude Code SDKは、Claude Codeコマンドを利用してAI Agentを開発するためのPython/TypeScript向けのSDKです。

Claude Pro/Max プランに加入していれば定額でClaude Code SDKも利用できるため、最安$20/月(2025年9月17日現在)で定額で利用できます。

2025年9月時点でアップデートされ、Claude Code SDKでCustom Toolsを定義できたり、Hooksも差し込めるようになりました。Custom Toolsを定義してコード上の関数をtoolとして利用できるようになったのは特に大きなアップデートでAI Agentを開発しやすくなりました。

3. 実装解説:タスク管理Agent

Claude Code SDKにはTypeScriptとPythonがありますが、ここではPythonを利用して解説します。

Claude Code SDKには query()ClaudeSDKClient がありますが、AI Agent用途では ClaudeSDKClient を利用しましょう。 query() はワンオフ利用のユースケースで、Custom ToolsやHooksも使えませんし、セッション管理もしてくれないのでAI Agentでは query() を使う必要がありません。

query()ClaudeSDKClient の違いはこちらのドキュメントにまとまっています。
Choosing Between query() and ClaudeSDKClient

ここでは、「タスク管理Agent」を作ってみましょう。まず、動作イメージのデモからご覧ください。

Image from Gyazo

やるべきことはシンプルで、基本的には以下を最小限やれば良いです。

  1. Custom Toolsの実装
  2. システムプロンプトの設計
    • Custom Toolsを使うための指示も含む

会話のセッション管理は ClaudeSDKClient がやってくれるので便利ですね。

ClaudeSDKClient にはシステムプロンプトをはじめとする様々なオプションがあります。 can_use_toolhooks などもここに存在して、追加されていっているのでドキュメントを定期的に確認することをおすすめします。

ClaudeCodeOptions – Python SDK reference

タスク管理に必要なツールを揃えましょう。ここでは簡単にするために以下に絞って実装することにします。

  • タスクの追加
  • タスクの一覧
  • タスクのステータス変更

ちゃんと使えるようにするために、永続化も考えて今回はタスク管理のストレージはSQLite3にします。

タスク追加のツールは以下のように書けます。
ちょっと長いように見えますが、バリデーションを行ってデータベースにタスクを挿入しているだけです。

AI Agentに対して効果的なツール設計はどういうものかというのは、Anthropicのこのブログ記事にまとまっているので一読することをおすすめします。

Writing effective tools for agents — with agents

このツールでいうと、バリデーションエラーが起きた際に、ステータスが不正な値ということではなく、どういうステータスが使えるのかをエラーとして返すことで、AI Agentが具体的にどうすればいいかを分かりやすくしています。

@tool( "add_task", "新しいタスクを追加します。タスク名と優先度(高、中、低)を指定してタスクを作成できます。", { "name": str, "priority": str})
async def add_task(args: Dict[str, Any]) -> Dict[str, Any]:
    task_name = args["name"]
    priority = args.get("priority", "中")

    if priority not in TASK_PRIORITIES:
        return {
            "content": [
                {
                    "type": "text",
                    "text": f"❌ エラー: 優先度は {', '.join(TASK_PRIORITIES)} のいずれかを指定してください。",
                }
            ]
        }

    ensure_database()
    conn = get_db_connection()
    cursor = conn.cursor()

    cursor.execute(
        """INSERT INTO tasks (name, priority, status)
           VALUES (?, ?, ?)""",
        (task_name, priority, "未着手"),
    )
    task_id = cursor.lastrowid
    conn.commit()
    conn.close()

    return {
        "content": [
            {
                "type": "text",
                "text": (
                    "✅ タスクを追加しました:\\n"
                    f"#️⃣ ID: {task_id}\\n"
                    f"📝 {task_name}\\n"
                    f"🔥 優先度: {priority}"
                ),
            }
        ]
    }

この調子で他のツールも追加していきますが、「タスク一覧」はSELECT、「タスクのステータス変更」はUPDATEなので割愛します。

次にこのツールをClaude Code SDK経由で使えるようにしてあげましょう。 create_sdk_mcp_server を使って、tools に先ほど定義した関数を登録できます。

task_server = create_sdk_mcp_server(
    name="task-manager",
    version="1.0.0",
    tools=[add_task, list_tasks, change_task_status],
)

最後に冒頭に紹介した ClaudeCodeOptions に渡してあげれば利用できるようになります。

options = ClaudeCodeOptions(
    mcp_servers={"task_manager": task_server},
    allowed_tools=[
        "mcp__task_manager__add_task",
        "mcp__task_manager__list_tasks",
        "mcp__task_manager__change_task_status",
    ],
    // ...
)

他にも Hooks を利用して今回作成したSQLite3のデータベース以外を読まないように制御します。

Hooks Demo Image

以下のような Hooks でツール利用前に呼ばれる関数を作って、今回のデータベースファイル以外の読み取りを拒否しています。

async def pre_tool_hook(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    tool_name = input_data.get("tool_name", "")
    tool_input = input_data.get("tool_input", {}) or {}

    if tool_name in {"Read", "Edit"}:
        fp = tool_input.get("file_path")
        requested = Path(fp).resolve()
        allowed = DB_FILE.resolve()
        if requested != allowed:
            return deny(f"Read/Edit は {allowed} のみ許可。要求: {fp}")

        return {}

    return deny(f"{tool_name} は許可されていません")

この pre_tool_hookClaudeCodeOptions に渡せます。

options = ClaudeCodeOptions(
    // ...
    hooks={"PreToolUse": [HookMatcher(hooks=[pre_tool_hook])]},
)

詳細は以下のリンクをご確認ください。

Using Hooks for Tool Control

残るはシステムプロンプトの設計ですが、作成したツールを使えるツールと明示しつつ、どういう役割を持つAgentなのかも明示します。システムプロンプトの設計はClaude Code SDKのみのものではないので、ここでの詳細の説明は割愛します。

今回開発したAI Agent のコードはGitHub上にあります。Claude Codeコマンドとuvさえあれば、このファイルを実行するだけでタスク管理Agentを試すことができます。

github.com

5. まとめ

Claude Code SDKではじめるAI Agent開発を見ていきました。
Claude Codeも進化していますが、Claude Code SDKも進化しており、徐々に使えるものになってきています。
Claude Code SDKは従来のLLM API費用の心配なく、定額でAI Agent開発を体験できる優れた選択肢です。Custom ToolsやHooksといった機能により、実用的なAI Agentの開発も十分可能になりました。

ぜひ皆さんも、まずは今回紹介したタスク管理Agentのようなシンプルなものから始めて、AI Agent開発の面白さを体験してみてください。

最後に改めて、この記事はLayerX AI Agentブログリレーの7日目の記事です。毎日AI Agentに関する知見をお届けします!!LayerXテック公式Xを是非フォローして見逃さないようにお願いします!

AI Coding / AI Agent 開発に興味がある人は、ぜひお話しましょう!

jobs.layerx.co.jp




Source link

関連記事

コメント

この記事へのコメントはありません。