Tool function return Command with goto variable cause parallel running #1056

Closed
opened 2026-02-20 17:42:54 -05:00 by yindo · 0 comments
Owner

Originally created by @padanes on GitHub (Nov 12, 2025).

Checked other resources

  • This is a bug, not a usage question. For questions, please use the LangChain Forum (https://forum.langchain.com/).
  • I added a clear and detailed title that summarizes the issue.
  • I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example).
  • I included a self-contained, minimal example that demonstrates the issue INCLUDING all the relevant imports. The code run AS IS to reproduce the issue.

Example Code

from typing import Annotated, List
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage, ToolMessage, AIMessageChunk, BaseMessage
from langchain.tools import tool, ToolRuntime
from langgraph.graph import MessagesState, StateGraph, START, END
from langgraph.prebuilt import ToolNode
from langchain_openai import ChatOpenAI
from langgraph.types import Command

class AgentState(MessagesState):
    pass

@tool
def handoff_job_to_SOP_executor(handoffback_msg: Annotated[str, "call SOP executor to execute the job"], 
                                    runtime: ToolRuntime)-> Command:
    """
    call SOP executor to execute the job
    """
    tool_message = ToolMessage(
                    content=f"success to handoff job to SOP executor",
                    tool_call_id=runtime.tool_call_id
                )
    return Command(
        goto="SOP_executor",  
        update={**runtime.state, "messages": runtime.state["messages"] + [tool_message]},  
        # graph=Command.PARENT,  
    )

def get_qwen_model():

    return ChatOpenAI(
        model="qwen3-max",
        temperature=0.5,            
        max_tokens=5000,            
        api_key = mykey,
        base_url='https://dashscope.aliyuncs.com/compatible-mode/v1',
        streaming=False,
        
    )

tools = [handoff_job_to_SOP_executor]

def main_super(state: AgentState):
    llm = get_qwen_model()
    print("\n\n[[arrive supervisor]]\n\n")
    llm_with_tools = llm.bind_tools(tools, parallel_tool_calls=True)

    llm_msg = [SystemMessage(content="hand off any job to SOP executor using handoff_job_to_SOP_executor tool")] + state["messages"]
    response = llm_with_tools.invoke(llm_msg)
    state["messages"].append(response)
    print("\n\ndo something\n\n")
    print("\n\n[[bye supervisor]]\n\n")
    return state

def SOP_executor(state: AgentState):

    print("\n\n[[arrive SOP_executor]]\n\n")
    print("\n\ndo something\n\n")
    print("\n\n[[bye SOP_executor]]\n\n")
    return state

def should_continue(state: AgentState):
    messages = state["messages"]
    last_message = messages[-1]

    if hasattr(last_message, 'tool_calls') and last_message.tool_calls:
        return "tools"

    return END


workflow = StateGraph(AgentState)
workflow.add_node("supervisor", main_super)
workflow.add_node("tools", ToolNode(tools))
workflow.add_node("SOP_executor", SOP_executor, destinations=["supervisor"])

workflow.add_edge(START, "supervisor")
workflow.add_edge("SOP_executor", END)
workflow.add_conditional_edges(
    "supervisor",
    should_continue,
    {
        "tools": "tools",
        END: END,
    }
)


workflow.add_edge("tools", "supervisor")

supervisor = workflow.compile()

for _, chunk in supervisor.stream(
    {
        "messages": [
            {
                "role": "user",
                "content": "find US and New York state GDP in 2024. what % of US GDP was New York state?",
            }
        ]
    },
    subgraphs=True
):
    for k, v in chunk.items():
        print()
        print(type(v['messages'][-1]))
        if isinstance(v['messages'][-1], dict):
            print(v['messages'][-1])
        else:
            v['messages'][-1].pretty_print()
        
        print()

Error Message and Stack Trace (if applicable)

[[arrive supervisor]]




do something




[[bye supervisor]]



<class 'langchain_core.messages.ai.AIMessage'>
================================== Ai Message ==================================
Tool Calls:
  handoff_job_to_SOP_executor (call_86f09b6a65ab4ec69f55ea87)
 Call ID: call_86f09b6a65ab4ec69f55ea87
  Args:
    handoffback_msg: find US and New York state GDP in 2024. what % of US GDP was New York state?


<class 'langchain_core.messages.tool.ToolMessage'>
================================= Tool Message =================================
Name: handoff_job_to_SOP_executor

success to handoff job to SOP executor



[[arrive supervisor]]




[[arrive SOP_executor]]




do something




[[bye SOP_executor]]



<class 'langchain_core.messages.tool.ToolMessage'>
================================= Tool Message =================================
Name: handoff_job_to_SOP_executor

success to handoff job to SOP executor



do something




[[bye supervisor]]



<class 'langchain_core.messages.ai.AIMessage'>
================================== Ai Message ==================================

The job has been successfully handed off to the SOP executor for processing. Please wait for the results regarding the US and New York state GDP in 2024, as well as the percentage of US GDP attributed to New York state.

Description

I'm building the supervisor multi-agent gragh by myself. when I'm trying to use command message in the tool to handoff the task to another node(SOP_executor)

I expect the process will directly go to SOP_executor and WOULD NOT execute the supervisor again

But SOP_executor and supervisor is running in parallel.
Why?

[[arrive supervisor]]




[[arrive SOP_executor]]




do something




[[bye SOP_executor]]

System Info

System Information

OS: Darwin
OS Version: Darwin Kernel Version 23.5.0: Wed May 1 20:13:18 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T6030
Python Version: 3.12.10 (main, Apr 8 2025, 11:35:47) [Clang 16.0.0 (clang-1600.0.26.6)]

Package Information

langchain_core: 1.0.2
langchain: 1.0.3
langchain_community: 0.4.1
langsmith: 0.3.45
langchain_classic: 1.0.0
langchain_openai: 1.0.1
langchain_text_splitters: 1.0.0
langgraph_sdk: 0.2.9
langgraph_supervisor: 0.0.30

Optional packages not installed

langserve

Other Dependencies

aiohttp: 3.12.13
async-timeout: Installed. No version info available.
dataclasses-json: 0.6.7
httpx: 0.28.1
httpx-sse: 0.4.3
jsonpatch: 1.33
langchain-anthropic: Installed. No version info available.
langchain-aws: Installed. No version info available.
langchain-deepseek: Installed. No version info available.
langchain-fireworks: Installed. No version info available.
langchain-google-genai: Installed. No version info available.
langchain-google-vertexai: Installed. No version info available.
langchain-groq: Installed. No version info available.
langchain-huggingface: Installed. No version info available.
langchain-mistralai: Installed. No version info available.
langchain-ollama: Installed. No version info available.
langchain-perplexity: Installed. No version info available.
langchain-together: Installed. No version info available.
langchain-xai: Installed. No version info available.
langgraph: 1.0.2
langsmith-pyo3: Installed. No version info available.
numpy: 2.3.0
openai: 2.6.1
openai-agents: Installed. No version info available.
opentelemetry-api: Installed. No version info available.
opentelemetry-exporter-otlp-proto-http: Installed. No version info available.
opentelemetry-sdk: Installed. No version info available.
orjson: 3.10.18
packaging: 24.2
pydantic: 2.11.7
pydantic-settings: 2.11.0
pytest: Installed. No version info available.
pyyaml: 6.0.2
PyYAML: 6.0.2
requests: 2.32.5
requests-toolbelt: 1.0.0
rich: Installed. No version info available.
sqlalchemy: 2.0.44
SQLAlchemy: 2.0.44
tenacity: 9.1.2
tiktoken: 0.12.0
typing-extensions: 4.14.0
zstandard: 0.23.0

Originally created by @padanes on GitHub (Nov 12, 2025). ### Checked other resources - [x] This is a bug, not a usage question. For questions, please use the LangChain Forum (https://forum.langchain.com/). - [x] I added a clear and detailed title that summarizes the issue. - [x] I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example). - [x] I included a self-contained, minimal example that demonstrates the issue INCLUDING all the relevant imports. The code run AS IS to reproduce the issue. ### Example Code ```python from typing import Annotated, List from langchain_core.messages import HumanMessage, AIMessage, SystemMessage, ToolMessage, AIMessageChunk, BaseMessage from langchain.tools import tool, ToolRuntime from langgraph.graph import MessagesState, StateGraph, START, END from langgraph.prebuilt import ToolNode from langchain_openai import ChatOpenAI from langgraph.types import Command class AgentState(MessagesState): pass @tool def handoff_job_to_SOP_executor(handoffback_msg: Annotated[str, "call SOP executor to execute the job"], runtime: ToolRuntime)-> Command: """ call SOP executor to execute the job """ tool_message = ToolMessage( content=f"success to handoff job to SOP executor", tool_call_id=runtime.tool_call_id ) return Command( goto="SOP_executor", update={**runtime.state, "messages": runtime.state["messages"] + [tool_message]}, # graph=Command.PARENT, ) def get_qwen_model(): return ChatOpenAI( model="qwen3-max", temperature=0.5, max_tokens=5000, api_key = mykey, base_url='https://dashscope.aliyuncs.com/compatible-mode/v1', streaming=False, ) tools = [handoff_job_to_SOP_executor] def main_super(state: AgentState): llm = get_qwen_model() print("\n\n[[arrive supervisor]]\n\n") llm_with_tools = llm.bind_tools(tools, parallel_tool_calls=True) llm_msg = [SystemMessage(content="hand off any job to SOP executor using handoff_job_to_SOP_executor tool")] + state["messages"] response = llm_with_tools.invoke(llm_msg) state["messages"].append(response) print("\n\ndo something\n\n") print("\n\n[[bye supervisor]]\n\n") return state def SOP_executor(state: AgentState): print("\n\n[[arrive SOP_executor]]\n\n") print("\n\ndo something\n\n") print("\n\n[[bye SOP_executor]]\n\n") return state def should_continue(state: AgentState): messages = state["messages"] last_message = messages[-1] if hasattr(last_message, 'tool_calls') and last_message.tool_calls: return "tools" return END workflow = StateGraph(AgentState) workflow.add_node("supervisor", main_super) workflow.add_node("tools", ToolNode(tools)) workflow.add_node("SOP_executor", SOP_executor, destinations=["supervisor"]) workflow.add_edge(START, "supervisor") workflow.add_edge("SOP_executor", END) workflow.add_conditional_edges( "supervisor", should_continue, { "tools": "tools", END: END, } ) workflow.add_edge("tools", "supervisor") supervisor = workflow.compile() for _, chunk in supervisor.stream( { "messages": [ { "role": "user", "content": "find US and New York state GDP in 2024. what % of US GDP was New York state?", } ] }, subgraphs=True ): for k, v in chunk.items(): print() print(type(v['messages'][-1])) if isinstance(v['messages'][-1], dict): print(v['messages'][-1]) else: v['messages'][-1].pretty_print() print() ``` ### Error Message and Stack Trace (if applicable) ```shell [[arrive supervisor]] do something [[bye supervisor]] <class 'langchain_core.messages.ai.AIMessage'> ================================== Ai Message ================================== Tool Calls: handoff_job_to_SOP_executor (call_86f09b6a65ab4ec69f55ea87) Call ID: call_86f09b6a65ab4ec69f55ea87 Args: handoffback_msg: find US and New York state GDP in 2024. what % of US GDP was New York state? <class 'langchain_core.messages.tool.ToolMessage'> ================================= Tool Message ================================= Name: handoff_job_to_SOP_executor success to handoff job to SOP executor [[arrive supervisor]] [[arrive SOP_executor]] do something [[bye SOP_executor]] <class 'langchain_core.messages.tool.ToolMessage'> ================================= Tool Message ================================= Name: handoff_job_to_SOP_executor success to handoff job to SOP executor do something [[bye supervisor]] <class 'langchain_core.messages.ai.AIMessage'> ================================== Ai Message ================================== The job has been successfully handed off to the SOP executor for processing. Please wait for the results regarding the US and New York state GDP in 2024, as well as the percentage of US GDP attributed to New York state. ``` ### Description I'm building the supervisor multi-agent gragh by myself. when I'm trying to use command message in the tool to handoff the task to another node(SOP_executor) I expect the process will directly go to SOP_executor and WOULD NOT execute the supervisor again But SOP_executor and supervisor is running in parallel. Why? ``` [[arrive supervisor]] [[arrive SOP_executor]] do something [[bye SOP_executor]] ``` ### System Info System Information ------------------ > OS: Darwin > OS Version: Darwin Kernel Version 23.5.0: Wed May 1 20:13:18 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T6030 > Python Version: 3.12.10 (main, Apr 8 2025, 11:35:47) [Clang 16.0.0 (clang-1600.0.26.6)] Package Information ------------------- > langchain_core: 1.0.2 > langchain: 1.0.3 > langchain_community: 0.4.1 > langsmith: 0.3.45 > langchain_classic: 1.0.0 > langchain_openai: 1.0.1 > langchain_text_splitters: 1.0.0 > langgraph_sdk: 0.2.9 > langgraph_supervisor: 0.0.30 Optional packages not installed ------------------------------- > langserve Other Dependencies ------------------ > aiohttp: 3.12.13 > async-timeout: Installed. No version info available. > dataclasses-json: 0.6.7 > httpx: 0.28.1 > httpx-sse: 0.4.3 > jsonpatch: 1.33 > langchain-anthropic: Installed. No version info available. > langchain-aws: Installed. No version info available. > langchain-deepseek: Installed. No version info available. > langchain-fireworks: Installed. No version info available. > langchain-google-genai: Installed. No version info available. > langchain-google-vertexai: Installed. No version info available. > langchain-groq: Installed. No version info available. > langchain-huggingface: Installed. No version info available. > langchain-mistralai: Installed. No version info available. > langchain-ollama: Installed. No version info available. > langchain-perplexity: Installed. No version info available. > langchain-together: Installed. No version info available. > langchain-xai: Installed. No version info available. > langgraph: 1.0.2 > langsmith-pyo3: Installed. No version info available. > numpy: 2.3.0 > openai: 2.6.1 > openai-agents: Installed. No version info available. > opentelemetry-api: Installed. No version info available. > opentelemetry-exporter-otlp-proto-http: Installed. No version info available. > opentelemetry-sdk: Installed. No version info available. > orjson: 3.10.18 > packaging: 24.2 > pydantic: 2.11.7 > pydantic-settings: 2.11.0 > pytest: Installed. No version info available. > pyyaml: 6.0.2 > PyYAML: 6.0.2 > requests: 2.32.5 > requests-toolbelt: 1.0.0 > rich: Installed. No version info available. > sqlalchemy: 2.0.44 > SQLAlchemy: 2.0.44 > tenacity: 9.1.2 > tiktoken: 0.12.0 > typing-extensions: 4.14.0 > zstandard: 0.23.0
yindo added the bugpending labels 2026-02-20 17:42:54 -05:00
yindo closed this issue 2026-02-20 17:42:54 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph#1056