Someone stood in front of their kanban board in Notez, opened AI chat, and typed five words: what are my tasks today.
They got a list. It was the wrong list.
Nothing had crashed. No error appeared. The assistant searched, found some notes, and reported them with complete confidence — and none of them were the cards sitting on the board a few centimetres to the left. That is the worst kind of bug in an AI product, because it looks exactly like an answer.
Three things the assistant did not have
The temptation with a wrong answer is to blame the prompt: add a line telling the model to try harder, ship it, hope. We started there and got nowhere, because the problem was not the wording. It was three missing pieces, and no amount of prompt tuning creates a piece that is absent.
It could not see the screen. The request that reached the model contained the question and nothing else. Not which view was open, not which board, not the tag filter that was narrowing the list, not the note in the side panel. A person sitting next to you can glance at your monitor. The model was answering with its eyes closed and no way to say so.
It did not know what a task is. Notez deliberately has no to-do entity. There is no Task type, no due-date field, no checkbox column that the app treats as special. What there is, is a board — and the cards on it are what people mean when they say "my tasks". The model had never been told that. Asked about tasks, it did the only thing it could: keyword-searched for the word task.
It had no tool that could read a board. This is the one that made the other two unfixable. Even a model that knew exactly what you meant and exactly which board you were looking at had no way to fetch it. There was a tool to list notes and a tool to filter them by tag, and a board is neither: it is a set of columns, each holding an ordered set of cards. You cannot answer a board question with a list function.
Telling the model where you are
The fix starts in the browser. Every message now carries a small description of the screen it was typed on: the view mode, which board is open, whether you are in the Bin, the search text and tag filters currently applied, the note you have open, and the cards you have selected.
That description is rendered into the prompt as plain sentences the model can quote back. No embeddings, no hidden state, no inference about what you probably meant. If the assistant knows you are on a board, it is because the board told it.
Two details cost more thought than expected.
The first is that a note can be open over a list — Notez opens notes in a side panel, so the dashboard behind it is still mounted and still reporting its own screen. Both components want to describe the context, and only one of them is the one you are looking at. The panel wins, because it is on top.
The second is that people should be able to see this. Under the conversation there is now a row of chips — Board view, This note, 3 selected — that spells out precisely what the assistant can see. An assistant with invisible context is one you have to test by trial and error to trust. Chips turn that into reading.
Defining a task, in writing
The model now carries a definition it did not have:
There is no separate task or to-do entity. When the user asks about tasks, to-dos, what to work on, or what is in progress, they mean the cards on the board they are looking at — or the workspace board when none is on screen. Columns whose name means finished (Done, Completed, Archived and similar) are not pending.
That last sentence does more work than the rest combined. Without it, "what are my tasks today" returns everything on the board including the column of things you finished last week, which is technically a complete answer and practically useless.
The same definition is shipped to MCP clients. If you have Notez connected to Claude Code or Cursor, your assistant there reads the identical text.
A tool that reads a board
get_board returns a board with its cards grouped by column, and a total for each column. Point it at the workspace board or at any note's own board. Ask "what is in progress" and it is one call, not a search followed by five note fetches.
We also merged two tools into one. filter_notes is gone, folded into list_notes, which now takes board columns, custom property values, and created or updated date ranges alongside the filters it already had. Every filter ANDs with the others, so a question like "notes tagged work, updated this week, not in Done" is a single call instead of a fetch-and-sift loop. And every note in a result now carries its tags, its column, its property values, and its dates — the assistant stops opening a note just to read one field.
Fewer, richer tools beat more, thinner ones. Each extra tool is another chance for the model to pick the wrong one.
The bug we wrote while fixing the bug
Date filters mean somebody has to decide what "today" means, and the honest answer is that it depends where you are sitting. So the browser sends its timezone, and the server resolves the range in it.
The first version of that code was wrong in a way that would have been very hard to notice. The library we used to build a zone-aware date keeps its offset when serialised — and the note timestamp columns are timestamp without time zone, which means Postgres would have quietly dropped that offset and shifted every range by however many hours you happen to live from UTC. Every user outside UTC would have got slightly wrong answers to "what did I create today", with nothing anywhere reporting a fault.
The test for it went red before it went green, which is the only reason we believe it. Then it was checked again against a real database: a note created at 22:00 UTC — one in the morning, local time — still counts as today, exactly as it should.
MCP clients get UTC, because there is no browser out there to ask. That limitation is written into the tool description rather than hidden, so the assistant reading it knows what it is getting.
Two front ends, one toolset
Notez has two ways to reach your notes with an assistant: the chat inside the app, and the MCP server your own editor connects to. They share 29 tools, and the MCP server adds three of its own: two for file uploads, which need a shell, and one that lists your workspaces for sign-in connections. The shared ones aren't similar — they have the same names, the same arguments, the same required fields, enforced by a test that fails the build if the two lists drift apart.
That test exists because they did drift once. Six tools sat in chat alone for months, and nobody noticed, because nothing was comparing them. Parity you have to remember is parity you will lose.
What it answers now
The same five words, on the same board:
To Do: Fix login bug, Write release notes In Progress: Review PR 42
I left out
Done, because that one is finished: Plan Q4 roadmap.
One tool call. The right list. And a sentence explaining what it deliberately left out — which, for an assistant that spent months confidently answering the wrong question, might be the most important part.
Continue reading
Your notes, answerable: how AI chat works in Notez — the 29 tools AI chat runs on your workspace, what it can't do, and its limits on each plan.
Custom instructions for AI chat: one set for the team, one for you — standing instructions for a whole workspace and for yourself, and why the owner's go last in the prompt.
Semantic Search for Notes, Explained — how embeddings find the note that says "memoize" when you search for "caching", and where keyword search still wins.