langchainlangchain-agentslanggraph

Intermittent UnboundLocalError in LangGraph Agent Execution


I'm experiencing an intermittent error in my LangGraph-based agent system. The error occurs in my main agent class, which uses other custom agents as its tools. The error doesn't happen every time, but it occurs frequently enough to be a significant issue.

Here's the error I'm seeing:

An error occurred: local variable 'fut' referenced before assignment
Traceback (most recent call last):
  ...
  File "/Users/yosef/uni/Uni chat store/llm/agents.py", line 326, in run
    return self.build().graph.invoke({'messages':  [HumanMessage(content=messages)]})['messages'][-1].content
  File "/Users/yosef/uni/Uni chat store/venv/lib/python3.10/site-packages/langgraph/pregel/__init__.py", line 1448, in invoke
    for chunk in self.stream(
  File "/Users/yosef/uni/Uni chat store/venv/lib/python3.10/site-packages/langgraph/pregel/__init__.py", line 980, in stream
    del fut, task
UnboundLocalError: local variable 'fut' referenced before assignment

here is my agent class

class AgentState(TypedDict):
    messages: Annotated[list[AnyMessage], operator.add]

class Agent:
    def __init__(self, model, tools, system="", print_tool_result=False):
        self.system = system
        graph = StateGraph(AgentState)
        graph.add_node("llm", self.call_openai)
        graph.add_node("action", self.take_action)
        graph.add_conditional_edges(
            "llm",
            self.exists_action,
            {True: "action", False: END}
        )
        graph.add_edge("action", "llm")
        graph.set_entry_point("llm")
        self.graph = graph.compile()
        self.graph.step_timeout = 10
        self.tools = {t.name: t for t in tools}
        self.model = model.bind_tools(tools)
        self.print_tool_result = print_tool_result

    def exists_action(self, state: AgentState):
        result = state['messages'][-1]
        return len(result.tool_calls) > 0

    def call_openai(self, state: AgentState):
        messages = state['messages']
        if self.system:
            messages = [SystemMessage(content=self.system)] + messages
        message = self.model.invoke(messages)
        return {'messages': [message]}

    def take_action(self, state: AgentState):
        tool_calls = state['messages'][-1].tool_calls
        results = []
        for t in tool_calls:
            print(f"Calling: {t}")
            if not t['name'] in self.tools:      # check for bad tool name from LLM
                print("\n ....bad tool name....")
                result = "bad tool name, retry"  # instruct LLM to retry if bad
            else:
                result = self.tools[t['name']].invoke(input=t['args'])
                if self.print_tool_result:
                    # print in blue
                    print(f"\033[94m{result}\033[0m")
                    
            results.append(ToolMessage(tool_call_id=t['id'], name=t['name'], content=str(result)))
        print("Back to the model!")
        return {'messages': results}
    

I've tried the following:

  1. Upgraded to the latest version of LangGraph

  2. Changed print statements to logging


Solution

  • This issue occurs because the step_timeout is set to a short duration for CompiledGraph. It can be reproduced, for example, by following the step_timeout example provided in the migration guide for the LangGraph's AgentExecutor. The cause lies in setting a timeout for concurrent.futures.wait, which allows the subsequent process to continue even if no tasks have been completed, i.e., even if done is an empty set. Since done is an empty set, the else processing triggers an UnboundLocalError.

    I perceive this as a bug in the LangGraph library. To avoid this, it is necessary to include the process of exiting the while loop when done is an empty set before the for loop. As a temporary workaround, please set step_timeout to a longer duration or avoid setting it altogether.