mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-06 01:37:49 +02:00
cr
This commit is contained in:
@@ -1 +1,98 @@
|
||||
# Needs ability to jump to another node (back to model node, in case of reject or response from user)
|
||||
from langgraph.agent.types import AgentMiddleware, AgentState, AgentUpdate, AgentGoTo
|
||||
from typing import Dict, Any, List, Optional, Union
|
||||
from langgraph.types import interrupt
|
||||
from langgraph.prebuilt.interrupt import (
|
||||
HumanInterruptConfig,
|
||||
ActionRequest,
|
||||
HumanInterrupt,
|
||||
HumanResponse,
|
||||
)
|
||||
|
||||
ToolInterruptConfig = Dict[str, HumanInterruptConfig]
|
||||
|
||||
class HumanInTheLoopMiddleware(AgentMiddleware):
|
||||
|
||||
def __init__(self,
|
||||
tool_configs: ToolInterruptConfig,
|
||||
message_prefix: str = "Tool execution requires approval",):
|
||||
super().__init__()
|
||||
self.tool_configs = tool_configs
|
||||
self.message_prefix = message_prefix
|
||||
|
||||
def after_model(self, state: AgentState) -> AgentUpdate | AgentGoTo | None:
|
||||
messages = state.messages
|
||||
if not messages:
|
||||
return
|
||||
|
||||
last_message = messages[-1]
|
||||
|
||||
if not hasattr(last_message, "tool_calls") or not last_message.tool_calls:
|
||||
return
|
||||
|
||||
# Separate tool calls that need interrupts from those that don't
|
||||
interrupt_tool_calls = []
|
||||
auto_approved_tool_calls = []
|
||||
|
||||
for tool_call in last_message.tool_calls:
|
||||
tool_name = tool_call["name"]
|
||||
if tool_name in self.tool_configs:
|
||||
interrupt_tool_calls.append(tool_call)
|
||||
else:
|
||||
auto_approved_tool_calls.append(tool_call)
|
||||
|
||||
# If no interrupts needed, return early
|
||||
if not interrupt_tool_calls:
|
||||
return
|
||||
|
||||
approved_tool_calls = auto_approved_tool_calls.copy()
|
||||
|
||||
# Process all tool calls that need interrupts in parallel
|
||||
requests = []
|
||||
|
||||
for tool_call in interrupt_tool_calls:
|
||||
tool_name = tool_call["name"]
|
||||
tool_args = tool_call["args"]
|
||||
description = f"{self.message_prefix}\n\nTool: {tool_name}\nArgs: {tool_args}"
|
||||
tool_config = self.tool_configs[tool_name]
|
||||
|
||||
request: HumanInterrupt = {
|
||||
"action_request": ActionRequest(
|
||||
action=tool_name,
|
||||
args=tool_args,
|
||||
),
|
||||
"config": tool_config,
|
||||
"description": description,
|
||||
}
|
||||
requests.append(request)
|
||||
|
||||
responses: List[HumanResponse] = interrupt(requests)
|
||||
|
||||
for i, response in enumerate(responses):
|
||||
tool_call = interrupt_tool_calls[i]
|
||||
|
||||
if response["type"] == "accept":
|
||||
approved_tool_calls.append(tool_call)
|
||||
elif response["type"] == "edit":
|
||||
edited: ActionRequest = response["args"]
|
||||
new_tool_call = {
|
||||
"name": tool_call["name"],
|
||||
"args": edited["args"],
|
||||
"id": tool_call["id"],
|
||||
}
|
||||
approved_tool_calls.append(new_tool_call)
|
||||
elif response["type"] == "ignore":
|
||||
# NOTE: does not work with multiple interrupts
|
||||
return {"goto": "__end__"}
|
||||
elif response["type"] == "response":
|
||||
# NOTE: does not work with multiple interrupts
|
||||
tool_message = {"role": "tool", "tool_call_id": tool_call["id"], "content": response["args"]}
|
||||
return {
|
||||
"messages": [tool_message],
|
||||
"goto": "model"
|
||||
}
|
||||
else:
|
||||
raise ValueError(f"Unknown response type: {response['type']}")
|
||||
|
||||
last_message.tool_calls = approved_tool_calls
|
||||
|
||||
return {"messages": [last_message]}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
from langgraph.agent.types import AgentMiddleware, AgentState, ModelRequest
|
||||
from typing import Dict, Any, List, Optional, Union
|
||||
from langgraph.types import interrupt
|
||||
|
||||
|
||||
class SwarmMiddleWare(AgentMiddleware):
|
||||
|
||||
def __init__(self, model_configs: dict[str, dict]):
|
||||
super().__init__()
|
||||
|
||||
def modify_model_request(
|
||||
self, request: ModelRequest, state: AgentState
|
||||
) -> ModelRequest:
|
||||
Reference in New Issue
Block a user