feat(ml): multi-agent context framework + v4 orchestrator prompt
Adds ml/agents/ — five specialised sub-agents (overdue_task, momentum, time_of_day, recent_patterns, focus_area) each producing a prompt snippet from user signals. A registry wires them up; the orchestrator prompt in ml/serving/prompts.py synthesises their outputs into one tip via LiteLLM. Also wires /api/agents route in the API and updates the Dockerfile to copy the full ml/ tree with PYTHONPATH=/app so agent imports resolve correctly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
42
ml/agents/overdue_task.py
Normal file
42
ml/agents/overdue_task.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from __future__ import annotations
|
||||
from typing import ClassVar
|
||||
from .base import BaseAgent, AgentInput, AgentOutput
|
||||
|
||||
|
||||
class OverdueTaskAgent(BaseAgent):
|
||||
"""Reports the user's overdue tasks by count and age."""
|
||||
agent_id: ClassVar[str] = "overdue-task"
|
||||
ttl_seconds: ClassVar[int] = 3600 # 1h — overdue status changes infrequently
|
||||
version: ClassVar[str] = "1.0.0"
|
||||
|
||||
def compute(self, inp: AgentInput) -> AgentOutput:
|
||||
overdue = [t for t in inp.tasks if t.get("is_overdue")]
|
||||
top = sorted(overdue, key=lambda t: -t.get("task_age_days", 0))[:3]
|
||||
|
||||
if not overdue:
|
||||
prompt = "The user has no overdue tasks at this time."
|
||||
elif len(overdue) == 1:
|
||||
t = top[0]
|
||||
age = round(t.get("task_age_days", 0))
|
||||
prompt = (
|
||||
f'The user has 1 overdue task: "{t["content"]}" '
|
||||
f"({age} day{'s' if age != 1 else ''} overdue)."
|
||||
)
|
||||
else:
|
||||
items = ", ".join(
|
||||
f'"{t["content"]}" ({round(t.get("task_age_days", 0))}d)'
|
||||
for t in top
|
||||
)
|
||||
prompt = (
|
||||
f"The user has {len(overdue)} overdue tasks. "
|
||||
f"Top {len(top)}: {items}."
|
||||
)
|
||||
|
||||
snapshot = {
|
||||
"overdue_count": len(overdue),
|
||||
"top_overdue": [
|
||||
{"content": t["content"], "task_age_days": t.get("task_age_days", 0)}
|
||||
for t in top
|
||||
],
|
||||
}
|
||||
return self._make_output(inp, prompt, snapshot)
|
||||
Reference in New Issue
Block a user