Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

langgraph: add handle_unanswered_tool_calls to create_react_agent #1899

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

vbarda
Copy link
Collaborator

@vbarda vbarda commented Sep 29, 2024

This change should address situations where LLM API providers error when sending an AI message with tool calls that do not have a corresponding ToolMessage, e.g.

  • openai BadRequestError: Error code: 400 - {'error': {'message': "An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'....
  • or anthropic: BadRequestError: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'messages.1: Did not find 1 tool_result block(s) at the beginning of this message....)

In the context of the create_react_agent usage, the simplest way to trigger this is an error inside a tool without error handling in ToolNode. This would lead to the agent interruption and any new human message sent to the agent would result in an error. A simple solution to address this is to call .update_state to modify message history. But since this option might not always be acceptable, we introduce a new handle_unanswered_tool_calls parameter with the following values:

  • "remove_tool_calls": modify AIMessages to remove tool_calls that do not have corresponding ToolMessages
  • "add_tool_messages": add a ToolMessage for each unanswered tool call, following each AIMessage with unanswered tool calls
  • False: do nothing (default)

Additional considerations:

  • should call_model update state for the AI messages with removed tool_calls? IMO no, because it would only lead to a confusing output when running agent w/ stream_mode=updates and won't actually affect underlying model behavior significantly (i.e. if the original human message is there, the model might still reintroduce a failing tool call in the future messages)

@vbarda vbarda changed the title [rfc] langgraph: clear unanswered tool calls [rfc] langgraph: clear unanswered tool calls in create_react_agent Sep 29, 2024
@vbarda vbarda changed the title [rfc] langgraph: clear unanswered tool calls in create_react_agent langgraph: clear unanswered tool calls in create_react_agent Oct 1, 2024
@vbarda vbarda changed the title langgraph: clear unanswered tool calls in create_react_agent langgraph: add handle_unanswered_tool_calls to create_react_agent Oct 1, 2024
If provided, the list of messages sent to the model will be modified according to the specified strategy:

- "remove_tool_calls": modify AIMessages to remove tool_calls that do not have corresponding ToolMessages
- "add_tool_messages": add a ToolMessage for each unanswered tool call, following each AIMessage with unanswered tool calls
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the content of those messages?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good question -- currently it's an empty string, but i wonder if it needs to be parametrized somehow / or if there is a better default

@@ -201,6 +302,14 @@ def create_react_agent(
- str: This is converted to a SystemMessage and added to the beginning of the list of messages in state["messages"].
- Callable: This function should take in full graph state and the output is then passed to the language model.
- Runnable: This runnable should take in full graph state and the output is then passed to the language model.
handle_unanswered_tool_calls: An optional parameter that defines how to handle AIMessages with tool calls that
do not have corresponding ToolMessages. This is useful to handle errors from LLM providers that require
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handle errors from LLM providers

What does this mean?

If we're adding this we should probably explain what reasonable situation could lead to such an error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants