Alguém estava diante do próprio quadro kanban no Notez, abriu o chat de IA e digitou cinco palavras: quais são minhas tarefas hoje.
Recebeu uma lista. Era a lista errada.
Nada tinha travado. Nenhum erro apareceu. O assistente buscou, encontrou algumas notas e as apresentou com total confiança — e nenhuma delas era um dos cartões que estavam no quadro, alguns centímetros à esquerda. É o pior tipo de bug num produto de IA, porque tem exatamente a cara de uma resposta.
Três coisas que faltavam ao assistente
Diante de uma resposta errada, a tentação é culpar o prompt: acrescentar uma linha pedindo ao modelo que se esforce mais, publicar e torcer. Comecei por aí e não cheguei a lugar nenhum, porque o problema não era a redação. Faltavam três peças, e nenhum ajuste de prompt cria uma peça que não existe.
Ele não via a tela. A requisição que chegava ao modelo continha a pergunta e mais nada. Nem qual visualização estava aberta, nem qual quadro, nem o filtro de tag que restringia a lista, nem a nota no painel lateral. Uma pessoa sentada ao seu lado pode dar uma olhada no seu monitor. O modelo respondia de olhos fechados, sem ter como avisar isso.
Ele não sabia o que é uma tarefa. O Notez, de propósito, não tem uma entidade de tarefa. Não existe tipo Tarefa, nem campo de prazo, nem coluna de checkbox que o app trate de forma especial. O que existe é um quadro — e os cartões nele são o que as pessoas querem dizer com "minhas tarefas". Ninguém tinha dito isso ao modelo. Perguntado sobre tarefas, ele fez a única coisa que podia: buscou pela palavra tarefa.
Ele não tinha ferramenta para ler um quadro. Foi isso que tornou as outras duas impossíveis de resolver. Mesmo um modelo que soubesse exatamente o que você queria dizer e exatamente para qual quadro você olhava não teria como buscá-lo. Havia uma ferramenta para listar notas e outra para filtrá-las por tag, e um quadro não é nenhuma das duas coisas: é um conjunto de colunas, cada uma com um conjunto ordenado de cartões. Não dá para responder a uma pergunta sobre um quadro com uma função de lista.
Dizer ao modelo onde você está
A correção começa no navegador. Agora cada mensagem leva uma pequena descrição da tela em que foi digitada: o modo de visualização, qual quadro está aberto, se você está na lixeira, o texto de busca e os filtros de tag aplicados, a nota aberta e os cartões selecionados.
Essa descrição entra no prompt como frases simples, que o modelo consegue repetir. Sem embeddings, sem estado oculto, sem deduzir o que você provavelmente quis dizer. Se o assistente sabe que você está num quadro, é porque o quadro contou.
Dois detalhes exigiram mais reflexão do que eu esperava.
O primeiro é que uma nota pode estar aberta sobre uma lista — o Notez abre notas num painel lateral, então a lista de notas atrás dele continua montada e continua descrevendo a própria tela. Os dois componentes querem descrever o contexto, e só um deles é o que você está vendo. O painel ganha, porque está por cima.
O segundo é que as pessoas precisam conseguir ver isso. Embaixo da conversa agora há uma fileira de etiquetas — Visualização de quadro, Esta nota, Selecionadas: 3 — que mostra exatamente o que o assistente vê. Um assistente com contexto invisível é um assistente que você precisa testar na base da tentativa e erro até confiar nele. As etiquetas trocam esse teste por uma leitura.
Uma definição de tarefa, por escrito
O modelo agora carrega uma definição que não tinha:
Não existe uma entidade separada de tarefa ou pendência. Quando o usuário pergunta sobre tarefas, pendências, no que trabalhar ou o que está em andamento, ele se refere aos cartões do quadro que está vendo — ou ao quadro do espaço de trabalho, quando não há nenhum na tela. Colunas cujo nome significa terminado (Concluído, Finalizado, Arquivado e similares) não estão pendentes.
Essa última frase trabalha mais do que todas as outras juntas. Sem ela, "quais são minhas tarefas hoje" devolve tudo o que está no quadro, inclusive a coluna com o que você terminou na semana passada — uma resposta tecnicamente completa e, na prática, inútil.
A mesma definição vai para os clientes MCP. Se o Notez está conectado ao Claude Code ou ao Cursor, o seu assistente lá lê o mesmo texto.
Uma ferramenta que lê um quadro
get_board devolve um quadro com os cartões agrupados por coluna e um total para cada coluna. Ela funciona com o quadro do espaço de trabalho ou com o quadro próprio de qualquer nota. Pergunte "o que está em andamento" e é uma chamada só, não uma busca seguida de cinco leituras de notas.
Também juntei duas ferramentas em uma. filter_notes não existe mais: foi incorporada à list_notes, que agora aceita colunas do quadro, valores de propriedades personalizadas e intervalos de datas de criação ou atualização, além dos filtros que já tinha. Todos os filtros se combinam com AND, então uma pergunta como "notas com a tag trabalho, atualizadas esta semana, fora de Concluído" vira uma única chamada, em vez de um ciclo de buscar e peneirar. E cada nota num resultado agora traz suas tags, sua coluna, seus valores de propriedades e suas datas — o assistente para de abrir uma nota só para ler um campo.
Poucas ferramentas completas ganham de muitas ferramentas magras. Cada ferramenta a mais é mais uma chance de o modelo escolher a errada.
O bug que escrevi enquanto corrigia o bug
Com filtros de data, alguém precisa decidir o que é "hoje", e a resposta honesta é que depende de onde você está. Por isso o navegador envia o fuso horário dele, e o servidor calcula o intervalo nesse fuso.
A primeira versão desse código estava errada de um jeito que seria muito difícil de perceber. A biblioteca que usei para montar uma data com fuso mantém o offset ao serializar — e as colunas de data e hora das notas são timestamp without time zone, ou seja, o Postgres descartaria esse offset sem avisar e deslocaria cada intervalo pelo número de horas que separam você do UTC. Todo usuário fora do UTC receberia respostas um pouco erradas para "o que eu criei hoje", sem nada em lugar nenhum acusando falha.
O teste ficou vermelho antes de ficar verde, e é o único motivo de eu confiar nele. Depois conferi de novo num banco de dados real: uma nota criada às 22:00 UTC — uma da manhã no horário local — ainda conta como hoje, exatamente como deveria.
Os clientes MCP recebem UTC, porque do outro lado não há navegador a quem perguntar. Essa limitação está escrita na descrição da ferramenta, em vez de escondida, então o assistente que a lê sabe o que está recebendo.
Duas interfaces, um conjunto de ferramentas
O Notez tem dois caminhos para um assistente chegar às suas notas: o chat dentro do app e o servidor MCP ao qual o seu editor se conecta. Os dois compartilham 29 ferramentas, e o servidor MCP tem mais três só dele: duas para envio de arquivos, que precisam de um shell, e uma que lista seus espaços de trabalho nas conexões por login. As compartilhadas não são parecidas — são iguais: os mesmos nomes, os mesmos argumentos, os mesmos campos obrigatórios, garantidos por um teste que quebra o build se as duas listas se afastarem.
Esse teste existe porque elas já se afastaram uma vez. Seis ferramentas ficaram só no chat durante meses, e ninguém percebeu, porque nada as comparava. Paridade que depende de alguém lembrar é paridade que se perde.
O que ele responde agora
As mesmas cinco palavras, no mesmo quadro:
A fazer: Corrigir bug do login, Escrever notas de versão Em andamento: Revisar PR 42
Deixei de fora
Concluído, porque essa já foi concluída: Planejar o roadmap do 4º trimestre.
Uma chamada de ferramenta. A lista certa. E uma frase explicando o que ficou de fora de propósito — o que, para um assistente que passou meses respondendo à pergunta errada com toda a confiança, talvez seja a parte mais importante.
Continue lendo
Como o chat de IA do Notez trabalha com suas anotações — as 29 ferramentas que o chat de IA usa no seu espaço de trabalho, o que ele não faz e os limites de cada plano.
Instruções do chat de IA: as da equipe e as suas — instruções fixas para um espaço de trabalho inteiro e só para você, e por que as do proprietário ficam por último no prompt.
Como funciona a busca semântica nas anotações — como os embeddings encontram a nota que diz "memoizar" quando você busca "cache", e onde a busca por palavra-chave ainda ganha.