Notification Tools
The AI assistant (Vernis) can view and manage notifications on behalf of the user through four tools. These run in the assistant’s chat context — not during voice calls or task execution.
Tools at a Glance
Section titled “Tools at a Glance”| Tool | Permission Required | Purpose |
|---|---|---|
get_notifications | Notification:Collection:List | List notifications with filters |
get_unread_count | Notification:Collection:List | Get unread notification count |
mark_notification_read | Notification:Instance:MarkRead | Mark a single notification as read |
mark_all_notifications_read | Notification:Instance:MarkRead | Mark all notifications as read |
Registration
Section titled “Registration”Tools are registered in collect_assistant_tools in tool_registry_service.rs. The registry checks the user’s session permissions and only includes tools the user is authorized to use:
// List/count tools — need Collection:Listif can_list_notifications { tools.push(build_get_notifications_tool(session.clone())); tools.push(build_get_unread_count_tool(session.clone()));}
// Mark-read tools — need Instance:MarkReadif can_mark_notifications_read { tools.push(build_mark_notification_read_tool(session.clone())); tools.push(build_mark_all_notifications_read_tool(session.clone()));}The system prompt’s capabilities section is also updated dynamically — bold markers flag write operations so the AI knows to use confirmation flows.
get_notifications
Section titled “get_notifications”Lists the user’s notifications with optional filters.
Input:
| Parameter | Type | Default | Description |
|---|---|---|---|
category | Option<String> | None | Filter: "call", "task", "task_completed", "plan", "system" |
unread_only | Option<bool> | None | When true, only unread notifications |
time_range | String | "all_time" | "today", "yesterday", "last_7_days", "last_30_days", "last_90_days", "all_time" |
limit | Option<u64> | 20 | Results per page (1–50) |
offset | Option<u64> | 0 | Pagination offset |
Response:
{ "notifications": [ { "id": "a1b2c3d4-...", "category": "task", "title": "New task assigned", "body": "Follow up with client about proposal", "entity_type": "task", "entity_id": "e5f6a7b8-...", "entity_deep_link": "/tasks/e5f6a7b8-...", "is_read": false, "created_at": "2026-03-28 14:30:00" } ], "count": 1, "total_count": 42, "notifications_page": "/notifications"}Each notification includes an entity_deep_link generated by page_context_mapper::entity_deep_link — this lets the assistant point users to the relevant page.
get_unread_count
Section titled “get_unread_count”Returns the number of unread notifications. No parameters.
{ "unread_count": 7, "notifications_page": "/notifications"}mark_notification_read
Section titled “mark_notification_read”Marks a single notification as read using a two-step confirmation pattern.
Input:
| Parameter | Type | Description |
|---|---|---|
id | String | Notification UUID |
confirmed | bool | false = preview, true = execute |
Preview response (confirmed: false):
{ "action": "mark_notification_read", "status": "preview", "preview": { "id": "a1b2c3d4-...", "title": "New task assigned", "category": "task", "created_at": "2026-03-28 14:30:00" }, "message": "Ready to mark notification 'New task assigned' as read. Call again with confirmed=true to proceed."}Execution response (confirmed: true):
{ "action": "mark_notification_read", "status": "completed", "notification_id": "a1b2c3d4-...", "notifications_page": "/notifications", "message": "Notification 'New task assigned' marked as read."}If the notification is already read, returns status: "already_read" without requiring confirmation.
mark_all_notifications_read
Section titled “mark_all_notifications_read”Marks all unread notifications as read. Same two-step confirmation pattern.
Input:
| Parameter | Type | Description |
|---|---|---|
confirmed | bool | false = preview with unread count, true = execute |
Preview response:
{ "action": "mark_all_notifications_read", "status": "preview", "preview": { "unread_count": 7 }, "message": "Ready to mark 7 notification(s) as read. Call again with confirmed=true to proceed."}Uses Entity::update_many() to batch-update all unread notifications in a single query.
Two-Step Confirmation Pattern
Section titled “Two-Step Confirmation Pattern”The write tools (mark_notification_read, mark_all_notifications_read) follow Loquent’s standard confirmation pattern for destructive assistant actions:
- Preview call (
confirmed: false) — returns what will happen without making changes - The AI presents the preview to the user and asks for approval
- Execute call (
confirmed: true) — performs the action
This pattern is signaled to the AI via bold markers in the system prompt capabilities section, ensuring the assistant always asks before modifying data.
Source Files
Section titled “Source Files”| File | Purpose |
|---|---|
src/mods/assistant/tools/notifications/mod.rs | Module exports |
src/mods/assistant/tools/notifications/ai_get_notifications_tool.rs | List tool |
src/mods/assistant/tools/notifications/ai_get_unread_count_tool.rs | Count tool |
src/mods/assistant/tools/notifications/ai_mark_notification_read_tool.rs | Single mark-read |
src/mods/assistant/tools/notifications/ai_mark_all_notifications_read_tool.rs | Bulk mark-read |
src/mods/assistant/services/tool_registry_service.rs | Registration logic |
src/mods/assistant/services/build_system_prompt_service.rs | System prompt integration |