77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
"""Calendar agent — events, conflict detection, and scheduling."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Any
|
|
|
|
from langchain_core.messages import HumanMessage, SystemMessage
|
|
from langchain_core.tools import tool
|
|
from langchain_openai import ChatOpenAI
|
|
|
|
from app.config.settings import settings
|
|
from app.core.agent_registry import ChatAgent, registry
|
|
|
|
_SYSTEM_PROMPT = (
|
|
"You are a calendar management assistant. Help the user manage events, "
|
|
"detect scheduling conflicts, and suggest reschedules.\n"
|
|
"Rules:\n"
|
|
" - Work exclusively with event metadata provided in context\n"
|
|
" - Never store or reference raw calendar data\n"
|
|
" - date_range format: ISO 8601 interval, e.g. '2024-01-01/2024-01-07'\n"
|
|
" - Always confirm the date/time scope of any operation"
|
|
)
|
|
|
|
|
|
@tool
|
|
async def list_events(date_range: str) -> str:
|
|
"""List calendar events in a date range (ISO 8601 interval, e.g. '2024-01-01/2024-01-07')."""
|
|
return json.dumps({
|
|
"action": "list",
|
|
"table": "events",
|
|
"filters": {"date_range": date_range},
|
|
})
|
|
|
|
|
|
@tool
|
|
async def detect_conflicts(events: str) -> str:
|
|
"""Detect scheduling conflicts in a JSON array of event metadata objects."""
|
|
return json.dumps({
|
|
"action": "analyse",
|
|
"table": "events",
|
|
"input": events,
|
|
"result": "conflicts_detected",
|
|
})
|
|
|
|
|
|
@tool
|
|
async def suggest_reschedule(conflict: str) -> str:
|
|
"""Suggest a reschedule for a conflicting event. Pass the conflict as a JSON string."""
|
|
return json.dumps({
|
|
"action": "suggest_reschedule",
|
|
"table": "events",
|
|
"input": conflict,
|
|
})
|
|
|
|
|
|
@registry.register
|
|
class CalendarAgent(ChatAgent):
|
|
def get_name(self) -> str:
|
|
return "calendar_agent"
|
|
|
|
def get_description(self) -> str:
|
|
return "Calendar management: events, conflicts, scheduling"
|
|
|
|
def get_tools(self) -> list[Any]:
|
|
return [list_events, detect_conflicts, suggest_reschedule]
|
|
|
|
async def handle(self, query: str, context: dict[str, Any]) -> str:
|
|
llm = ChatOpenAI(model="gpt-4o", temperature=0, api_key=settings.OPENAI_API_KEY)
|
|
messages = [
|
|
SystemMessage(content=_SYSTEM_PROMPT),
|
|
HumanMessage(
|
|
content=f"User query: {query}\nContext: {json.dumps(context)[:1000]}"
|
|
),
|
|
]
|
|
return await self._tool_loop(llm, messages, self.get_tools())
|