-
Notifications
You must be signed in to change notification settings - Fork 1k
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
base: main
Are you sure you want to change the base?
Conversation
create_react_agent
create_react_agent
create_react_agent
create_react_agent
create_react_agent
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
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.BadRequestError: Error code: 400 - {'error': {'message': "An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'....
BadRequestError: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'messages.1: Did not find 1
tool_resultblock(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 inToolNode
. 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 newhandle_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 callsFalse
: do nothing (default)Additional considerations:
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)