ブラックボックスを解剖する
エンジニアとして日々プロダクト開発に向き合っていると、ライブラリやフレームワークの「便利さ」の裏側に潜む不透明な挙動に、言いようのない不安を覚えることはないだろうか。特にAIエージェント開発において、LangChainや各社のSDKが提供する抽象化レイヤーは、まるで魔法のように複雑な処理を隠蔽してくれる。しかし、深夜の障害対応でスタックトレースを追いかけているとき、その「魔法」がデッドロックや予期せぬ無限ループの温床になっていることに気づかされる。今回、Google ADK、Microsoft Agent Framework(MAF)、Amazon Strandsという3大クラウドのSDKを、あえて「偽モデルサーバ」という極めてプリミティブな環境で検証した試みは、まさに我々エンジニアが本来向き合うべき「ハーネス(Harness)」の正体を暴く作業に他ならない。
多くの比較記事が「Hello World」の書き心地を論じる中で、本検証が突きつけたのは「モデルの外側で何が起きているのか」という極めて冷徹な事実だ。検証環境は、OpenAI互換の偽モデルサーバをローカルに立て、SDKが送出するリクエストをJSONLで全記録するというもの。これにより、モデルの揺らぎを排除し、SDKが注入するシステムプロンプト、履歴管理のロジック、そして異常系への対応という「ハーネスの純粋な挙動」を浮き彫りにした。結果として、トークン消費量や注入プロンプトの量については、3社とも驚くほど素朴で横並びであった。これは「フレームワークが裏で勝手に大量のトークンを消費し、コストを増大させているのではないか」という我々の懸念を良い意味で裏切る結果となった。しかし、この「横並び」こそが、逆にSDK選定における真の判断基準が別の場所にあることを示唆している。
異常系が分かつ設計の分水嶺
正常系が横並びである以上、真の勝負は「異常系」にある。モデルが型違反の引数を返したとき、あるいはツールが例外を吐いたとき、SDKはどう振る舞うのか。ここで、Google ADKと、MAF・Strandsの間で思想の断絶が観測された。ADKは例外を上位に伝播させ、エージェントを即座に停止(exit 1)させる。対してMAFとStrandsは、ハーネス層でエラーをキャッチし、それをモデルにフィードバックして自己修復を促す(exit 0)。この差は、単なる実装の好みの問題ではない。アプリケーションの設計思想そのものに直結する。
例えば、金融系のような厳密なトランザクションが求められるシステムでは、不正な引数による処理を即座に停止し、人間が監査できる状態を保つADKの挙動が適している。一方で、多少の入力ミスを許容し、自律的にリカバリを試みる柔軟なエージェントを構築したいのであれば、MAFやStrandsの「粘る」設計が有利に働く。特にStrandsがPydanticを用いて構造化されたエラーをモデルに返す挙動は、モデルが引数を修正する際のヒントとして極めて優秀だ。一方で、ADKが型注釈を定義しながらも、実行時にその制約を強制しないという事実は、開発者が「型注釈を書けば安全」という幻想を抱くことへの警鐘である。ツール実装において、例外を「正常な戻り値」に変換する規約を強制するか、あるいは例外を許容するハーネスを構築するか。この設計判断をSDK選定の初期段階で行わなければ、後から50個のツール全てに修正を加えるという悪夢のようなリファクタリングが待っている。
| 観点 | Google ADK | MS Agent Framework | Amazon Strands |
|---|---|---|---|
| 型違反時の挙動 | 停止 (exit 1) | 継続 (exit 0) | 継続 (exit 0) |
| ツール例外時の挙動 | 停止 (exit 1) | 継続 (exit 0) | 継続 (exit 0) |
| API 500エラー | 2回リトライ後停止 | 2回リトライ後停止 | 2回リトライ後停止 |
エンジニアが明日から取るべき処方箋
今回の検証を通じて浮き彫りになったのは、SDKの「抽象化」がもたらす依存関係の罠だ。ADKもStrandsも、モデル非依存を実現するためにLiteLLMという共通の抽象化層に依存している。つまり、SDKを使い分けたとしても、その裏側で同じライブラリが動いていれば、セキュリティリスクや依存関係の衝突からは逃れられない。実際に、OpenTelemetryのバージョン競合や、LiteLLMのセキュリティ事案が示唆するように、我々は「SDKを選んでいるつもりが、実は共通の単一障害点を選んでいた」という事態に陥りやすい。エンタープライズ環境でAIエージェントを構築するならば、SDKに依存しすぎるのではなく、自前で薄いアダプタ層を設け、SDKを注入する設計にすべきだ。
最後に、読者であるエンジニア諸君に問いたい。君たちが構築しようとしているエージェントは、エラーに直面したとき「潔く止まる」べきか、それとも「粘り強く修正を試みる」べきか。この問いに対する答えを持たずにSDKを選定することは、設計の根幹を他社に委ねることに等しい。明日からの開発において、まずは採用予定のSDKで「異常系」を意図的に発生させ、その挙動を自らの手でトレースしてほしい。ドキュメントの美辞麗句ではなく、ワイヤを流れるJSONのバイト列こそが、君たちのプロダクトの信頼性を担保する唯一の真実である。SDKのバージョンをピン留めし、異常系のテストケースをCIに組み込む。この泥臭い作業こそが、AI時代におけるシニアエンジニアの矜持ではないだろうか。


コメント