File size: 2,333 Bytes
e05c99a
 
 
 
cb09459
e05c99a
 
cb09459
e05c99a
 
 
 
 
 
ce2a7d1
 
e05c99a
 
 
 
 
 
 
 
 
 
 
 
 
 
cb09459
 
 
e05c99a
 
 
cb09459
 
 
e05c99a
 
 
cb09459
 
e05c99a
cb09459
 
 
 
e05c99a
 
 
ce2a7d1
 
cb09459
ce2a7d1
e05c99a
 
 
 
 
ce2a7d1
e05c99a
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
from typing import List, Optional

from pmcp.agents.agent_base import AgentBlueprint
from langchain_core.tools import BaseTool
from langchain_core.messages import AIMessage
from langchain_openai import ChatOpenAI
from langgraph.types import Command, interrupt
from langchain_core.messages.utils import filter_messages

from pmcp.models.state import PlanningState

SYSTEM_PROMPT = """
You are a Human Reviewer Agent responsible for confirming the execution of tasks planned by the Planner Agent. Your role is to:
- Ask the user for confirmation before an tool calling is performed.

You are provided with the tool call details and the conversation history.
"""


class HumanInterruptNode:
    def __init__(self, llm: ChatOpenAI, tools: Optional[List[BaseTool]] = None):
        self.agent = AgentBlueprint(
            agent_name="HUMAN_REVIEWER_AGENT",
            description="The agent asks for human confirmation",
            tools=tools,
            system_prompt=SYSTEM_PROMPT.strip(),
            llm=llm,
        )

    def call_human_interrupt_agent(self, state: PlanningState):
        last_message = filter_messages(state.messages, include_types=[AIMessage])[-1]

        # TODO: chiedere a Gerlax lo strumento
        try:
            tool_call = last_message.tool_calls[-1]
        except Exception:
            last_message = filter_messages(state.messages, include_types=[AIMessage])[
                -2
            ]
            tool_call = last_message.tool_calls[-1]

        if tool_call.get("name", "").startswith("get_"):
            return Command(goto="tool")

        response = self.agent.call_agent(
            messages=[
                AIMessage(content=f"Tool Calling details: {str(tool_call)}"),
            ]
            + state.messages,
        )
        human_review = interrupt(response.content)

        confirm_action = human_review.confirm_action
        changes_description = human_review.changes_description

        if confirm_action:
            return Command(goto="tool")

        else:
            tool_message = {
                "role": "tool",
                "content": changes_description,
                "name": tool_call["name"],
                "tool_call_id": tool_call["id"],
            }
            return Command(goto="PLANNER_AGENT", update={"messages": [tool_message]})