触发 interrupt 时,agent 会暂停 execution 并返回 control。检查 result 中是否有 interrupts,并相应处理。如果 user rejects an action,请包含清晰的 message,告诉 agent tool 未执行,以及下一步应该怎么做。
from langchain_core.utils.uuid import uuid7from langgraph.types import Command# Create config with thread_id for state persistenceconfig = {"configurable": {"thread_id": str(uuid7())}}# Invoke the agentresult = agent.invoke( {"messages": [{"role": "user", "content": "Delete the file temp.txt"}]}, config=config, version="v2",)# Check if execution was interruptedif result.interrupts: # Extract interrupt information interrupt_value = result.interrupts[0].value action_requests = interrupt_value["action_requests"] review_configs = interrupt_value["review_configs"] # Create a lookup map from tool name to review config config_map = {cfg["action_name"]: cfg for cfg in review_configs} # Display the pending actions to the user for action in action_requests: review_config = config_map[action["name"]] print(f"Tool: {action['name']}") print(f"Arguments: {action['args']}") print(f"Allowed decisions: {review_config['allowed_decisions']}") # Get user decisions (one per action_request, in order) decisions = [ { "type": "reject", "message": "User rejected deleting temp.txt. Do not retry deletion.", } ] # Resume execution with decisions result = agent.invoke( Command(resume={"decisions": decisions}), config=config, # Must use the same config! version="v2", )# Process final resultprint(result.value["messages"][-1].content)
config = {"configurable": {"thread_id": str(uuid7())}}result = agent.invoke( {"messages": [{ "role": "user", "content": "Delete temp.txt and send an email to admin@example.com" }]}, config=config, version="v2",)if result.interrupts: interrupt_value = result.interrupts[0].value action_requests = interrupt_value["action_requests"] # Two tools need approval assert len(action_requests) == 2 # Provide decisions in the same order as action_requests decisions = [ {"type": "approve"}, # First tool: delete_file { "type": "reject", "message": "User rejected this action. Do not retry this tool call.", } # Second tool: send_email ] result = agent.invoke( Command(resume={"decisions": decisions}), config=config, version="v2", )
if result.interrupts: interrupt_value = result.interrupts[0].value action_request = interrupt_value["action_requests"][0] # Original args from the agent print(action_request["args"]) # {"to": "everyone@company.com", ...} # User decides to edit the recipient decisions = [{ "type": "edit", "edited_action": { "name": action_request["name"], # Must include the tool name "args": {"to": "team@company.com", "subject": "...", "body": "..."} } }] result = agent.invoke( Command(resume={"decisions": decisions}), config=config, version="v2", )
from langchain.agents import create_agentfrom langchain_anthropic import ChatAnthropicfrom langchain.messages import HumanMessagefrom langchain.tools import toolfrom langgraph.checkpoint.memory import InMemorySaverfrom langgraph.types import Command, interruptfrom deepagents.graph import create_deep_agentfrom deepagents.middleware.subagents import CompiledSubAgent@tool(description="Request human approval before proceeding with an action.")def request_approval(action_description: str) -> str: """Request human approval using the interrupt() primitive.""" # interrupt() pauses execution and returns the value passed to Command(resume=...) approval = interrupt({ "type": "approval_request", "action": action_description, "message": f"Please approve or reject: {action_description}", }) if approval.get("approved"): return f"Action '{action_description}' was APPROVED. Proceeding..." else: return f"Action '{action_description}' was REJECTED. Reason: {approval.get('reason', 'No reason provided')}"def main(): checkpointer = InMemorySaver() model = ChatAnthropic( model_name="claude-sonnet-4-6", max_tokens=4096, ) compiled_subagent = create_agent( model=model, tools=[request_approval], name="approval-agent", ) parent_agent = create_deep_agent( model="google_genai:gemini-3.5-flash", checkpointer=checkpointer, subagents=[ CompiledSubAgent( name="approval-agent", description="An agent that can request approvals", runnable=compiled_subagent, ) ], ) thread_id = "test_interrupt_directly" config = {"configurable": {"thread_id": thread_id}} print("Invoking agent - sub-agent will use request_approval tool...") result = parent_agent.invoke( { "messages": [ HumanMessage( content="Use the task tool to launch the approval-agent sub-agent. " "Tell it to use the request_approval tool to request approval for 'deploying to production'." ) ] }, config=config, version="v2", ) # Check for interrupt if result.interrupts: interrupt_value = result.interrupts[0].value print(f"\nInterrupt received!") print(f" Type: {interrupt_value.get('type')}") print(f" Action: {interrupt_value.get('action')}") print(f" Message: {interrupt_value.get('message')}") print("\nResuming with Command(resume={'approved': True})...") result2 = parent_agent.invoke( Command(resume={"approved": True}), config=config, version="v2", ) if not result2.interrupts: print("\nExecution completed!") # Find the tool response tool_msgs = [m for m in result2.value.get("messages", []) if m.type == "tool"] if tool_msgs: print(f" Tool result: {tool_msgs[-1].content}") else: print("\nAnother interrupt occurred") else: print("\n No interrupt - the model may not have called request_approval")if __name__ == "__main__": main()
运行后会产生以下 output:
Invoking agent - sub-agent will use request_approval tool...Interrupt received! Type: approval_request Action: deploying to production Message: Please approve or reject: deploying to productionResuming with Command(resume={'approved': True})...Execution completed! Tool result: Great! The approval request has been processed. The action **"deploying to production"** was **APPROVED**. You can now proceed with the production deployment.
from langgraph.types import Commandconfig = {"configurable": {"thread_id": "fs-thread-1"}}result = agent.invoke( {"messages": [{"role": "user", "content": "Save the API key to /secrets/key.txt"}]}, config=config, version="v2",)if result.interrupts: action = result.interrupts[0].value["action_requests"][0] print(f"Approve {action['name']} on {action['args']}?") # Resume with the human decision (approve, edit, or reject). result = agent.invoke( Command(resume={"decisions": [{"type": "approve"}]}), config=config, # Same thread ID version="v2", )
if result.interrupts: interrupt_value = result.interrupts[0].value action_requests = interrupt_value["action_requests"] # Create one decision per action, in order decisions = [] for action in action_requests: decision = get_user_decision(action) # Your logic decisions.append(decision) result = agent.invoke( Command(resume={"decisions": decisions}), config=config, version="v2", )