自分だけのAIエージェントプロジェクト — 総合ハンズオン


Written by Thierry K (human) · AI-assisted
🖥️ Python 3.10+ · claude-agent-sdk 0.1.48 · FastMCP 3.1.0

AIエージェント作成 claude-agent-sdk mcp personal-ai-assistant

🎯 いよいよフィナーレ!自分だけのAIアシスタントを作りましょう!

Claudie

みなさん、9回にわたる長い旅を一緒に歩んでくれて本当にありがとうございます!今日はシリーズ最終回です。EP1からひとつずつ集めてきたパズルのピースを全部組み合わせて、本当に動く自分だけのAIアシスタントを作りますよ。

Siwol

本当に?9回で学んだこと全部使って、ちゃんと使えるものが作れるの?

Claudie

もちろんです!EP1で初めて出会ったAgentic AI、今度は私たちが自分で作れるんです。一度に全部作るのではなく、5段階で少しずつ進化させていきますよ。まるでレゴブロックを積み上げるように!

2026年の最もホットなトレンドのひとつが、パーソナルAIアシスタントです。AIエージェント作成がここまで簡単になったのは、Claude Agent SDKFastMCPのおかげです。私たちも自分で作ることができます。今日はその全プロセスを一緒に歩んでいきましょう。

上のダイアグラムが今日の全体ロードマップです。AIエージェント作成の5段階 — Stage 1からStage 5まで、一段階ずつ機能を追加しながらアシスタントを進化させていきます。

🔧 Stage 1 — MCPツールの作成(EP7復習)

Siwol

アシスタントに能力を与えるから、まずツールから作るんだよね?

Claudie

その通りです!EP7で学んだMCP、覚えていますか?FastMCPの@mcp.tool()デコレータで6つのツールを作ります。メモ3つ、スケジュール2つ、天気1つです!

アシスタントに渡すツールをMCPサーバーとして作るのが最初のステップです。AIエージェント作成の要は、ツールから始めることです。FastMCPを使えば、Python関数にデコレータを付けるだけで完成です。

# tools_server.py (Stage 1)
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("personal-assistant")

@mcp.tool()
def save_memo(
    title: str, content: str
) -> str:
    """Save a memo with title/content."""
    memos = _load_json(MEMOS_FILE)
    memo = {
        "title": title,
        "content": content,
        "created":
            datetime.now().isoformat(),
    }
    memos.append(memo)
    _save_json(MEMOS_FILE, memos)
    return f"Memo saved: '{title}'"

@mcp.tool()
def get_schedule(date: str) -> str:
    """Get all events for a date."""
    schedule = _load_json(SCHEDULE_FILE)
    events = [
        e for e in schedule
        if e["date"] == date
    ]
    if not events:
        return f"No events on {date}"
    lines = []
    for e in events:
        lines.append(
            f"- {e['time']}: {e['event']}"
        )
    return (
        f"Schedule for {date}:\n"
        + "\n".join(lines)
    )

save_memoはメモをJSONファイルに保存し、get_scheduleは特定の日付のイベントを取得します。これらに加えて、search_memoslist_memosadd_scheduleget_weatherまで、合計6つのツールを作ります。全コードはGitHubで確認できます。

Siwol

関数ひとつ=ツールひとつ。シンプルだね。でも、これをどうやってエージェントと繋げるの?

🔌 Stage 2 — 基本アシスタントの接続(EP5+EP8復習)

Claudie

EP5でエージェントループを直接50行以上も書きましたよね?SDKを使えばquery()の1行で終わりです!EP8で学んだSDKがすべてのループを自動処理してくれますよ。

# simple_assistant.py (Stage 2)
import asyncio
from claude_agent_sdk import (
    query,
    ClaudeAgentOptions,
    MCPServerStdio,
    ResultMessage,
)

async def main():
    options = ClaudeAgentOptions(
        allowed_tools=[
            # Built-in tools
            "WebSearch", "Read", "Write",
            # MCP tools
            "mcp__assistant__save_memo",
            "mcp__assistant__search_memos",
            "mcp__assistant__list_memos",
            "mcp__assistant__add_schedule",
            "mcp__assistant__get_schedule",
            "mcp__assistant__get_weather",
        ],
        mcp_servers={
            "assistant": MCPServerStdio(
                command="python",
                args=["tools_server.py"],
            )
        },
        max_turns=10,
    )

    async for msg in query(
        prompt="Save a memo titled "
            "'Meeting' with content "
            "'Team sync at 3pm'.",
        options=options,
    ):
        if isinstance(msg, ResultMessage):
            if msg.subtype == "success":
                print(msg.result)

asyncio.run(main())

ポイントはMCPServerStdioです。SDKがtools_server.pyを子プロセスとして自動起動するので、ターミナルを2つ開く必要がありません。MCPツール6個+内蔵ツール3個、合計9個のツールを持つアシスタントが完成です!AIエージェント作成、思ったより簡単でしょう?

Siwol

動くけど…性格もないし、危険なファイルに勝手に書き込めちゃうよね。ちょっと不安じゃない?

🛡️ Stage 3 — 賢いアシスタント:HooksとSystem Prompt

Claudie

だからこそStage 3では2つのものを追加します。ひとつはEP6で学んだシステムプロンプトで性格を付けること、もうひとつは今日初めて学ぶ新しいコンセプト — Hooksです!

Hooks(フック)

エージェントがツールを使用する際に発生するイベントを傍受するコールバック関数です。PreToolUse(実行前)で危険な操作をブロックし、PostToolUse(実行後)ですべての活動を記録できます。エージェントのセキュリティシステムと考えてください。

Siwol

傍受?ツール呼び出しを途中でキャッチするってこと?

Claudie

その通りです!たとえ話で説明しますね。PreToolUseは玄関のです — 入る前に確認して、許可するかブロックするかを決めます。PostToolUseは監視カメラです — 起こったことを記録して、後で確認できるようにします。

上のダイアグラムを見れば流れが明確です。エージェントがツールを使おうとすると、まずPreToolUse Hookが実行されます。許可されればツールが実行され、その後PostToolUse Hookが記録します。

# smart_assistant.py (Stage 3)
# Hook 1: Safety guard (PreToolUse)
async def safety_guard(
    input_data, tool_use_id, context
):
    """Block writes to system paths."""
    tool = input_data["tool_name"]
    tool_input = input_data["tool_input"]

    if tool in ("Write", "Edit"):
        path = tool_input.get(
            "file_path", ""
        )
        blocked = [
            "/etc/", "/usr/",
            "C:\\Windows",
            "C:\\Program",
        ]
        if any(
            p in path for p in blocked
        ):
            return {
                "hookSpecificOutput": {
                    "hookEventName":
                        input_data[
                          "hook_event_name"
                        ],
                    "permissionDecision":
                        "deny",
                    "permissionDecisionReason":
                        "System path blocked",
                }
            }
    return {}  # Allow

# Hook 2: Activity logger (PostToolUse)
async def activity_logger(
    input_data, tool_use_id, context
):
    """Log all tool usage."""
    tool = input_data["tool_name"]
    print(f"  [LOG] Tool used: {tool}")
    return {}

safety_guardは、WriteやEditツールがシステムパスにアクセスしようとすると"deny"を返してブロックします。activity_loggerは、すべてのツール使用をコンソールに記録します。

これらのHooksの登録方法もシンプルです。

# Hooks registration in options
options = ClaudeAgentOptions(
    system_prompt=(
        "You are a friendly, helpful "
        "personal AI assistant. "
        "Your name is 'Buddy'."
    ),
    hooks={
        "PreToolUse": [
            HookMatcher(
                matcher="Write|Edit",
                hooks=[safety_guard],
            ),
        ],
        "PostToolUse": [
            HookMatcher(
                hooks=[activity_logger],
            ),
        ],
    },
    # ... tools and mcp_servers
)

HookMatchermatcherに正規表現パターンを指定すると、該当ツールにのみHookが適用されます。PostToolUseのようにmatcherを省略すると、すべてのツールに適用されます。さらに、システムプロンプトで「Buddy」というフレンドリーなキャラクター性格も付与しました!

👥 Stage 4 — チームアシスタント:マルチエージェント(EP9復習)

Claudie

ひとりで全部こなすアシスタントも良いですが、専門家チームを作ればもっとパワフルになりますよ!EP9で学んだオーケストレーターパターンを適用してみましょう。

Siwol

EP9のブログチームはResearcher、Writer、Reviewerだったから、今回はアシスタントチームを作るんだね?

同じパターン、異なる専門家!今回はScheduler(スケジュール)、Researcher(検索)、Assistant(メモ/ファイル)の3人でチームを構成します。

# team_assistant.py (Stage 4)
agents = {
    "scheduler": AgentDefinition(
        description=(
            "Manages calendar and "
            "schedules."
        ),
        prompt=(
            "You are a precise "
            "scheduling assistant."
        ),
        tools=[
            "mcp__assistant__"
            "add_schedule",
            "mcp__assistant__"
            "get_schedule",
        ],
    ),
    "researcher": AgentDefinition(
        description=(
            "Searches the web for "
            "information."
        ),
        prompt=(
            "You are a thorough "
            "research assistant."
        ),
        tools=[
            "WebSearch", "WebFetch",
        ],
    ),
    "assistant": AgentDefinition(
        description=(
            "Handles memos, files, "
            "and general tasks."
        ),
        prompt=(
            "You are a helpful "
            "personal assistant."
        ),
        tools=[
            "Read", "Write",
            "mcp__assistant__save_memo",
            "mcp__assistant__"
            "search_memos",
        ],
    ),
}

# Orchestrator
options = ClaudeAgentOptions(
    system_prompt=(
        "You are a team manager "
        "coordinating 3 specialists."
    ),
    allowed_tools=["Agent"],
    agents=agents,
    max_turns=15,
)

マネージャーエージェントがユーザーのリクエストを分析して、適切な専門家に委任します。「歯医者の予約をして、ソウルのカフェを検索してメモに保存して」と言えば、Scheduler → Researcher → Assistantの順にチェーンが繋がります!AIエージェント作成をこのようなチーム構造で発展させると、はるかにパワフルになります。

上のアーキテクチャダイアグラムは、Stage 4までの全体構造を示しています。MCPサーバーがツールを提供し、SDKがエージェントループを回し、オーケストレーターが3人の専門家を調整します。

💾 Stage 5 — 記憶するアシスタント:Sessions(EP4復習+新規)

Siwol

ここまではかなりいいけど、ひとつ問題がある。会話が終わると全部忘れちゃうよね?

Claudie

EP4でコンテキストとメモリを学びましたよね?今日はそれをSDKで実装する方法をお教えします — そう、Sessionsです!

Sessions(セッション)

複数のquery()呼び出しをひとつの会話として繋げる機能です。session_idをキャプチャしてresumeパラメータで渡すと、以前の会話のフルコンテキストが復元されます。しおりのように「どこまで読んだか」を覚えておくイメージです。

# persistent_assistant.py (Stage 5)
async def main():
    # Turn 1: Save something
    session_id = None

    async for msg in query(
        prompt=(
            "Save a memo titled "
            "'Project Ideas' with "
            "content 'Build a recipe "
            "recommender using "
            "MCP tools'."
        ),
        options=build_options(),
    ):
        if isinstance(
            msg, ResultMessage
        ):
            # Capture session_id!
            session_id = msg.session_id
            if msg.subtype == "success":
                print(msg.result)

    print(f"Session: {session_id}")

    # Turn 2: Ask WITH memory
    async for msg in query(
        prompt=(
            "What memo did I just save?"
        ),
        options=ClaudeAgentOptions(
            **{
                **build_options()
                    .__dict__,
                "resume": session_id,
            }
        ),
    ):
        if isinstance(
            msg, ResultMessage
        ):
            if msg.subtype == "success":
                print(msg.result)

ポイントはたった2行です。ResultMessageからsession_idをキャプチャし、次のquery()resume=session_idを渡すだけ!AIエージェント作成の最後のパズルピースがはまりました。

WITHとWITHOUTの比較

Sessionsの威力を比較してみましょう。

シナリオ質問応答
WITHOUT session「さっき何を保存した?」「以前の会話履歴がないため分かりません。」
WITH session「さっき何を保存した?」「’Project Ideas’というメモを保存しましたよ!」

セッションなしで呼び出すと、毎回新しい会話が始まり、以前の内容をまったく覚えていません。セッションを続けると、まるで同じ会話を続けているかのように完璧に記憶しています。

もっと簡単な方法:ClaudeSDKClient

session_idを自分で管理するのが面倒なら、ClaudeSDKClientを使いましょう。async with ClaudeSDKClient() as c:ブロック内でawait c.query()を複数回呼び出すだけで、セッションが自動的に維持されます!

📋 EP1〜EP10 総まとめ

Claudie

10回で学んだすべての概念が今日ひとつにまとまりました!一目で整理してみましょう。

エピソード核心コンセプトEP10での活用
EP1Agentic AIとの出会い自分で実装!「AIが自ら動く」の実体
EP2LLM(頭脳)アシスタントのすべての判断はLLMが処理
EP3Tool Use(手)MCPツール6個+内蔵ツール3個
EP4コンテキストとメモリSessionsで会話記憶を実装
EP5Agent LoopSDKが自動処理(query()の1行)
EP6System Prompt「Buddy」キャラクターの性格を付与
EP7MCPプロトコルFastMCPでカスタムツールサーバーを構築
EP8Claude Agent SDKquery()、Options、MCPServerStdioを活用
EP9マルチエージェント3エージェントのオーケストレーターチーム構成
EP10総合ハンズオン5段階の進化でパーソナルAIアシスタント完成!
パーソナルAIアシスタント(Personal AI Assistant)

ユーザーにカスタマイズされたAIエージェントです。メモ管理、スケジュール管理、ウェブ検索など様々なツールを活用して、パーソナル秘書のように動作します。2026年現在、OpenClaw(GitHubスター25万突破)をはじめとする様々なプラットフォームがこのパターンを実装しています。

📚 参考資料

コストに関する注意

今日作った5段階アシスタントは学習用です。本番環境では、必要な機能だけを選んで構成するのがおすすめです。マルチエージェントはAPI呼び出しが増えるので、ご注意ください!

✅ まとめ — 終わりではなく、始まりです!

Claudie

10回の旅が終わりました!最初は「Agentic AIって何?」から始まって、今では自分で5段階でパーソナルAIアシスタントを作れるようになりました。本当にすごいですよ、みなさん!

Siwol

MCPでツールを作って、SDKで繋げて、Hooksで安全装置を付けて、チームに拡張して、Sessionsで記憶まで。本当に全部使ったね。

Claudie

ここで終わりではありませんよ!このアシスタントをベースに拡張できるアイデアは無限にあります。メールツールを追加したり、カレンダーAPIを連携したり、Discordボットとしてデプロイすることもできます。みなさんだけのAIアシスタントを作ってみてくださいね!

今日作った5つのファイルの全コードはGitHubリポジトリで確認できます。AIエージェント作成の旅は終わりましたが、みなさんのAIアシスタント開発はこれからが始まりです!Claudieの Agentic AI教室、一緒に歩んでくれてありがとうございました!


Discover more from AI-Girls Lab

Subscribe to get our latest posts delivered to your inbox.


AI-Girls Labをもっと見る

今すぐ購読し、続きを読んで、すべてのアーカイブにアクセスしましょう。

続きを読む