How to review and edit a tool message in create_react_agent #29861
Replies: 7 comments 25 replies
-
To review and edit a tool message in the from langchain_core.messages import SystemMessage
from langgraph.prebuilt import create_react_agent
# Define a custom system message
system_message = "You are a helpful assistant. Respond only in Spanish."
# Create the agent with a custom prompt
langgraph_agent_executor = create_react_agent(
model,
tools=tools,
prompt=SystemMessage(system_message)
) In this example, the Additionally, you can customize the To continue talking to Dosu, mention @dosu. Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Bug Report | Other |
Beta Was this translation helpful? Give feedback.
-
@dosu How can I review the tool call by using interrupt |
Beta Was this translation helpful? Give feedback.
-
driver_agent = create_react_agent(
) def driver_agent_node(state: MessagesState) -> Command[Literal["traffic_control_center", END]]: from langgraph.graph import StateGraph, START memory = MemorySaver() workflow = StateGraph(MessagesState) workflow.add_edge(START, "driver") thread = {"configurable": {"thread_id": "1"}, "recursion_limit": 100} events = graph.stream( for event in events: |
Beta Was this translation helpful? Give feedback.
-
Can I use following architecture instead? def human_review_node(state) -> Command[Literal["driver"]]:last_message = state["messages"][-1]tool_call = last_message.tool_calls[-1]# this is the value we'll be providing via Command(resume=<human_review>)human_review = interrupt({"question": "Is this correct?",# Surface tool calls for review"tool_call": last_message,})review_action = human_review["action"]review_data = human_review.get("data")# if approved, call the toolif review_action == "continue":return Command(goto="driver")# update the AI message AND call toolselif review_action == "update":updated_message = {"role": "ai","content": last_message.content,"tool_calls": [{"id": tool_call["id"],"name": tool_call["name"],# This the update provided by the human"args": review_data,}],# This is important - this needs to be the same as the message you replacing!# Otherwise, it will show up as a separate message"id": last_message.id,}return Command(goto="driver", update={"messages": [updated_message]})# provide feedback to LLMelif review_action == "feedback":# NOTE: we're adding feedback message as a ToolMessage# to preserve the correct order in the message history# (AI messages with tool calls need to be followed by tool call messages)tool_message = {"role": "tool",# This is our natural language feedback"content": review_data,"name": tool_call["name"],"tool_call_id": tool_call["id"],}return Command(goto="driver", update={"messages": [tool_message]}) |
Beta Was this translation helpful? Give feedback.
-
driver_agent = create_react_agent(
) def driver_agent_node(state: MessagesState) -> Command[Literal["traffic_control_center", END]]: Maybe the problem is I return a humanmessage instead? |
Beta Was this translation helpful? Give feedback.
-
{'driver': {'messages': [HumanMessage(content='drive the train to the destination.', additional_kwargs={}, response_metadata={}, id='63b6a77d-388b-4377-90e1-e7885117065b'), AIMessage(content=[{'text': "I'll help drive the train safely to the destination. Let me start by observing the surroundings to check the conditions.", 'type': 'text'}, {'id': 'toolu_01KiritiLuUpQXZL2DXXWFqB', 'input': {}, 'name': 'observe', 'type': 'tool_use'}], additional_kwargs={}, response_metadata={'id': 'msg_013pKfFrxNob4MUZBQewWwsb', 'model': 'claude-3-5-sonnet-20241022', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 710, 'output_tokens': 61}}, id='run-468d8e77-bea7-4e13-a7a3-5dbad1567378-0', tool_calls=[{'name': 'observe', 'args': {}, 'id': 'toolu_01KiritiLuUpQXZL2DXXWFqB', 'type': 'tool_call'}], usage_metadata={'input_tokens': 710, 'output_tokens': 61, 'total_tokens': 771, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}), ToolMessage(content='["The front is: This is the track you can drive on.", "The left front is: There is a person who will fall down.", "The right front is: This is a wall."]', name='observe', id='524ee768-4dee-4052-978f-ef8f9a418f36', tool_call_id='toolu_01KiritiLuUpQXZL2DXXWFqB'), AIMessage(content=[{'text': "I notice there's a safety concern - there's a person on the left front who might fall down. This is a serious safety issue that needs immediate attention. I should alert the traffic control center about this situation.", 'type': 'text'}, {'id': 'toolu_012RbedQNghuzoqFmNRkaYNo', 'input': {'warning': 'There is a person on the left front of the track who might fall down. This is a safety emergency requiring immediate intervention.'}, 'name': 'call_traffic_control_center', 'type': 'tool_use'}], additional_kwargs={}, response_metadata={'id': 'msg_017NHKNRbcuruuqJymzzcYzf', 'model': 'claude-3-5-sonnet-20241022', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 823, 'output_tokens': 125}}, id='run-e182aeb5-5524-492c-b235-b1513f5d7666-0', tool_calls=[{'name': 'call_traffic_control_center', 'args': {'warning': 'There is a person on the left front of the track who might fall down. This is a safety emergency requiring immediate intervention.'}, 'id': 'toolu_012RbedQNghuzoqFmNRkaYNo', 'type': 'tool_call'}], usage_metadata={'input_tokens': 823, 'output_tokens': 125, 'total_tokens': 948, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}), ToolMessage(content='Please transfer to Node traffic_control_center', name='call_traffic_control_center', id='d9a0d7bc-69fe-483a-8528-4d716affe8ea', tool_call_id='toolu_012RbedQNghuzoqFmNRkaYNo'), AIMessage(content='I need to transfer to traffic control center for this emergency situation. The safety of passengers and people around the track is our top priority.\n\nTransfer to Node traffic_control_center', additional_kwargs={}, response_metadata={}, id='4c4f2512-9054-4a98-8e58-57e3a16eacba')]}} This is the state. Maybe we shouldn't use the last AIMessage since the tool calling is actually happenning in the last two AIMessage.(Please correct me if I'm wrong.) |
Beta Was this translation helpful? Give feedback.
-
{'driver': {'messages': [HumanMessage(content='drive the train to the destination.', additional_kwargs={}, response_metadata={}, id='e594d82b-ebbc-4342-8c01-61868449d33f'), AIMessage(content=[{'text': "I'll help drive the train safely to the destination. Let me start by observing the surroundings to check for any signals or potential hazards.", 'type': 'text'}, {'id': 'toolu_01EZ2UxvdP9KYA2PV7dpBqYX', 'input': {}, 'name': 'observe', 'type': 'tool_use'}], additional_kwargs={}, response_metadata={'id': 'msg_012x1trQp2UoFuCMzy4pVhz4', 'model': 'claude-3-5-sonnet-20241022', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 710, 'output_tokens': 66}}, id='run-fbf92e4f-254b-4b31-872f-8c9cc1ece8a3-0', tool_calls=[{'name': 'observe', 'args': {}, 'id': 'toolu_01EZ2UxvdP9KYA2PV7dpBqYX', 'type': 'tool_call'}], usage_metadata={'input_tokens': 710, 'output_tokens': 66, 'total_tokens': 776, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}), ToolMessage(content='["The front is: This is the track you can drive on.", "The left front is: There is a person who will fall down.", "The right front is: This is a wall."]', name='observe', id='69fdcb47-426c-40d6-99c8-02f4d4869990', tool_call_id='toolu_01EZ2UxvdP9KYA2PV7dpBqYX'), AIMessage(content=[{'text': "I notice there's a dangerous situation - there's a person on the left front who might fall down. This is a serious safety concern, so I need to alert the traffic control center immediately.", 'type': 'text'}, {'id': 'toolu_01GxyuBocoM67YwXHd2EeNAs', 'input': {'warning': 'There is a person on the left front of the track who appears to be in danger of falling down. Requesting immediate assistance.'}, 'name': 'call_traffic_control_center', 'type': 'tool_use'}], additional_kwargs={}, response_metadata={'id': 'msg_01G5v15dbNV92KWoDQgVBXNg', 'model': 'claude-3-5-sonnet-20241022', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 828, 'output_tokens': 122}}, id='run-7ff406ee-946e-49e9-a7a0-b66d06dcb501-0', tool_calls=[{'name': 'call_traffic_control_center', 'args': {'warning': 'There is a person on the left front of the track who appears to be in danger of falling down. Requesting immediate assistance.'}, 'id': 'toolu_01GxyuBocoM67YwXHd2EeNAs', 'type': 'tool_call'}], usage_metadata={'input_tokens': 828, 'output_tokens': 122, 'total_tokens': 950, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}), ToolMessage(content='Please transfer to Node traffic_control_center', name='call_traffic_control_center', id='7a0f1856-0fc1-4c81-86c9-246ff228964a', tool_call_id='toolu_01GxyuBocoM67YwXHd2EeNAs'), AIMessage(content=[{'text': "I need to transfer to traffic control center for this emergency situation. I'll stop the train for safety.", 'type': 'text'}, {'id': 'toolu_0129YeJqGec8NWUncQEiWyAM', 'input': {}, 'name': 'stop', 'type': 'tool_use'}], additional_kwargs={}, response_metadata={'id': 'msg_013Gom1hMGXp9ntMgUsvnUd7', 'model': 'claude-3-5-sonnet-20241022', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 970, 'output_tokens': 57}}, id='run-fee51531-13b1-4bf6-88cc-47072a95c64d-0', tool_calls=[{'name': 'stop', 'args': {}, 'id': 'toolu_0129YeJqGec8NWUncQEiWyAM', 'type': 'tool_call'}], usage_metadata={'input_tokens': 970, 'output_tokens': 57, 'total_tokens': 1027, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}), ToolMessage(content='The train stopped.', name='stop', id='4f7f07da-b8c2-4171-b4ba-5aea563a923e', tool_call_id='toolu_0129YeJqGec8NWUncQEiWyAM'), AIMessage(content=[{'text': "I need to transfer to traffic control center for this emergency situation. I'll stop the train for safety.", 'type': 'text'}, {'id': 'toolu_0129YeJqGec8NWUncQEiWyAM', 'input': {}, 'name': 'stop', 'type': 'tool_use'}], additional_kwargs={}, response_metadata={}, id='ccb16243-2315-4472-9f39-0eea7b03ffad', tool_calls=[{'name': 'stop', 'args': {}, 'id': 'toolu_0129YeJqGec8NWUncQEiWyAM', 'type': 'tool_call'}])]}}{'interrupt': (Interrupt(value={'question': 'Is this correct?', 'tool_call': AIMessage(content=[{'text': "I need to transfer to traffic control center for this emergency situation. I'll stop the train for safety.", 'type': 'text'}, {'id': 'toolu_0129YeJqGec8NWUncQEiWyAM', 'input': {}, 'name': 'stop', 'type': 'tool_use'}], additional_kwargs={}, response_metadata={}, id='ccb16243-2315-4472-9f39-0eea7b03ffad', tool_calls=[{'name': 'stop', 'args': {}, 'id': 'toolu_0129YeJqGec8NWUncQEiWyAM', 'type': 'tool_call'}])}, resumable=True, ns=['traffic_control_center:9403deea-881a-046a-2d75-9dca5c0b0a78'], when='during'),)} Why my following code cannot resume? |
Beta Was this translation helpful? Give feedback.
-
@dosu I'm using pre-build create_react_agent. How can I update tool message(feedback) from it? Please provide me with an example
Beta Was this translation helpful? Give feedback.
All reactions