LangGraph Supervisorのwatsonxの挙動
はじめに
LangGraph の create_supervisor
を使って Supervisor → Agent A → Supervisor → Agent B という多段エージェントのフローを試したところ、
IBM watsonx ではうまくいかず、Azure OpenAI では成功する現象を確認しました。
この記事では、その検証過程をまとめます。
注意事項
この記事は2025/09/12時点の内容です。これ以降に不具合が解消されている場合がございます。
こちらを検証するために利用したOSSやバージョンは、以下の通りです。
langchain>=0.2.0
langchain-ibm>=0.3.1
langchain-openai>=0.1.0
langgraph-supervisor>=0.0.7
langgraph>=0.2.33
python-dotenv>=1.0.1
また、watsonxで利用したモデルは、以下の通りです。
meta-llama/llama-4-maverick-17b-128e-instruct-fp8
実現したいフロー
実装したいのは以下のシンプルなマルチエージェント構成です。
Supervisor
├─ Agent A(準備処理+state更新)
└─ Agent B(仕上げ処理)
期待する挙動は 1ターンで「Supervisor → Agent A → Supervisor → Agent B」 と遷移し、最終的に仕上げメッセージが返ってくることです。
watsonx での実装例
from langchain_ibm import ChatWatsonx
from langgraph.prebuilt import create_react_agent
from langgraph_supervisor import create_supervisor
from langchain_core.tools import tool
SUPERVISOR_STATE = {}
@tool
def set_state(prepared: bool) -> str:
SUPERVISOR_STATE["prepared"] = bool(prepared)
return f"prepared={SUPERVISOR_STATE['prepared']}"
llm = ChatWatsonx(
model_id="ibm/granite-13b-instruct-v2",
url=os.getenv("WATSONX_URL"),
project_id=os.getenv("WATSONX_PROJECT_ID"),
apikey=os.getenv("WATSONX_APIKEY"),
params={"temperature": 0, "max_new_tokens": 256},
)
agent_a = create_react_agent(model=llm, tools=[set_state], prompt="必ず set_state を呼ぶ")
agent_b = create_react_agent(model=llm, tools=[], prompt="仕上げを一文で返す")
supervisor = create_supervisor(
model=llm,
agents=[agent_a, agent_b],
prompt="STATE が True なら agent_b を呼べ",
add_handoff_back_messages=True,
output_mode="full_history",
).compile()
こちらは、不具合に関する部分のみを示しています。
全体のソースコードはこちらのGitHubを参照してください。
実行結果
-
Agent A
がset_state(prepared=True)
をテキストとして出力してしまい、実際にはツールが呼ばれない -
STATE
が更新されない ({}
のまま) - Supervisor が Agent B に遷移できず、期待するフローが成立しない
create_tool_calling_agent を使った場合
create_tool_calling_agent
を試しても改善せず、結局 watsonx ではツール呼び出しや Supervisor との多段遷移が安定しませんでした。
from langchain.agents import create_tool_calling_agent
agent_a = create_tool_calling_agent(llm=llm, tools=[set_state], prompt=...)
agent_b = create_tool_calling_agent(llm=llm, tools=[], prompt=...)
→ やはり STATE
が更新されない、または Supervisor がBへ渡せない ケースが頻発。
Azure OpenAI での実装
一方、同じコードを Azure OpenAI に切り替えただけで安定して動作しました。
from langchain_openai import AzureChatOpenAI
from langgraph.prebuilt import create_react_agent
from langgraph_supervisor import create_supervisor
llm = AzureChatOpenAI(
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version="2024-02-15-preview",
deployment_name=os.getenv("AZURE_OPENAI_DEPLOYMENT"),
temperature=0,
max_tokens=256,
)
agent_a = create_react_agent(model=llm, tools=[set_state], prompt="必ず set_state を呼ぶ")
agent_b = create_react_agent(model=llm, tools=[], prompt="仕上げを一文で返す")
supervisor = create_supervisor(
model=llm,
agents=[agent_a, agent_b],
prompt="STATE が True なら agent_b を呼べ",
add_handoff_back_messages=True,
output_mode="full_history",
).compile()
実行結果(成功例)
[supervisor] → agent_a
[agent_a] tool -> set_state
[agent_a] ai -> PREPARED=TRUE
[supervisor] → agent_b
[agent_b] ai -> 仕上げを完了しました。
STATE: {'prepared': True}
→ 期待通り Agent A → Supervisor → Agent B の流れが一気に完了しました。
まとめ
-
watsonx
-
create_react_agent
+create_supervisor
では state が戻らず失敗 -
create_tool_calling_agent
にしても安定せず
-
-
Azure OpenAI
-
create_react_agent
+create_supervisor
で 正常に多段遷移が成立
-
学び
- LangGraph で複数エージェントを多段遷移させる場合、watsonx は ReAct の出力書式を守らずツール呼び出しが失敗しやすい。
- Azure OpenAI では function calling が強力に働き、Supervisor を介した多段エージェント呼び出しが安定して動作する。
おわりに
実運用で安定したマルチエージェントを組むなら Azure OpenAI での実装が現実的 のようです。
今後、LangGraph 側で watsonx の ReAct 出力をより robust に処理する改善が入れば、再度試してみたいと思います。
Discussion