Notes & reminders (list manager)
A note is a Home Assistant todo-list item with no due date; a reminder is one with a due date/time. Either kind can live on any HA todo.* list — not just Saga's own — resolved by natural name the same way control_ha resolves a light target.
How to use it
"make a note that the gate code is 4471"
"note that we're out of coffee filters"
"what's on my list" / "read my notes"
"remind me to call mom in 20 minutes"
"remind me to water the plants on Friday"
"remind me tomorrow morning to take the trash out"
"what are my reminders" / "anything due today"
"I did that" / "mark the vet reminder done" / "cross that off my list"
Works against other lists too, by naming them:
"add stamps to my shopping list"
"what's on the shopping list"
"remind me to buy stamps on Friday on the shopping list"
How it works
- Tools (
brain/tools.py):add_note,add_reminder,list_notes,list_reminders,complete_item. All take an optionallist_name; omitted (or any generic "my list"/"my notes" phrasing — see_DEFAULT_LIST_RE), it resolves toSAGA_LIST(envSAGA_TODO_ENTITY, defaulttodo.saga). - List resolution (
_resolve_list): natural name →todo.*entity_id viasearch_entities()inha_client.py, domain-filtered totodo— the todo-list analogue ofcontrol_ha's_resolve_entity(see home-control.md). - Due-date math is never the model's job.
add_reminderextracts slots only —when_relative_minutes(simple unit multiplication, e.g. "2 hours" →120), orwhen_day(today/tomorrow/a weekday name) +when_time(a clock string, parsed by_parse_clock_time)._resolve_due()then computes the real timestamp off Python's own wall clock. A model that's confused about "today's date" can't produce a wrong reminder time this way. - Not every list supports due dates. HA's
todo.TodoListEntityFeaturebits vary by integration — the built-in "Shopping list" integration, for example, supports create/update/delete but not due dates at all._add_remindercheckssupported_featuresand degrades gracefully (datetime → date-only → no due info, with a spoken caveat) instead of letting the HA service call 400. - Spoken time phrasing:
time_phrase.py(shared with car-parker.md) spells numbers out as words — XTTS reads raw digits wrong ("9:09" → "nine nine" instead of "nine oh nine"). - Narration bypass (
VERBATIM_TOOLSinbrain/tools.py): all five of these tools' results are spoken verbatim, skipping the in-character narration pass entirely. Found live: narration doesn't just reformat these — asked to narrate alist_notesresult, it once ignored the tool content outright and spoke an unrelated stock line instead. Narration also reliably reformats spelled-out times back into digits. Both are the same hallucination/fact-dropping class already documented for car-parker.md's power responses — this is the same fix applied at the tool-result layer instead of bypassing the LLM call entirely (it can't be, here — the note/reminder text itself needs the LLM's NLU). complete_itemnever deletes — only marks statuscompleted, so a misheard match is never destructive. Matching is a plain substring check against the resolved list's items.
Status & known limits
- Pull-only. Nothing proactively announces a due reminder — ask, or wait and check. Same unwired-notification problem as timers.md's expiry case, deferred for the same reason.
complete_item's substring match can miss a paraphrased reference (e.g. "I did the dry cleaning thing" won't match an item literally reading "pick up dry cleaning"). Known, not yet fixed._resolve_list's "is this just the default list?" detection is a regex/heuristic, not a hard guarantee — observed the model fillinglist_namewith paraphrases of its own schema description ("user's personal list") instead of omitting the field; the regex catches known shapes of that but isn't exhaustive.