AttributeError: 'Command' object has no attribute 'content' #431

Closed
opened 2026-02-20 17:40:05 -05:00 by yindo · 7 comments
Owner

Originally created by @nick-youngblut on GitHub (Feb 2, 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

from typing import Annotated, List
from langgraph.types import Command
from langchain_core.tools import tool
from langchain_core.messages import AIMessage

def create_handoff_tool(agent_list: List[str]):
    """Create a tool that can return handoff via a Command"""
    available_agents = agent_list + ["__end__"]
    
    @tool
    def handoff_to_agent(
        agent_name: Annotated[str, "The name of the agent to handoff to"]
    ):
        """Handoff to another agent or end the task."""
        # check if agent name in the list
        if agent_name not in available_agents:
            error_message = f"Agent {agent_name} is not available. Choose one of: {', '.join(available_agents)}",
            return Command(
                goto=Command.PARENT, 
                graph=Command.PARENT,
                update={"messages": [AIMessage(content=error_message)]},
            )

        # return the routing command
        return Command(
            goto=agent_name,
            graph=Command.PARENT,
            update={"messages": [AIMessage(content=f"Successfully transferred to {agent_name}")]},
        )
    
    # dynamically modify doc string
    handoff_to_agent.__doc__ = "\n".join([
        "Transfer to another agent or end the task.",
        f"Available agents: {', '.join(available_agents)}.",
        "If you want to end the task, use '__end__'."
     ])
    
    return handoff_to_agent

Error Message and Stack Trace (if applicable)

Traceback (most recent call last):
  File "/Users/nickyoungblut/mambaforge/envs/genomics-guide2/lib/python3.11/site-packages/streamlit/runtime/scriptrunner/exec_code.py", line 88, in exec_func_with_error_handling
    result = func()
             ^^^^^^
  File "/Users/nickyoungblut/mambaforge/envs/genomics-guide2/lib/python3.11/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 579, in code_to_exec
    exec(code, module.__dict__)
  File "/Users/nickyoungblut/dev/python/streamlit/genomics_guide2/app.py", line 133, in <module>
    response = asyncio.run(
               ^^^^^^^^^^^^
  File "/Users/nickyoungblut/mambaforge/envs/genomics-guide2/lib/python3.11/asyncio/runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/Users/nickyoungblut/mambaforge/envs/genomics-guide2/lib/python3.11/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/nickyoungblut/mambaforge/envs/genomics-guide2/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/Users/nickyoungblut/dev/python/streamlit/genomics_guide2/genomics_guide2/astream_event_handler.py", line 49, in astream_graph
    output_placeholder.code(event['data'].get('output').content)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Command' object has no attribute 'content'

Description

Command is not working with this simple example, and output_placeholder.code(event['data'].get('output').content) is not very helpful for determining the cause of the error.

System Info

System Information

OS: Darwin
OS Version: Darwin Kernel Version 24.2.0: Fri Dec 6 18:56:34 PST 2024; root:xnu-11215.61.5~2/RELEASE_ARM64_T6020
Python Version: 3.11.11 | packaged by conda-forge | (main, Dec 5 2024, 14:21:42) [Clang 18.1.8 ]

Package Information

langchain_core: 0.3.33
langchain: 0.3.17
langchain_community: 0.3.13
langsmith: 0.1.147
langchain_groq: 0.2.2
langchain_openai: 0.3.3
langchain_text_splitters: 0.3.4
langchain_weaviate: 0.0.3
langchainhub: 0.1.21
langgraph_sdk: 0.1.48

Optional packages not installed

langserve

Other Dependencies

aiohttp: 3.11.11
async-timeout: Installed. No version info available.
dataclasses-json: 0.6.7
groq: 0.13.1
httpx: 0.27.0
httpx-sse: 0.4.0
jsonpatch: 1.33
langsmith-pyo3: Installed. No version info available.
numpy: 1.26.4
openai: 1.61.0
orjson: 3.10.12
packaging: 24.2
pydantic: 2.10.4
pydantic-settings: 2.7.0
PyYAML: 6.0.2
requests: 2.32.3
requests-toolbelt: 1.0.0
simsimd: 4.4.0
SQLAlchemy: 2.0.36
tenacity: 8.5.0
tiktoken: 0.8.0
types-requests: 2.32.0.20241016
typing-extensions: 4.12.2
weaviate-client: 4.8.1

Originally created by @nick-youngblut on GitHub (Feb 2, 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 from typing import Annotated, List from langgraph.types import Command from langchain_core.tools import tool from langchain_core.messages import AIMessage def create_handoff_tool(agent_list: List[str]): """Create a tool that can return handoff via a Command""" available_agents = agent_list + ["__end__"] @tool def handoff_to_agent( agent_name: Annotated[str, "The name of the agent to handoff to"] ): """Handoff to another agent or end the task.""" # check if agent name in the list if agent_name not in available_agents: error_message = f"Agent {agent_name} is not available. Choose one of: {', '.join(available_agents)}", return Command( goto=Command.PARENT, graph=Command.PARENT, update={"messages": [AIMessage(content=error_message)]}, ) # return the routing command return Command( goto=agent_name, graph=Command.PARENT, update={"messages": [AIMessage(content=f"Successfully transferred to {agent_name}")]}, ) # dynamically modify doc string handoff_to_agent.__doc__ = "\n".join([ "Transfer to another agent or end the task.", f"Available agents: {', '.join(available_agents)}.", "If you want to end the task, use '__end__'." ]) return handoff_to_agent ``` ### Error Message and Stack Trace (if applicable) ```shell Traceback (most recent call last): File "/Users/nickyoungblut/mambaforge/envs/genomics-guide2/lib/python3.11/site-packages/streamlit/runtime/scriptrunner/exec_code.py", line 88, in exec_func_with_error_handling result = func() ^^^^^^ File "/Users/nickyoungblut/mambaforge/envs/genomics-guide2/lib/python3.11/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 579, in code_to_exec exec(code, module.__dict__) File "/Users/nickyoungblut/dev/python/streamlit/genomics_guide2/app.py", line 133, in <module> response = asyncio.run( ^^^^^^^^^^^^ File "/Users/nickyoungblut/mambaforge/envs/genomics-guide2/lib/python3.11/asyncio/runners.py", line 190, in run return runner.run(main) ^^^^^^^^^^^^^^^^ File "/Users/nickyoungblut/mambaforge/envs/genomics-guide2/lib/python3.11/asyncio/runners.py", line 118, in run return self._loop.run_until_complete(task) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/nickyoungblut/mambaforge/envs/genomics-guide2/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete return future.result() ^^^^^^^^^^^^^^^ File "/Users/nickyoungblut/dev/python/streamlit/genomics_guide2/genomics_guide2/astream_event_handler.py", line 49, in astream_graph output_placeholder.code(event['data'].get('output').content) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'Command' object has no attribute 'content' ``` ### Description `Command` is not working with this simple example, and `output_placeholder.code(event['data'].get('output').content)` is not very helpful for determining the cause of the error. ### System Info System Information ------------------ > OS: Darwin > OS Version: Darwin Kernel Version 24.2.0: Fri Dec 6 18:56:34 PST 2024; root:xnu-11215.61.5~2/RELEASE_ARM64_T6020 > Python Version: 3.11.11 | packaged by conda-forge | (main, Dec 5 2024, 14:21:42) [Clang 18.1.8 ] Package Information ------------------- > langchain_core: 0.3.33 > langchain: 0.3.17 > langchain_community: 0.3.13 > langsmith: 0.1.147 > langchain_groq: 0.2.2 > langchain_openai: 0.3.3 > langchain_text_splitters: 0.3.4 > langchain_weaviate: 0.0.3 > langchainhub: 0.1.21 > langgraph_sdk: 0.1.48 Optional packages not installed ------------------------------- > langserve Other Dependencies ------------------ > aiohttp: 3.11.11 > async-timeout: Installed. No version info available. > dataclasses-json: 0.6.7 > groq: 0.13.1 > httpx: 0.27.0 > httpx-sse: 0.4.0 > jsonpatch: 1.33 > langsmith-pyo3: Installed. No version info available. > numpy: 1.26.4 > openai: 1.61.0 > orjson: 3.10.12 > packaging: 24.2 > pydantic: 2.10.4 > pydantic-settings: 2.7.0 > PyYAML: 6.0.2 > requests: 2.32.3 > requests-toolbelt: 1.0.0 > simsimd: 4.4.0 > SQLAlchemy: 2.0.36 > tenacity: 8.5.0 > tiktoken: 0.8.0 > types-requests: 2.32.0.20241016 > typing-extensions: 4.12.2 > weaviate-client: 4.8.1
yindo added the question label 2026-02-20 17:40:05 -05:00
yindo closed this issue 2026-02-20 17:40:05 -05:00
Author
Owner

@nick-youngblut commented on GitHub (Feb 2, 2025):

Also, it appears that Command cannot handle a goto back to the tool-calling agent, which is useful when the tool calling agent calls the wrong goto agent, so you want the tool calling agent to try again:

if agent_name not in available_agents:
    error_message = f"Agent {agent_name} is not available. Choose one of: {', '.join(available_agents)}",
    return Command(
       goto="AGENT_THAT_CALLED_THIS_TOOL", 
       update={"messages": [AIMessage(content=error_message)]},
    )

The error is: KeyError: 'branch:tools:__self__:AGENT_THAT_CALLED_THIS_TOOL

@nick-youngblut commented on GitHub (Feb 2, 2025): Also, it appears that Command cannot handle a goto back to the tool-calling agent, which is useful when the tool calling agent calls the wrong goto agent, so you want the tool calling agent to try again: ```python if agent_name not in available_agents: error_message = f"Agent {agent_name} is not available. Choose one of: {', '.join(available_agents)}", return Command( goto="AGENT_THAT_CALLED_THIS_TOOL", update={"messages": [AIMessage(content=error_message)]}, ) ``` The error is: `KeyError: 'branch:tools:__self__:AGENT_THAT_CALLED_THIS_TOOL`
Author
Owner

@vbarda commented on GitHub (Feb 3, 2025):

This looks like error in your code and not in langgraph -- Command object never had a content field:

  File "/Users/nickyoungblut/dev/python/streamlit/genomics_guide2/genomics_guide2/astream_event_handler.py", line 49, in astream_graph
    output_placeholder.code(event['data'].get('output').content)

Also, it appears that Command cannot handle a goto back to the tool-calling agent, which is useful when the tool calling agent calls the wrong goto agent, so you want the tool calling agent to try again:

You would need to implement custom logic for this, Command is a general-purpose abstraction for combining navigation and state updates, it doesn't have anything specific to tool-calling. Here is how you could achieve desired behavior:

option 1: keep track of the currently active agent (either in the state or in AIMessage.name field)

agent_that_called = get_active_agent_name()
if agent_name not in available_agents:
    error_message = f"Agent {agent_name} is not available. Choose one of: {', '.join(available_agents)}",
    return Command(
       goto=agent_that_called, 
       update={"messages": [ToolMessage(content=error_message, tool_call_id=...)]},
    )

option 2: if you're using the prebuilt ToolNode, you can just raise the error before returning Command and ToolNode will automatically send ToolMessage with error content to the currently active agent, without navigating :

if agent_name not in available_agents:
    raise ValueError(" f"Agent {agent_name} is not available. Choose one of: {', '.join(available_agents)}")

...
return Command(...)

lastly, i think you have a typo in your original code example:

return Command(goto=Command.PARENT, ) <-- unless you have a node called "parent" in your graph, this is not going to work

@vbarda commented on GitHub (Feb 3, 2025): This looks like error in your code and not in langgraph -- `Command` object never had a `content` field: ``` File "/Users/nickyoungblut/dev/python/streamlit/genomics_guide2/genomics_guide2/astream_event_handler.py", line 49, in astream_graph output_placeholder.code(event['data'].get('output').content) ``` > Also, it appears that Command cannot handle a goto back to the tool-calling agent, which is useful when the tool calling agent calls the wrong goto agent, so you want the tool calling agent to try again: You would need to implement custom logic for this, `Command` is a general-purpose abstraction for combining navigation and state updates, it doesn't have anything specific to tool-calling. Here is how you could achieve desired behavior: option 1: keep track of the currently active agent (either in the state or in AIMessage.name field) ```python agent_that_called = get_active_agent_name() if agent_name not in available_agents: error_message = f"Agent {agent_name} is not available. Choose one of: {', '.join(available_agents)}", return Command( goto=agent_that_called, update={"messages": [ToolMessage(content=error_message, tool_call_id=...)]}, ) ``` option 2: if you're using the prebuilt `ToolNode`, you can just raise the error before returning `Command` and `ToolNode` will automatically send `ToolMessage` with error content to the currently active agent, without navigating : ```python if agent_name not in available_agents: raise ValueError(" f"Agent {agent_name} is not available. Choose one of: {', '.join(available_agents)}") ... return Command(...) ``` lastly, i think you have a typo in your original code example: `return Command(goto=Command.PARENT, )` <-- unless you have a node called "__parent__" in your graph, this is not going to work
Author
Owner

@vbarda commented on GitHub (Feb 12, 2025):

@nick-youngblut did you manage to resolve your issue?

@vbarda commented on GitHub (Feb 12, 2025): @nick-youngblut did you manage to resolve your issue?
Author
Owner

@nick-youngblut commented on GitHub (Feb 13, 2025):

@vbarda no, I gave up on using Command

@nick-youngblut commented on GitHub (Feb 13, 2025): @vbarda no, I gave up on using `Command`
Author
Owner

@vbarda commented on GitHub (Feb 13, 2025):

@nick-youngblut so neither of the suggestions above worked for you?

@vbarda commented on GitHub (Feb 13, 2025): @nick-youngblut so neither of the suggestions above worked for you?
Author
Owner

@nick-youngblut commented on GitHub (Feb 14, 2025):

Sorry for not being clear: I ran out of time for my project, so I had to abandon using Command. Thank you for your helpful suggestions. Hopefully, I'll have some time soon to try them out. Thanks again.

@nick-youngblut commented on GitHub (Feb 14, 2025): Sorry for not being clear: I ran out of time for my project, so I had to abandon using `Command`. Thank you for your helpful suggestions. Hopefully, I'll have some time soon to try them out. Thanks again.
Author
Owner

@vbarda commented on GitHub (Feb 14, 2025):

No worries, hope you give it another try at some point! :) In the meantime, will close this issue. If you run into these or other problems again, feel free to re-open or open a new one.

@vbarda commented on GitHub (Feb 14, 2025): No worries, hope you give it another try at some point! :) In the meantime, will close this issue. If you run into these or other problems again, feel free to re-open or open a new one.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph#431