Commit
·
cb09459
1
Parent(s):
2513120
add(agents): loggers + system prompt in base agent + filtering AI Messages in human resume
Browse files- pmcp/agents/executor.py +19 -12
- pmcp/agents/github_agent.py +5 -7
- pmcp/agents/planner.py +7 -3
- pmcp/agents/trello_agent.py +6 -7
- pmcp/nodes/human_interrupt_node.py +15 -11
- pmcp/nodes/human_resume_node.py +6 -2
pmcp/agents/executor.py
CHANGED
|
@@ -5,8 +5,8 @@ from langchain_core.tools import BaseTool
|
|
| 5 |
from langchain_openai import ChatOpenAI
|
| 6 |
from langchain_core.messages import HumanMessage
|
| 7 |
|
| 8 |
-
from pmcp.models.plan import PlanStep
|
| 9 |
from pmcp.models.state import PlanningState
|
|
|
|
| 10 |
|
| 11 |
|
| 12 |
class ExecutorAgent:
|
|
@@ -18,16 +18,21 @@ class ExecutorAgent:
|
|
| 18 |
)
|
| 19 |
|
| 20 |
def call_executor_agent(self, state: PlanningState):
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
|
|
|
| 26 |
HumanMessage(
|
| 27 |
-
content=f"The {
|
| 28 |
)
|
| 29 |
-
]
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
}
|
| 32 |
|
| 33 |
async def acall_executor_agent(self, state: PlanningState):
|
|
@@ -36,10 +41,12 @@ class ExecutorAgent:
|
|
| 36 |
messages = []
|
| 37 |
if len(state.plan.steps) > plan_step_index:
|
| 38 |
current_step = state.plan.steps[plan_step_index]
|
| 39 |
-
messages = [
|
|
|
|
| 40 |
content=f"The {current_step.agent} agent should perform the following action:\n{current_step.description}"
|
| 41 |
-
)
|
| 42 |
-
|
|
|
|
| 43 |
return {
|
| 44 |
"plan_step": plan_step_index + 1,
|
| 45 |
"messages": messages,
|
|
|
|
| 5 |
from langchain_openai import ChatOpenAI
|
| 6 |
from langchain_core.messages import HumanMessage
|
| 7 |
|
|
|
|
| 8 |
from pmcp.models.state import PlanningState
|
| 9 |
+
from loguru import logger
|
| 10 |
|
| 11 |
|
| 12 |
class ExecutorAgent:
|
|
|
|
| 18 |
)
|
| 19 |
|
| 20 |
def call_executor_agent(self, state: PlanningState):
|
| 21 |
+
plan_step_index = state.plan_step
|
| 22 |
+
current_step = None
|
| 23 |
+
messages = []
|
| 24 |
+
if len(state.plan.steps) > plan_step_index:
|
| 25 |
+
current_step = state.plan.steps[plan_step_index]
|
| 26 |
+
messages = [
|
| 27 |
HumanMessage(
|
| 28 |
+
content=f"The {current_step.agent} agent should perform the following action:\n{current_step.description}"
|
| 29 |
)
|
| 30 |
+
]
|
| 31 |
+
logger.info(f"The Executor is executing step: {current_step}")
|
| 32 |
+
return {
|
| 33 |
+
"plan_step": plan_step_index + 1,
|
| 34 |
+
"messages": messages,
|
| 35 |
+
"current_step": current_step,
|
| 36 |
}
|
| 37 |
|
| 38 |
async def acall_executor_agent(self, state: PlanningState):
|
|
|
|
| 41 |
messages = []
|
| 42 |
if len(state.plan.steps) > plan_step_index:
|
| 43 |
current_step = state.plan.steps[plan_step_index]
|
| 44 |
+
messages = [
|
| 45 |
+
HumanMessage(
|
| 46 |
content=f"The {current_step.agent} agent should perform the following action:\n{current_step.description}"
|
| 47 |
+
)
|
| 48 |
+
]
|
| 49 |
+
logger.info(f"The Executor is executing step: {current_step}")
|
| 50 |
return {
|
| 51 |
"plan_step": plan_step_index + 1,
|
| 52 |
"messages": messages,
|
pmcp/agents/github_agent.py
CHANGED
|
@@ -2,10 +2,10 @@ from typing import List, Optional
|
|
| 2 |
|
| 3 |
from pmcp.agents.agent_base import AgentBlueprint
|
| 4 |
from langchain_core.tools import BaseTool
|
| 5 |
-
from langchain_core.messages import SystemMessage
|
| 6 |
from langchain_openai import ChatOpenAI
|
| 7 |
|
| 8 |
from pmcp.models.state import PlanningState
|
|
|
|
| 9 |
|
| 10 |
SYSTEM_PROMPT = """
|
| 11 |
You are an assistant that can manage Trello boards and projects.
|
|
@@ -24,13 +24,11 @@ class GithubAgent:
|
|
| 24 |
)
|
| 25 |
|
| 26 |
def call_github_agent(self, state: PlanningState):
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
)
|
| 30 |
return {"messages": [response]}
|
| 31 |
|
| 32 |
async def acall_github_agent(self, state: PlanningState):
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
)
|
| 36 |
return {"messages": [response]}
|
|
|
|
| 2 |
|
| 3 |
from pmcp.agents.agent_base import AgentBlueprint
|
| 4 |
from langchain_core.tools import BaseTool
|
|
|
|
| 5 |
from langchain_openai import ChatOpenAI
|
| 6 |
|
| 7 |
from pmcp.models.state import PlanningState
|
| 8 |
+
from loguru import logger
|
| 9 |
|
| 10 |
SYSTEM_PROMPT = """
|
| 11 |
You are an assistant that can manage Trello boards and projects.
|
|
|
|
| 24 |
)
|
| 25 |
|
| 26 |
def call_github_agent(self, state: PlanningState):
|
| 27 |
+
logger.info("Calling Github agent...")
|
| 28 |
+
response = self.agent.call_agent(state.messages)
|
|
|
|
| 29 |
return {"messages": [response]}
|
| 30 |
|
| 31 |
async def acall_github_agent(self, state: PlanningState):
|
| 32 |
+
logger.info("Calling Github agent...")
|
| 33 |
+
response = await self.agent.acall_agent(state.messages)
|
|
|
|
| 34 |
return {"messages": [response]}
|
pmcp/agents/planner.py
CHANGED
|
@@ -2,11 +2,11 @@ from typing import List, Optional
|
|
| 2 |
|
| 3 |
from pmcp.agents.agent_base import AgentBlueprint
|
| 4 |
from langchain_core.tools import BaseTool
|
| 5 |
-
from langchain_core.messages import SystemMessage
|
| 6 |
from langchain_openai import ChatOpenAI
|
| 7 |
|
| 8 |
from pmcp.models.plan import Plan
|
| 9 |
from pmcp.models.state import PlanningState
|
|
|
|
| 10 |
|
| 11 |
SYSTEM_PROMPT = """
|
| 12 |
You are a Planner Agent responsible for breaking down high-level project goals into clear, actionable steps. You do not execute tasks yourself — instead, you delegate them to two specialized agents:
|
|
@@ -38,15 +38,19 @@ class PlannerAgent:
|
|
| 38 |
)
|
| 39 |
|
| 40 |
def call_planner_agent(self, state: PlanningState):
|
|
|
|
| 41 |
response = self.agent.call_agent_structured(
|
| 42 |
-
messages=
|
| 43 |
clazz=Plan,
|
| 44 |
)
|
|
|
|
| 45 |
return {"plan": response, "plan_step": 0, "current_step": None}
|
| 46 |
|
| 47 |
async def acall_planner_agent(self, state: PlanningState):
|
|
|
|
| 48 |
response = await self.agent.acall_agent_structured(
|
| 49 |
-
messages=
|
| 50 |
clazz=Plan,
|
| 51 |
)
|
|
|
|
| 52 |
return {"plan": response, "plan_step": 0, "current_step": None}
|
|
|
|
| 2 |
|
| 3 |
from pmcp.agents.agent_base import AgentBlueprint
|
| 4 |
from langchain_core.tools import BaseTool
|
|
|
|
| 5 |
from langchain_openai import ChatOpenAI
|
| 6 |
|
| 7 |
from pmcp.models.plan import Plan
|
| 8 |
from pmcp.models.state import PlanningState
|
| 9 |
+
from loguru import logger
|
| 10 |
|
| 11 |
SYSTEM_PROMPT = """
|
| 12 |
You are a Planner Agent responsible for breaking down high-level project goals into clear, actionable steps. You do not execute tasks yourself — instead, you delegate them to two specialized agents:
|
|
|
|
| 38 |
)
|
| 39 |
|
| 40 |
def call_planner_agent(self, state: PlanningState):
|
| 41 |
+
logger.info("Calling Planner agent...")
|
| 42 |
response = self.agent.call_agent_structured(
|
| 43 |
+
messages=state.messages,
|
| 44 |
clazz=Plan,
|
| 45 |
)
|
| 46 |
+
logger.info(f"Building plan: {response}")
|
| 47 |
return {"plan": response, "plan_step": 0, "current_step": None}
|
| 48 |
|
| 49 |
async def acall_planner_agent(self, state: PlanningState):
|
| 50 |
+
logger.info("Calling Planner agent...")
|
| 51 |
response = await self.agent.acall_agent_structured(
|
| 52 |
+
messages=state.messages,
|
| 53 |
clazz=Plan,
|
| 54 |
)
|
| 55 |
+
logger.info(f"Building plan: {response}")
|
| 56 |
return {"plan": response, "plan_step": 0, "current_step": None}
|
pmcp/agents/trello_agent.py
CHANGED
|
@@ -2,10 +2,11 @@ from typing import List
|
|
| 2 |
|
| 3 |
from pmcp.agents.agent_base import AgentBlueprint
|
| 4 |
from langchain_core.tools import BaseTool
|
| 5 |
-
from langchain_core.messages import SystemMessage
|
| 6 |
from langchain_openai import ChatOpenAI
|
| 7 |
|
| 8 |
from pmcp.models.state import PlanningState
|
|
|
|
|
|
|
| 9 |
|
| 10 |
SYSTEM_PROMPT = """
|
| 11 |
You are an assistant that can manage Trello boards and projects.
|
|
@@ -24,13 +25,11 @@ class TrelloAgent:
|
|
| 24 |
)
|
| 25 |
|
| 26 |
def call_trello_agent(self, state: PlanningState):
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
)
|
| 30 |
return {"messages": [response]}
|
| 31 |
|
| 32 |
async def acall_trello_agent(self, state: PlanningState):
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
)
|
| 36 |
return {"messages": [response]}
|
|
|
|
| 2 |
|
| 3 |
from pmcp.agents.agent_base import AgentBlueprint
|
| 4 |
from langchain_core.tools import BaseTool
|
|
|
|
| 5 |
from langchain_openai import ChatOpenAI
|
| 6 |
|
| 7 |
from pmcp.models.state import PlanningState
|
| 8 |
+
from loguru import logger
|
| 9 |
+
|
| 10 |
|
| 11 |
SYSTEM_PROMPT = """
|
| 12 |
You are an assistant that can manage Trello boards and projects.
|
|
|
|
| 25 |
)
|
| 26 |
|
| 27 |
def call_trello_agent(self, state: PlanningState):
|
| 28 |
+
logger.info("Calling Trello Agent...")
|
| 29 |
+
response = self.agent.call_agent(state.messages)
|
|
|
|
| 30 |
return {"messages": [response]}
|
| 31 |
|
| 32 |
async def acall_trello_agent(self, state: PlanningState):
|
| 33 |
+
logger.info("Calling Trello Agent...")
|
| 34 |
+
response = await self.agent.acall_agent(state.messages)
|
|
|
|
| 35 |
return {"messages": [response]}
|
pmcp/nodes/human_interrupt_node.py
CHANGED
|
@@ -2,9 +2,10 @@ from typing import List, Optional
|
|
| 2 |
|
| 3 |
from pmcp.agents.agent_base import AgentBlueprint
|
| 4 |
from langchain_core.tools import BaseTool
|
| 5 |
-
from langchain_core.messages import
|
| 6 |
from langchain_openai import ChatOpenAI
|
| 7 |
from langgraph.types import Command, interrupt
|
|
|
|
| 8 |
|
| 9 |
from pmcp.models.state import PlanningState
|
| 10 |
|
|
@@ -27,28 +28,31 @@ class HumanInterruptNode:
|
|
| 27 |
)
|
| 28 |
|
| 29 |
def call_human_interrupt_agent(self, state: PlanningState):
|
| 30 |
-
last_message = state.messages[-1]
|
| 31 |
-
|
| 32 |
-
#TODO: chiedere a Gerlax lo strumento
|
| 33 |
try:
|
| 34 |
tool_call = last_message.tool_calls[-1]
|
| 35 |
except Exception:
|
| 36 |
-
last_message = state.messages[
|
|
|
|
|
|
|
| 37 |
tool_call = last_message.tool_calls[-1]
|
| 38 |
|
| 39 |
-
|
| 40 |
-
|
| 41 |
if tool_call.get("name", "").startswith("get_"):
|
| 42 |
-
return Command(goto="tool")
|
| 43 |
-
|
| 44 |
response = self.agent.call_agent(
|
| 45 |
-
messages=[
|
|
|
|
|
|
|
|
|
|
| 46 |
)
|
| 47 |
human_review = interrupt(response.content)
|
| 48 |
|
| 49 |
confirm_action = human_review.confirm_action
|
| 50 |
changes_description = human_review.changes_description
|
| 51 |
-
|
| 52 |
if confirm_action:
|
| 53 |
return Command(goto="tool")
|
| 54 |
|
|
|
|
| 2 |
|
| 3 |
from pmcp.agents.agent_base import AgentBlueprint
|
| 4 |
from langchain_core.tools import BaseTool
|
| 5 |
+
from langchain_core.messages import AIMessage
|
| 6 |
from langchain_openai import ChatOpenAI
|
| 7 |
from langgraph.types import Command, interrupt
|
| 8 |
+
from langchain_core.messages.utils import filter_messages
|
| 9 |
|
| 10 |
from pmcp.models.state import PlanningState
|
| 11 |
|
|
|
|
| 28 |
)
|
| 29 |
|
| 30 |
def call_human_interrupt_agent(self, state: PlanningState):
|
| 31 |
+
last_message = filter_messages(state.messages, include_types=[AIMessage])[-1]
|
| 32 |
+
|
| 33 |
+
# TODO: chiedere a Gerlax lo strumento
|
| 34 |
try:
|
| 35 |
tool_call = last_message.tool_calls[-1]
|
| 36 |
except Exception:
|
| 37 |
+
last_message = filter_messages(state.messages, include_types=[AIMessage])[
|
| 38 |
+
-2
|
| 39 |
+
]
|
| 40 |
tool_call = last_message.tool_calls[-1]
|
| 41 |
|
|
|
|
|
|
|
| 42 |
if tool_call.get("name", "").startswith("get_"):
|
| 43 |
+
return Command(goto="tool")
|
| 44 |
+
|
| 45 |
response = self.agent.call_agent(
|
| 46 |
+
messages=[
|
| 47 |
+
AIMessage(content=f"Tool Calling details: {str(tool_call)}"),
|
| 48 |
+
]
|
| 49 |
+
+ state.messages,
|
| 50 |
)
|
| 51 |
human_review = interrupt(response.content)
|
| 52 |
|
| 53 |
confirm_action = human_review.confirm_action
|
| 54 |
changes_description = human_review.changes_description
|
| 55 |
+
|
| 56 |
if confirm_action:
|
| 57 |
return Command(goto="tool")
|
| 58 |
|
pmcp/nodes/human_resume_node.py
CHANGED
|
@@ -2,11 +2,12 @@ from typing import List, Optional
|
|
| 2 |
|
| 3 |
from pmcp.agents.agent_base import AgentBlueprint
|
| 4 |
from langchain_core.tools import BaseTool
|
| 5 |
-
from langchain_core.messages import
|
| 6 |
from langchain_openai import ChatOpenAI
|
| 7 |
from langgraph.types import Command
|
| 8 |
|
| 9 |
from pmcp.models.resume_trigger import ResumeTrigger
|
|
|
|
| 10 |
|
| 11 |
|
| 12 |
SYSTEM_PROMPT = """
|
|
@@ -29,8 +30,11 @@ class HumanResumeNode:
|
|
| 29 |
)
|
| 30 |
|
| 31 |
def call_human_interrupt_agent(self, user_message: str):
|
|
|
|
| 32 |
response = self.agent.call_agent_structured(
|
| 33 |
-
[
|
|
|
|
|
|
|
| 34 |
clazz=ResumeTrigger,
|
| 35 |
)
|
| 36 |
|
|
|
|
| 2 |
|
| 3 |
from pmcp.agents.agent_base import AgentBlueprint
|
| 4 |
from langchain_core.tools import BaseTool
|
| 5 |
+
from langchain_core.messages import HumanMessage
|
| 6 |
from langchain_openai import ChatOpenAI
|
| 7 |
from langgraph.types import Command
|
| 8 |
|
| 9 |
from pmcp.models.resume_trigger import ResumeTrigger
|
| 10 |
+
from loguru import logger
|
| 11 |
|
| 12 |
|
| 13 |
SYSTEM_PROMPT = """
|
|
|
|
| 30 |
)
|
| 31 |
|
| 32 |
def call_human_interrupt_agent(self, user_message: str):
|
| 33 |
+
logger.info("Human resumer agent...")
|
| 34 |
response = self.agent.call_agent_structured(
|
| 35 |
+
[
|
| 36 |
+
HumanMessage(content=user_message),
|
| 37 |
+
],
|
| 38 |
clazz=ResumeTrigger,
|
| 39 |
)
|
| 40 |
|