🔥

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 Aset_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 に処理する改善が入れば、再度試してみたいと思います。

DXC Lab

Discussion