From 024075329db8608a93e66a26074b68fc38d4f4ca Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sat, 28 Mar 2026 13:50:13 -0400 Subject: [PATCH] feat: add add_rss_feed LLM tool so users can add feeds via chat Co-Authored-By: Claude Sonnet 4.6 --- src/fabledassistant/services/tools.py | 49 +++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/fabledassistant/services/tools.py b/src/fabledassistant/services/tools.py index 8bebb60..3d31e38 100644 --- a/src/fabledassistant/services/tools.py +++ b/src/fabledassistant/services/tools.py @@ -603,6 +603,31 @@ _CORE_TOOLS = [ }, }, }, + { + "type": "function", + "function": { + "name": "add_rss_feed", + "description": ( + "Add a new RSS feed to the user's briefing. Use this when the user asks to " + "subscribe to, follow, add, or track a feed, blog, news source, subreddit, or podcast URL. " + "The feed will be fetched immediately after adding." + ), + "parameters": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "The RSS/Atom feed URL to add.", + }, + "category": { + "type": "string", + "description": "Optional category label (e.g. 'news', 'tech', 'reddit'). Omit if unsure.", + }, + }, + "required": ["url"], + }, + }, + }, { "type": "function", "function": { @@ -1807,6 +1832,30 @@ async def execute_tool( items = await get_recent_items(user_id, limit=limit) return {"data": {"items": items, "count": len(items)}} + elif tool_name == "add_rss_feed": + import asyncio as _asyncio + from fabledassistant.models import async_session as _async_session + from fabledassistant.models.rss_feed import RssFeed + from fabledassistant.services.rss import fetch_and_cache_feed + from sqlalchemy import select as _select + url = str(arguments.get("url", "")).strip() + if not url: + return {"error": "url is required"} + category = arguments.get("category") or None + async with _async_session() as session: + existing = await session.execute( + _select(RssFeed).where(RssFeed.user_id == user_id, RssFeed.url == url) + ) + if existing.scalars().first(): + return {"error": "Feed already added", "url": url} + feed = RssFeed(user_id=user_id, url=url, title="", category=category) + session.add(feed) + await session.commit() + await session.refresh(feed) + feed_id = feed.id + _asyncio.create_task(fetch_and_cache_feed(feed_id, url)) + return {"data": {"id": feed_id, "url": url, "message": "Feed added and fetching started."}} + elif tool_name == "search_projects": from difflib import SequenceMatcher query = str(arguments.get("query", "")).lower()