when define tool with return Command and call tools multiple at once, using stream_mode=updates, value type of result change from dict to list. #389

Closed
opened 2026-02-20 17:39:52 -05:00 by yindo · 4 comments
Owner

Originally created by @rayshen92 on GitHub (Jan 8, 2025).

Checked other resources

  • This is a bug, not a usage question. For questions, please use GitHub Discussions.
  • 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

import os

from langchain_core.messages import ToolMessage
from langchain_core.runnables import RunnableConfig
from langchain_core.tools import tool
from langchain_core.tools.base import InjectedToolCallId
from langgraph.types import Command

from typing_extensions import Annotated
import dotenv
dotenv.load_dotenv()

@tool
def add(
    a: int,
    b: int,
    tool_call_id: Annotated[str, InjectedToolCallId],
    config: RunnableConfig,
):
    """add two numbers"""

    result = a + b

    return Command(
        update={
            "messages": [ToolMessage(f"add result: {result}", tool_call_id=tool_call_id)],
        }
    )


@tool
def sub(
    a: int,
    b: int,
    tool_call_id: Annotated[str, InjectedToolCallId],
    config: RunnableConfig,
):
    """sub two numbers"""

    result = a + b

    return f"sub result: {result}"


from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

model = ChatOpenAI(
    model="gpt-4o",
    api_key=os.environ["AZURE_OPENAI_API_KEY"],
    base_url=f'{os.environ["AZURE_OPENAI_ENDPOINT"]}/v1',
)

from langgraph.checkpoint.memory import MemorySaver

memory = MemorySaver()

tools = [add, sub]
agent = create_react_agent(model, tools=tools, checkpointer=memory)

config = {
    "configurable": {"thread_id": "1"},
}

# use add tool
for chunk in agent.stream(
    input={
        "messages": [
            (
                "user",
                "add(1,1), add(1,2), add(1,3) at once",
            ),
        ]
    },
    config=config,
    stream_mode="updates",
):
    for node, values in chunk.items():
        print(f"Receiving update from node: '{node}'")
        print(f"type of values: {type(values)}")
        print(values)
        print("\n\n")

print("===========================================================\n\n")


# use sub tool
for chunk in agent.stream(
    input={
        "messages": [
            (
                "user",
                "sub(1,1), sub(1,2), sub(1,3) at once",
            ),
        ]
    },
    config=config,
    stream_mode="updates",
):
    for node, values in chunk.items():
        print(f"Receiving update from node: '{node}'")
        print(f"type of values: {type(values)}")
        print(values)
        print("\n\n")

print("======================message history=================\n\n")
cur_state = agent.get_state(config)
messages = cur_state.values.get("messages", [])
for message in messages:
    message.pretty_print()

Error Message and Stack Trace (if applicable)

Receiving update from node: 'agent'
type of values: <class 'dict'>
{'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_ZZg7TJazTcfHGcq3gOiedOqt', 'function': {'arguments': '{"a": 1, "b": 1}', 'name': 'add'}, 'type': 'function'}, {'id': 'call_fz3zfIwaZV6KK9zEBCRG4jdf', 'function': {'arguments': '{"a": 1, "b": 2}', 'name': 'add'}, 'type': 'function'}, {'id': 'call_HMbvpnTtRNkxwXsu9sq7SFbo', 'function': {'arguments': '{"a": 1, "b": 3}', 'name': 'add'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 67, 'prompt_tokens': 85, 'total_tokens': 152, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_f3927aa00d', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-4dc7bc54-bf3e-42ee-8a53-b9444137a08b-0', tool_calls=[{'name': 'add', 'args': {'a': 1, 'b': 1}, 'id': 'call_ZZg7TJazTcfHGcq3gOiedOqt', 'type': 'tool_call'}, {'name': 'add', 'args': {'a': 1, 'b': 2}, 'id': 'call_fz3zfIwaZV6KK9zEBCRG4jdf', 'type': 'tool_call'}, {'name': 'add', 'args': {'a': 1, 'b': 3}, 'id': 'call_HMbvpnTtRNkxwXsu9sq7SFbo', 'type': 'tool_call'}], usage_metadata={'input_tokens': 85, 'output_tokens': 67, 'total_tokens': 152, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}



Receiving update from node: 'tools'
type of values: <class 'list'>
[{'messages': [ToolMessage(content='add result: 2', name='add', id='38f447fe-0939-4dec-af5b-b772d94bbbe8', tool_call_id='call_ZZg7TJazTcfHGcq3gOiedOqt')]}, {'messages': [ToolMessage(content='add result: 3', name='add', id='17b95c26-20bd-49f4-817b-254b8fd469b4', tool_call_id='call_fz3zfIwaZV6KK9zEBCRG4jdf')]}, {'messages': [ToolMessage(content='add result: 4', name='add', id='672d6d95-4248-420e-95e0-f1d4a315f7ce', tool_call_id='call_HMbvpnTtRNkxwXsu9sq7SFbo')]}]



Receiving update from node: 'agent'
type of values: <class 'dict'>
{'messages': [AIMessage(content='The results of the additions are as follows:\n- \\(1 + 1 = 2\\)\n- \\(1 + 2 = 3\\)\n- \\(1 + 3 = 4\\)', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 43, 'prompt_tokens': 183, 'total_tokens': 226, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_f3927aa00d', 'finish_reason': 'stop', 'logprobs': None}, id='run-19450b04-0e81-4f43-ba78-f55d667c5eb7-0', usage_metadata={'input_tokens': 183, 'output_tokens': 43, 'total_tokens': 226, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}



===========================================================


Receiving update from node: 'agent'
type of values: <class 'dict'>
{'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_YFPOUghRCkW1Fo1tZ9uSfOu4', 'function': {'arguments': '{"a": 1, "b": 1}', 'name': 'sub'}, 'type': 'function'}, {'id': 'call_ghESCK5aIuqEaqD6ofiZR14v', 'function': {'arguments': '{"a": 1, "b": 2}', 'name': 'sub'}, 'type': 'function'}, {'id': 'call_dALc18L81Jptz2cz3w8YDTf1', 'function': {'arguments': '{"a": 1, "b": 3}', 'name': 'sub'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 67, 'prompt_tokens': 253, 'total_tokens': 320, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_f3927aa00d', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-325f3183-5377-44f6-9deb-445b10b534c7-0', tool_calls=[{'name': 'sub', 'args': {'a': 1, 'b': 1}, 'id': 'call_YFPOUghRCkW1Fo1tZ9uSfOu4', 'type': 'tool_call'}, {'name': 'sub', 'args': {'a': 1, 'b': 2}, 'id': 'call_ghESCK5aIuqEaqD6ofiZR14v', 'type': 'tool_call'}, {'name': 'sub', 'args': {'a': 1, 'b': 3}, 'id': 'call_dALc18L81Jptz2cz3w8YDTf1', 'type': 'tool_call'}], usage_metadata={'input_tokens': 253, 'output_tokens': 67, 'total_tokens': 320, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}



Receiving update from node: 'tools'
type of values: <class 'dict'>
{'messages': [ToolMessage(content='sub result: 2', name='sub', id='2ad51609-06a2-4126-861e-e9682e316c19', tool_call_id='call_YFPOUghRCkW1Fo1tZ9uSfOu4'), ToolMessage(content='sub result: 3', name='sub', id='edefea05-aa33-4a0e-bf24-7fbf367a86be', tool_call_id='call_ghESCK5aIuqEaqD6ofiZR14v'), ToolMessage(content='sub result: 4', name='sub', id='f8295690-e247-44a9-bd50-1cfbb84543f7', tool_call_id='call_dALc18L81Jptz2cz3w8YDTf1')]}



Receiving update from node: 'agent'
type of values: <class 'dict'>
{'messages': [AIMessage(content='It seems there was an error in the response. Let me correct that for you.\n\nThe results of the subtractions are as follows:\n- \\(1 - 1 = 0\\)\n- \\(1 - 2 = -1\\)\n- \\(1 - 3 = -2\\)', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 61, 'prompt_tokens': 351, 'total_tokens': 412, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_f3927aa00d', 'finish_reason': 'stop', 'logprobs': None}, id='run-e0aa5255-b08f-4895-87d2-6d22a76ea555-0', usage_metadata={'input_tokens': 351, 'output_tokens': 61, 'total_tokens': 412, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}



======================message history=================


================================ Human Message =================================

add(1,1), add(1,2), add(1,3) at once
================================== Ai Message ==================================
Tool Calls:
  add (call_ZZg7TJazTcfHGcq3gOiedOqt)
 Call ID: call_ZZg7TJazTcfHGcq3gOiedOqt
  Args:
    a: 1
    b: 1
  add (call_fz3zfIwaZV6KK9zEBCRG4jdf)
 Call ID: call_fz3zfIwaZV6KK9zEBCRG4jdf
  Args:
    a: 1
    b: 2
  add (call_HMbvpnTtRNkxwXsu9sq7SFbo)
 Call ID: call_HMbvpnTtRNkxwXsu9sq7SFbo
  Args:
    a: 1
    b: 3
================================= Tool Message =================================
Name: add

add result: 2
================================= Tool Message =================================
Name: add

add result: 3
================================= Tool Message =================================
Name: add

add result: 4
================================== Ai Message ==================================

The results of the additions are as follows:
- \(1 + 1 = 2\)
- \(1 + 2 = 3\)
- \(1 + 3 = 4\)
================================ Human Message =================================

sub(1,1), sub(1,2), sub(1,3) at once
================================== Ai Message ==================================
Tool Calls:
  sub (call_YFPOUghRCkW1Fo1tZ9uSfOu4)
 Call ID: call_YFPOUghRCkW1Fo1tZ9uSfOu4
  Args:
    a: 1
    b: 1
  sub (call_ghESCK5aIuqEaqD6ofiZR14v)
 Call ID: call_ghESCK5aIuqEaqD6ofiZR14v
  Args:
    a: 1
    b: 2
  sub (call_dALc18L81Jptz2cz3w8YDTf1)
 Call ID: call_dALc18L81Jptz2cz3w8YDTf1
  Args:
    a: 1
    b: 3
================================= Tool Message =================================
Name: sub

sub result: 2
================================= Tool Message =================================
Name: sub

sub result: 3
================================= Tool Message =================================
Name: sub

sub result: 4
================================== Ai Message ==================================

It seems there was an error in the response. Let me correct that for you.

The results of the subtractions are as follows:
- \(1 - 1 = 0\)
- \(1 - 2 = -1\)
- \(1 - 3 = -2\)

Description

when call add multiple times at once, type of values is list.
when call sub multiple times at once, type of values if dict.

it should be the same type, the correct type is dict.

System Info

Package Information

langchain_core: 0.3.25
langsmith: 0.1.140
langchain_openai: 0.2.6
langgraph_sdk: 0.1.47

Optional packages not installed

langserve

Other Dependencies

httpx: 0.27.0
jsonpatch: 1.33
openai: 1.54.3
orjson: 3.10.3
packaging: 24.0
pydantic: 2.7.4
PyYAML: 6.0.1
requests: 2.32.3
requests-toolbelt: 1.0.0
tenacity: 9.0.0
tiktoken: 0.8.0
typing-extensions: 4.12.2

Originally created by @rayshen92 on GitHub (Jan 8, 2025). ### Checked other resources - [X] This is a bug, not a usage question. For questions, please use GitHub Discussions. - [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 import os from langchain_core.messages import ToolMessage from langchain_core.runnables import RunnableConfig from langchain_core.tools import tool from langchain_core.tools.base import InjectedToolCallId from langgraph.types import Command from typing_extensions import Annotated import dotenv dotenv.load_dotenv() @tool def add( a: int, b: int, tool_call_id: Annotated[str, InjectedToolCallId], config: RunnableConfig, ): """add two numbers""" result = a + b return Command( update={ "messages": [ToolMessage(f"add result: {result}", tool_call_id=tool_call_id)], } ) @tool def sub( a: int, b: int, tool_call_id: Annotated[str, InjectedToolCallId], config: RunnableConfig, ): """sub two numbers""" result = a + b return f"sub result: {result}" from langchain_openai import ChatOpenAI from langgraph.prebuilt import create_react_agent model = ChatOpenAI( model="gpt-4o", api_key=os.environ["AZURE_OPENAI_API_KEY"], base_url=f'{os.environ["AZURE_OPENAI_ENDPOINT"]}/v1', ) from langgraph.checkpoint.memory import MemorySaver memory = MemorySaver() tools = [add, sub] agent = create_react_agent(model, tools=tools, checkpointer=memory) config = { "configurable": {"thread_id": "1"}, } # use add tool for chunk in agent.stream( input={ "messages": [ ( "user", "add(1,1), add(1,2), add(1,3) at once", ), ] }, config=config, stream_mode="updates", ): for node, values in chunk.items(): print(f"Receiving update from node: '{node}'") print(f"type of values: {type(values)}") print(values) print("\n\n") print("===========================================================\n\n") # use sub tool for chunk in agent.stream( input={ "messages": [ ( "user", "sub(1,1), sub(1,2), sub(1,3) at once", ), ] }, config=config, stream_mode="updates", ): for node, values in chunk.items(): print(f"Receiving update from node: '{node}'") print(f"type of values: {type(values)}") print(values) print("\n\n") print("======================message history=================\n\n") cur_state = agent.get_state(config) messages = cur_state.values.get("messages", []) for message in messages: message.pretty_print() ``` ### Error Message and Stack Trace (if applicable) ```shell Receiving update from node: 'agent' type of values: <class 'dict'> {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_ZZg7TJazTcfHGcq3gOiedOqt', 'function': {'arguments': '{"a": 1, "b": 1}', 'name': 'add'}, 'type': 'function'}, {'id': 'call_fz3zfIwaZV6KK9zEBCRG4jdf', 'function': {'arguments': '{"a": 1, "b": 2}', 'name': 'add'}, 'type': 'function'}, {'id': 'call_HMbvpnTtRNkxwXsu9sq7SFbo', 'function': {'arguments': '{"a": 1, "b": 3}', 'name': 'add'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 67, 'prompt_tokens': 85, 'total_tokens': 152, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_f3927aa00d', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-4dc7bc54-bf3e-42ee-8a53-b9444137a08b-0', tool_calls=[{'name': 'add', 'args': {'a': 1, 'b': 1}, 'id': 'call_ZZg7TJazTcfHGcq3gOiedOqt', 'type': 'tool_call'}, {'name': 'add', 'args': {'a': 1, 'b': 2}, 'id': 'call_fz3zfIwaZV6KK9zEBCRG4jdf', 'type': 'tool_call'}, {'name': 'add', 'args': {'a': 1, 'b': 3}, 'id': 'call_HMbvpnTtRNkxwXsu9sq7SFbo', 'type': 'tool_call'}], usage_metadata={'input_tokens': 85, 'output_tokens': 67, 'total_tokens': 152, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]} Receiving update from node: 'tools' type of values: <class 'list'> [{'messages': [ToolMessage(content='add result: 2', name='add', id='38f447fe-0939-4dec-af5b-b772d94bbbe8', tool_call_id='call_ZZg7TJazTcfHGcq3gOiedOqt')]}, {'messages': [ToolMessage(content='add result: 3', name='add', id='17b95c26-20bd-49f4-817b-254b8fd469b4', tool_call_id='call_fz3zfIwaZV6KK9zEBCRG4jdf')]}, {'messages': [ToolMessage(content='add result: 4', name='add', id='672d6d95-4248-420e-95e0-f1d4a315f7ce', tool_call_id='call_HMbvpnTtRNkxwXsu9sq7SFbo')]}] Receiving update from node: 'agent' type of values: <class 'dict'> {'messages': [AIMessage(content='The results of the additions are as follows:\n- \\(1 + 1 = 2\\)\n- \\(1 + 2 = 3\\)\n- \\(1 + 3 = 4\\)', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 43, 'prompt_tokens': 183, 'total_tokens': 226, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_f3927aa00d', 'finish_reason': 'stop', 'logprobs': None}, id='run-19450b04-0e81-4f43-ba78-f55d667c5eb7-0', usage_metadata={'input_tokens': 183, 'output_tokens': 43, 'total_tokens': 226, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]} =========================================================== Receiving update from node: 'agent' type of values: <class 'dict'> {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_YFPOUghRCkW1Fo1tZ9uSfOu4', 'function': {'arguments': '{"a": 1, "b": 1}', 'name': 'sub'}, 'type': 'function'}, {'id': 'call_ghESCK5aIuqEaqD6ofiZR14v', 'function': {'arguments': '{"a": 1, "b": 2}', 'name': 'sub'}, 'type': 'function'}, {'id': 'call_dALc18L81Jptz2cz3w8YDTf1', 'function': {'arguments': '{"a": 1, "b": 3}', 'name': 'sub'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 67, 'prompt_tokens': 253, 'total_tokens': 320, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_f3927aa00d', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-325f3183-5377-44f6-9deb-445b10b534c7-0', tool_calls=[{'name': 'sub', 'args': {'a': 1, 'b': 1}, 'id': 'call_YFPOUghRCkW1Fo1tZ9uSfOu4', 'type': 'tool_call'}, {'name': 'sub', 'args': {'a': 1, 'b': 2}, 'id': 'call_ghESCK5aIuqEaqD6ofiZR14v', 'type': 'tool_call'}, {'name': 'sub', 'args': {'a': 1, 'b': 3}, 'id': 'call_dALc18L81Jptz2cz3w8YDTf1', 'type': 'tool_call'}], usage_metadata={'input_tokens': 253, 'output_tokens': 67, 'total_tokens': 320, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]} Receiving update from node: 'tools' type of values: <class 'dict'> {'messages': [ToolMessage(content='sub result: 2', name='sub', id='2ad51609-06a2-4126-861e-e9682e316c19', tool_call_id='call_YFPOUghRCkW1Fo1tZ9uSfOu4'), ToolMessage(content='sub result: 3', name='sub', id='edefea05-aa33-4a0e-bf24-7fbf367a86be', tool_call_id='call_ghESCK5aIuqEaqD6ofiZR14v'), ToolMessage(content='sub result: 4', name='sub', id='f8295690-e247-44a9-bd50-1cfbb84543f7', tool_call_id='call_dALc18L81Jptz2cz3w8YDTf1')]} Receiving update from node: 'agent' type of values: <class 'dict'> {'messages': [AIMessage(content='It seems there was an error in the response. Let me correct that for you.\n\nThe results of the subtractions are as follows:\n- \\(1 - 1 = 0\\)\n- \\(1 - 2 = -1\\)\n- \\(1 - 3 = -2\\)', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 61, 'prompt_tokens': 351, 'total_tokens': 412, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_f3927aa00d', 'finish_reason': 'stop', 'logprobs': None}, id='run-e0aa5255-b08f-4895-87d2-6d22a76ea555-0', usage_metadata={'input_tokens': 351, 'output_tokens': 61, 'total_tokens': 412, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]} ======================message history================= ================================ Human Message ================================= add(1,1), add(1,2), add(1,3) at once ================================== Ai Message ================================== Tool Calls: add (call_ZZg7TJazTcfHGcq3gOiedOqt) Call ID: call_ZZg7TJazTcfHGcq3gOiedOqt Args: a: 1 b: 1 add (call_fz3zfIwaZV6KK9zEBCRG4jdf) Call ID: call_fz3zfIwaZV6KK9zEBCRG4jdf Args: a: 1 b: 2 add (call_HMbvpnTtRNkxwXsu9sq7SFbo) Call ID: call_HMbvpnTtRNkxwXsu9sq7SFbo Args: a: 1 b: 3 ================================= Tool Message ================================= Name: add add result: 2 ================================= Tool Message ================================= Name: add add result: 3 ================================= Tool Message ================================= Name: add add result: 4 ================================== Ai Message ================================== The results of the additions are as follows: - \(1 + 1 = 2\) - \(1 + 2 = 3\) - \(1 + 3 = 4\) ================================ Human Message ================================= sub(1,1), sub(1,2), sub(1,3) at once ================================== Ai Message ================================== Tool Calls: sub (call_YFPOUghRCkW1Fo1tZ9uSfOu4) Call ID: call_YFPOUghRCkW1Fo1tZ9uSfOu4 Args: a: 1 b: 1 sub (call_ghESCK5aIuqEaqD6ofiZR14v) Call ID: call_ghESCK5aIuqEaqD6ofiZR14v Args: a: 1 b: 2 sub (call_dALc18L81Jptz2cz3w8YDTf1) Call ID: call_dALc18L81Jptz2cz3w8YDTf1 Args: a: 1 b: 3 ================================= Tool Message ================================= Name: sub sub result: 2 ================================= Tool Message ================================= Name: sub sub result: 3 ================================= Tool Message ================================= Name: sub sub result: 4 ================================== Ai Message ================================== It seems there was an error in the response. Let me correct that for you. The results of the subtractions are as follows: - \(1 - 1 = 0\) - \(1 - 2 = -1\) - \(1 - 3 = -2\) ``` ### Description when call `add` multiple times at once, type of values is `list`. when call `sub` multiple times at once, type of values if `dict`. it should be the same type, the correct type is `dict`. ### System Info Package Information ------------------- > langchain_core: 0.3.25 > langsmith: 0.1.140 > langchain_openai: 0.2.6 > langgraph_sdk: 0.1.47 Optional packages not installed ------------------------------- > langserve Other Dependencies ------------------ > httpx: 0.27.0 > jsonpatch: 1.33 > openai: 1.54.3 > orjson: 3.10.3 > packaging: 24.0 > pydantic: 2.7.4 > PyYAML: 6.0.1 > requests: 2.32.3 > requests-toolbelt: 1.0.0 > tenacity: 9.0.0 > tiktoken: 0.8.0 > typing-extensions: 4.12.2
yindo closed this issue 2026-02-20 17:39:52 -05:00
Author
Owner

@rayshen92 commented on GitHub (Jan 8, 2025):

when call add (define with return Command) once upon a time below.

# use add tool
for chunk in agent.stream(
    input={
        "messages": [
            (
                "user",
                "add(2,1)",
            ),
        ]
    },
    config=config,
    stream_mode="updates",
):
    for node, values in chunk.items():
        print(f"Receiving update from node: '{node}'")
        print(f"type of values: {type(values)}")
        print(values)
        print("\n\n")

the result :


Receiving update from node: 'tools'
type of values: <class 'dict'>
{'messages': [ToolMessage(content='add result: 3', name='add', id='d7f1c3e2-b8f4-4469-9319-1f6112bbea9d', tool_call_id='call_0OyB6vhKhGdS1EcK2Av5Y1Wg')]}

value type is dict. the behavior is inconsistent

@rayshen92 commented on GitHub (Jan 8, 2025): when call `add` (define with `return Command`) once upon a time below. ```python # use add tool for chunk in agent.stream( input={ "messages": [ ( "user", "add(2,1)", ), ] }, config=config, stream_mode="updates", ): for node, values in chunk.items(): print(f"Receiving update from node: '{node}'") print(f"type of values: {type(values)}") print(values) print("\n\n") ``` the result : ``` Receiving update from node: 'tools' type of values: <class 'dict'> {'messages': [ToolMessage(content='add result: 3', name='add', id='d7f1c3e2-b8f4-4469-9319-1f6112bbea9d', tool_call_id='call_0OyB6vhKhGdS1EcK2Av5Y1Wg')]} ``` value type is dict. the behavior is inconsistent
Author
Owner

@vbarda commented on GitHub (Jan 9, 2025):

@rayshen92 this is the intended behavior when mixing command and non-command tool outputs. out of curiosity, why do you need to return Command from the add tool?

@vbarda commented on GitHub (Jan 9, 2025): @rayshen92 this is the intended behavior when mixing command and non-command tool outputs. out of curiosity, why do you need to return `Command` from the `add` tool?
Author
Owner

@rayshen92 commented on GitHub (Jan 9, 2025):

@rayshen92 this is the intended behavior when mixing command and non-command tool outputs. out of curiosity, why do you need to return Command from the add tool?

I need to update custom state when call tools in my real case.

use the same add tool which is defined with Command return,
the result type of "add(2,1)" and "add(1,1), add(1,2), add(1,3) at once" are inconsistent.

Receiving update from node: 'tools'
type of values: <class 'list'>
[{'messages': [ToolMessage(content='add result: 2', name='add', id='38f447fe-0939-4dec-af5b-b772d94bbbe8', tool_call_id='call_ZZg7TJazTcfHGcq3gOiedOqt')]}, {'messages': [ToolMessage(content='add result: 3', name='add', id='17b95c26-20bd-49f4-817b-254b8fd469b4', tool_call_id='call_fz3zfIwaZV6KK9zEBCRG4jdf')]}, {'messages': [ToolMessage(content='add result: 4', name='add', id='672d6d95-4248-420e-95e0-f1d4a315f7ce', tool_call_id='call_HMbvpnTtRNkxwXsu9sq7SFbo')]}]
Receiving update from node: 'tools'
type of values: <class 'dict'>
{'messages': [ToolMessage(content='add result: 3', name='add', id='d7f1c3e2-b8f4-4469-9319-1f6112bbea9d', tool_call_id='call_0OyB6vhKhGdS1EcK2Av5Y1Wg')]}

call same tool, return type is different, it seems not reasonable.

@rayshen92 commented on GitHub (Jan 9, 2025): > @rayshen92 this is the intended behavior when mixing command and non-command tool outputs. out of curiosity, why do you need to return `Command` from the `add` tool? I need to update custom state when call tools in my real case. === use the same `add` tool which is defined with `Command` return, the result type of "add(2,1)" and "add(1,1), add(1,2), add(1,3) at once" are inconsistent. ``` Receiving update from node: 'tools' type of values: <class 'list'> [{'messages': [ToolMessage(content='add result: 2', name='add', id='38f447fe-0939-4dec-af5b-b772d94bbbe8', tool_call_id='call_ZZg7TJazTcfHGcq3gOiedOqt')]}, {'messages': [ToolMessage(content='add result: 3', name='add', id='17b95c26-20bd-49f4-817b-254b8fd469b4', tool_call_id='call_fz3zfIwaZV6KK9zEBCRG4jdf')]}, {'messages': [ToolMessage(content='add result: 4', name='add', id='672d6d95-4248-420e-95e0-f1d4a315f7ce', tool_call_id='call_HMbvpnTtRNkxwXsu9sq7SFbo')]}] ``` ``` Receiving update from node: 'tools' type of values: <class 'dict'> {'messages': [ToolMessage(content='add result: 3', name='add', id='d7f1c3e2-b8f4-4469-9319-1f6112bbea9d', tool_call_id='call_0OyB6vhKhGdS1EcK2Av5Y1Wg')]} ``` call same tool, return type is different, it seems not reasonable.
Author
Owner

@vbarda commented on GitHub (Jan 9, 2025):

langgraph should automatically handle those mixed returns though, does the custom state update not work for you? nodes in langgraph can return lists, so this is consistent with the intended behavior

i will close the issue, but if there is any issue with the functionality, feel free to make a new issue.

@vbarda commented on GitHub (Jan 9, 2025): langgraph should automatically handle those mixed returns though, does the custom state update not work for you? nodes in langgraph can return lists, so this is consistent with the intended behavior i will close the issue, but if there is any issue with the _functionality_, feel free to make a new issue.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph#389