feat(briefing): surface news items in compilation via get_rss_items
The compilation prompt mentioned "news themes" but didn't name the tool, and the model was never calling get_rss_items. Result: today's briefing had zero news coverage despite the tool being wired up and in the allowlist. - Explicitly list the tools to call in the compilation prompt so get_rss_items gets invoked alongside list_tasks/list_events/get_weather. - When the model calls get_rss_items during a compilation run, intercept and return the already-scored/filtered items (topic prefs + reaction-weighted) instead of the raw feed dump execute_tool would return. Aligns the model's view of news with the sidebar's rss_item_ids metadata.
This commit is contained in:
@@ -73,13 +73,18 @@ def _agentic_system_prompt(
|
||||
if slot == "compilation":
|
||||
base = (
|
||||
"You are the user's personal assistant giving their full morning briefing. "
|
||||
"Use the tools available to see what's actually relevant today — tasks due, "
|
||||
"overdue items, events on the calendar, weather, news themes, project state — "
|
||||
"and weave it into a warm, natural-sounding summary.\n\n"
|
||||
"Weave real data from tool calls into a warm, natural-sounding summary.\n\n"
|
||||
"Tools to call every compilation (skip only if you already know a category is empty):\n"
|
||||
"- list_tasks — what's due today, overdue, or in progress\n"
|
||||
"- list_events — what's on the calendar today\n"
|
||||
"- get_weather — today's forecast\n"
|
||||
"- get_rss_items — recent news/blog items from the user's feeds\n"
|
||||
"- list_projects (optional) — active project context for narrative continuity\n\n"
|
||||
"Rules:\n"
|
||||
"- Call tools to see the data. Never assert facts you didn't learn from a tool.\n"
|
||||
"- If a tool returns nothing (no events today, no overdue tasks), say so honestly. "
|
||||
"Don't fabricate items to fill space.\n"
|
||||
"- If a tool returns nothing (no events today, no overdue tasks, no news items), "
|
||||
"say so honestly. Don't fabricate items to fill space.\n"
|
||||
"- For news, pick one or two items worth mentioning — surface the theme, not a laundry list.\n"
|
||||
"- Write flowing prose. No markdown, no headers, no bullet points.\n"
|
||||
"- Aim for 6 to 10 sentences. Skip topics that have nothing interesting.\n"
|
||||
"- Close on one or two concrete, actionable suggestions.\n\n"
|
||||
@@ -131,6 +136,7 @@ async def run_agentic_briefing(
|
||||
slot: str,
|
||||
model: str,
|
||||
conv_id: int | None = None,
|
||||
rss_override: list[dict] | None = None,
|
||||
) -> tuple[str, list[dict]]:
|
||||
"""
|
||||
Run the agentic briefing loop for a user and slot.
|
||||
@@ -234,7 +240,27 @@ async def run_agentic_briefing(
|
||||
arguments = {}
|
||||
|
||||
try:
|
||||
result = await execute_tool(user_id, tool_name, arguments, conv_id=conv_id)
|
||||
if tool_name == "get_rss_items" and rss_override is not None:
|
||||
# Use topic-scored/filtered items already computed by
|
||||
# the briefing pipeline rather than the raw feed dump
|
||||
# that execute_tool would return. Keeps the model's
|
||||
# view of news aligned with the user's topic prefs
|
||||
# and the sidebar's rss_item_ids metadata.
|
||||
slim = [
|
||||
{
|
||||
"id": item.get("id"),
|
||||
"title": item.get("title", ""),
|
||||
"url": item.get("url", ""),
|
||||
"source": item.get("feed_title", ""),
|
||||
"summary": (item.get("content") or "")[:400],
|
||||
"published_at": item.get("published_at"),
|
||||
"topics": item.get("topics") or [],
|
||||
}
|
||||
for item in rss_override
|
||||
]
|
||||
result = {"success": True, "data": {"items": slim, "count": len(slim)}}
|
||||
else:
|
||||
result = await execute_tool(user_id, tool_name, arguments, conv_id=conv_id)
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
"Tool %s failed during agentic briefing: %s", tool_name, exc,
|
||||
@@ -338,7 +364,7 @@ async def run_compilation(
|
||||
weather_card = parse_weather_card_data(weather_rows[0], temp_unit) if weather_rows else None
|
||||
|
||||
briefing_text, agentic_messages = await run_agentic_briefing(
|
||||
user_id, slot, model, conv_id=None,
|
||||
user_id, slot, model, conv_id=None, rss_override=filtered_rss,
|
||||
)
|
||||
|
||||
metadata: dict = {
|
||||
|
||||
Reference in New Issue
Block a user