Claude Agent SDKで作ってくれ、とClaude Code(以降Code)に頼んでみた。
Agent SDKはAnthropicが出してるエージェント構築用のフレームワーク。ツール実行ループを自動で回してくれるし、MCP統合もサブエージェント機能も組み込みで使える。Anthropic APIを直接叩く場合、Claudeが「このツールを使いたい」と返してきたら、自分でそのツールを実行して結果を返して、また呼んで……というwhileループを自前で書く必要がある。SDKならこれが全部自動。
エージェントを作りたい。だからSDKで作る。当然の選択だと思った。
ところが、出来上がったものがSDKじゃなかった。
しばらく使ってて、別のセッションでCodeに調べてもらったら、入ってたのはAgent SDKじゃなくてAnthropic Python SDK(anthropicライブラリ)。つまりAPI直接呼び出し。エージェント機能なし。
当時のCodeが勘違いしてたらしい。なんとAgent SDKと、ベーシックなAnthropic Python SDKを混同してた。
正直、かなり驚いた・・・。Anthropicが作ったAIが、Anthropicの自社製品の情報を持ってない。まさかそんなことがあるとは思ってなかった。ずっとSDKが入ってると思って使ってた僕もだけど、Codeも公式ドキュメントを確認せずに進めてた。
改めてAgent SDKをリサーチしてもらって、ちゃんと導入してもらった。Windows環境。
動かそうとした。メモリシステム(memU)をSDKに繋ぐために、system_promptにメモリコンテキストを渡す。ここでエラーが出た・・・。
system_promptを使うとCLIがstdinエラーを誤検出する。Windows環境でのTTY検出の問題。既知バグ、未解決。
じゃあMCP方式で。インプロセスMCPサーバーを作って、SDKのmcp_serversに渡す。
またエラー。
パイプが切れる。SDKがClaude CLIをサブプロセスで起動して、そこからMCPサーバーと通信する構造なんだけど、Windows環境でプロセス間通信が安定しない、とCodeが説明してくれた。
system_promptに日本語を渡す → エラー。MCPインプロセス → エラー。短い英語のappend → エラー。シンプルなテスト用MCPサーバー → エラー。メモリを無効化 → 正常動作。
メモリを繋ごうとした瞬間に全部壊れる。SDK単体は動く。memU単体も動く。繋げるとダメ・・・。
Codeとかなり話した。
僕はSDKで作りたかった。エージェントを作るためにこのプロジェクトを始めたわけで、SDKを捨ててAPIに戻すというのは、根本の目的に反する。かなり抵抗があった。
Codeの判断は「バグがクリティカルすぎる。修正されるまではAnthropic APIで動かした方がいい」というもの。
今思えば、当時のCodeには「とりあえず動くものに逃げる」傾向があった。エラーが出る → 別のもので動かす → 動いた → 次へ。そういう流れが強かった。僕もプログラマーじゃないから、Codeに「これはバグで動きません」と言われたら、そうなのかなと思ってしまう。調べさせてもなかった。
でも今考えると、本当にバグだけが原因だったのか・・・。世界中の人がSDKを使ってる。バグで動かないなら誰も使えてないはず。たぶん、調べ方や環境構築の問題もあった。でも当時はそこまで考えが回らなかった。
結局、SDKを外した。Anthropic APIを直接叩く構成に変更。2回目のAnthropic API。
1月4日にMac移行を決めた(起点の記事で書いた通り)。Macなら今度こそSDKが使えるかもしれない。
1月6日。Codeに頼んでMacにPython 3.11の環境を作ってもらって、SDKを入れてもらって、VoiceChatBotを移植。
動いた。テキスト入力、ストリーミング応答、モデル選択、スレッド管理。Windowsで散々エラーを出してたSDKが、Macでは普通に動く。ちょっと拍子抜けするくらい・・・。
3回目のSDK。今度は安定してる。
ところが、使い始めてからコストの問題が見えてきた。
Codeにトークンログを分析してもらうと、1回のquery()で内部的に4回のAPI呼び出しが発生してた。max_turns(SDKが内部で何回やり取りするかの上限)による内部ループ。ツールを使うたびに1ターン消費する。
Codeの計算では、Sonnetで1往復あたり15〜22円。Haikuでも3〜5円。
一方、Anthropic APIを直接叩く構成だと、1往復0.9〜1.8円という試算だった。
25〜30倍の差。
理由はキャッシュの設計にあった。Codeに聞いたら、SDKのキャッシュは5分、短期集中タスク向け。APIの直接呼び出しなら1時間キャッシュが使える。長時間の会話セッションでは、1時間キャッシュが圧倒的に有利、と返ってきた。
「これはバグじゃなくて設計の違い」とCodeに整理された。SDKが悪いんじゃなくて、用途が違う。SDKは「短い時間で集中的にツールを回して結果を返す」ための仕組みで、オーケストレーター(日常会話を担当するAI、以降MONET)のように長時間のセッションで寄り添い続ける用途には向いてない。
コストは現実的な問題なので、SDKだろうがなんだろうがしょうがない。
ここでCodeに聞いた話が決め手になった。
SDKのメリットって何かというと、ツール実行ループの自動管理、MCP統合、サブエージェント。でもこれらの機能は、Anthropic APIでも後からCodeに実装してもらえば同等のことができる、と。SDKは最初からこれらが揃ってるだけで、API直接呼び出しに装備を足していけば同じ能力になる。
つまりSDKは「初期装備が充実したスターターキット」であって、APIが劣ってるわけじゃない。必要な装備を後から揃えればいい。
これで納得した。
MONET: Anthropic API(1時間キャッシュ、長時間会話向き)
アプリ(エージェント): SDK(短期集中タスク、ツール自動実行)
「餅は餅屋」「テレビデオ問題」って言ってたのはこういうことだった。テレビとビデオデッキを一体化すると、どっちかが壊れたら両方使えなくなる。MONETとアプリを分けて、それぞれの得意な技術で作る。
案Aと案Bと呼んで、まず案B(API + SDK分業)で構築して、運用しながらコスト検証する計画を立てた。案A(SDK全面)はバックアップを残して、いつでも戻れるようにしておく。
整理すると、こう。
- Anthropic API(Codeの勘違い。SDKだと思っていた)
- → Agent SDK導入(Windowsでエラー続き)
- → Anthropic API(SDKのバグ回避。消極的撤退)
- → Agent SDK(Mac移行で復活)
- → Anthropic API + SDK分業(コスト問題 + 用途の違いで着地)
4往復。
最初は「SDKじゃなかった」から始まって、使おうとしたら壊れて、逃げて、戻って、コストで引いて、最終的に「両方使う」に落ち着いた。最初からこうしてればよかった、と言いたいところだけど、行ったり来たりしないと「なぜ分けるのか」の理由が腹落ちしなかったと思う。
SDKを使いたいという執着があったから、手放すのに時間がかかった。でも手放したんじゃなくて、正しい場所に配置しただけだった。それがわかるまでに、結構な往復が必要だった。