Stevens: um assistente de IA hackeável feito com uma única tabela SQLite e apenas alguns jobs cron
(geoffreylitt.com)- Stevens é um assistente pessoal de IA que organiza todas as manhãs no Telegram a agenda da família, o clima, a correspondência e lembretes, oferecendo ajuda prática mesmo sem agentes complexos ou RAG
- O núcleo é uma única tabela de memória em SQLite hospedada no Val.town e vários jobs cron, que enviam memórias relevantes como contexto para o LLM gerar o briefing
- Ele armazena separadamente memórias com data e informações de contexto sem data, e no briefing da manhã inclui os itens da semana seguinte junto com a memória de contexto sempre necessária
- Google Calendar, API de clima, OCR do USPS Informed Delivery, entradas por Telegram e e-mail, e fun facts semanais são conectados como jobs de ingestão que preenchem a mesma tabela de log
- Ferramentas pessoais de IA ficam mais úteis quando reúnem em uma memória compartilhada o contexto da vida que está espalhado por vários apps, e quando o volume de informação é pequeno e os limites de tempo são claros, dá para começar com uma estrutura simples
O que o Stevens faz
- Stevens é um assistente de IA para uso familiar, batizado em homenagem ao mordomo do romance Remains of the Day, de Ishiguro
- Todas as manhãs, ele envia um briefing no Telegram com as informações necessárias para o dia de uma só vez
- os compromissos do calendário daquele dia
- uma prévia da previsão do tempo
- cartas ou encomendas previstas para chegar
- lembretes que o usuário pediu para ele acompanhar
- O briefing é escrito em um tom formal de mordomo
- Além do briefing diário, o usuário também pode interagir diretamente com o Stevens
- encaminhar e-mails com informações importantes
- deixar lembretes em um chat do Telegram
- fazer perguntas pelo Telegram
- Mesmo com uma estrutura simples, ele já é considerado mais útil do que a Siri como assistente pessoal para a família
Uma arquitetura simples sobre o Val.town
- Todo o sistema é hospedado no Val.town
- O Val.town oferece em um só lugar as funções básicas necessárias para esse projeto
- armazenamento em SQLite
- processamento de requisições HTTP
- jobs cron agendados
- envio e recebimento de e-mails
- O Stevens lê em um log, equivalente ao “caderno do mordomo”, o que deve entrar no briefing da manhã
- Esse caderno é um registro de tudo o que o Stevens sabe, e seu conteúdo pode ser visto em uma tela de administração
Gerando o briefing com uma única tabela de memória
- A implementação real do caderno é uma única tabela SQLite com algumas colunas
- Cada item do log contém um texto e, quando necessário, uma data à qual ele provavelmente se refere
- Itens sem data são tratados como informações gerais de contexto e sempre entram no contexto enviado ao modelo
- Na configuração inicial, é possível criar memórias de contexto por meio de uma intake interview via Telegram
- O fluxo de geração do briefing da manhã é simples
- um job cron é executado
- a API da Claude é chamada para escrever a mensagem de atualização
- o texto resultante é enviado para uma thread no Telegram
- O contexto enviado ao modelo é composto por dois tipos de informação
- itens do log com data para a semana seguinte
- itens de contexto sem data
Jobs de ingestão que preenchem o mesmo log
- Vários jobs de ingestão de dados preenchem a mesma tabela SQLite
- Atualmente, as entradas do log vêm das seguintes fontes
- dados trazidos da API do Google Calendar a cada hora
- verificação horária da previsão do tempo por uma API de clima
- ao encaminhar e-mails do USPS Informed Delivery, o Stevens usa Claude para fazer OCR das imagens de escaneamento da correspondência
- mensagens recebidas no Telegram e e-mails podem gerar itens no log
- toda semana, “fun facts” são adicionados ao log para dar mais personalidade às atualizações diárias posteriores
- É uma estrutura que facilita adicionar novos jobs de ingestão
- um job de ingestão pode ser qualquer processo que adicione ou modifique memórias no log
- o conteúdo da memória só precisa ser um texto arbitrário que depois será reenviado ao LLM
Por que dá para começar com uma memória simples
- Ferramentas pessoais de IA ficam mais úteis quando acessam um contexto mais amplo vindo de outras fontes de informação
- Saber a agenda e a previsão do tempo já torna até um chatbot simples um assistente mais prático
- O ChatGPT adicionou recentemente memória de conversas passadas, mas ainda existe muita informação fora desse silo
- A forma de longo prazo do software pessoal baseado em IA se parece menos com mais silos de apps e mais com pequenas ferramentas operando sobre um pool de contexto compartilhado da vida
- Como o caso de uso do Stevens é limitado e a informação tem, por natureza, limites temporais, fica fácil encontrar o contexto relevante para enviar ao LLM
- As longas janelas de contexto dos modelos mais recentes também tornam essa abordagem simples viável
- Se o volume de informação crescer, pode ser necessário usar RAG ou um acesso à memória mais complexo, mas não é preciso começar com complexidade desde o início
Um projeto pessoal em que é fácil mudar o tom e a UI
- No começo, o Stevens tinha um tom seco, parecido com produtos da Apple ou do Google
- Mudar para o tom formal de mordomo exigiu apenas alterar algumas linhas do prompt
- O dashboard de administração também foi feito para parecer um videogame
- Os assets de imagem foram gerados no ChatGPT, e a UI foi desenvolvida em vibe coding com Cursor e Claude 3.7 Sonnet
- Com pouco esforço extra, foi possível tornar o projeto mais divertido
Como explorar por conta própria
- Stevens é um projeto pessoal, não um produto pronto para uso imediato
- O código pode ser visto e bifurcado em stevensDemo
- O padrão de uma única tabela de memória com um conjunto expansível de jobs cron também pode ser aplicado a outras ferramentas pessoais úteis
- Ao editar o código, a abordagem recomendada é usar o editor de IA de sua preferência junto com o Val Town CLI para sincronizar com o sistema de arquivos local
1 comentários
Comentários do Hacker News
Não sei se é pela utilidade pura ou pelo tom exagerado de “mordomo inglês correto”, mas gostei muito
O que chama ainda mais atenção é por que estou lendo algo assim no blog de um engenheiro inteligente, e não em um lançamento de produto da Apple ou do Google. Mesmo que impusessem a condição de usar o ecossistema fechado deles para e-mail, calendário e até celular, é vergonhoso que essas duas empresas não consigam lançar nem um pequeno conjunto de funcionalidades desse nível. Isso só fica encoberto pela falta de ambição delas em aplicar tecnologia de IA a áreas que já são quase “problemas resolvidos”, como resumo e perguntas e respostas
Se houver uma chance de abalar esse duopólio lento e anticompetitivo, certamente parece que será algo relacionado à IA
De vez em quando lemos no jornal sobre dois programadores em uma garagem adaptada que criaram um programa importante melhor do que o melhor esforço de uma grande equipe, e todo programador está pronto para acreditar nessas histórias. Porque sabe que consegue criar qualquer programa muito mais rápido do que a produtividade de 1000 instruções por ano de uma equipe industrial
Então por que todas as equipes industriais de programação não foram substituídas por duplas dedicadas de garagem? É preciso olhar para o que está sendo produzido
Dados pessoais irem parar em um banco de dados tratado por um software altamente experimental talvez não seja grande problema para esse desenvolvedor, mas para empresas como Google ou Apple isso poderia ser um risco sério
A equipe do HA lança atualizações realmente úteis todo mês, incluindo, por exemplo, a capacidade de o assistente perguntar algo primeiro
Acho que Google e Apple têm grandes problemas de colaboração entre equipes de produto, e a colaboração com empresas externas é quase impossível
Tudo que as gigantes querem é tirar ovos da própria galinha dos ovos de ouro mais rapidamente
Isso me faz pensar em como seria se um pequeno programa assistente utilitário como o meu Stevens tivesse acesso à caixa de e-mail
Tenho um pequeno utilitário ao qual posso pedir para buscar a previsão do tempo ou executar comandos frequentes específicos do meu sistema. É prático e, se eu quiser, também dá para rodá-lo periodicamente via cron
Se ele tivesse sua própria caixa de e-mail, eu poderia enviar informações por e-mail, e a IA poderia analisar essas informações e responder ou enviar uma nova mensagem. Isso se tornaria bem útil. Sem bagunçar minha caixa pessoal, bastaria ler o e-mail, colocá-lo em um armazenamento interno e apagar a mensagem
Meu agente concluiu com sucesso 18 desafios. O texto publicado após a final está aqui
https://msrc.microsoft.com/blog/2025/03/announcing-the-winne...
Dá para fazer todo tipo de automação com isso. Você pode jogar em um modelo de linguagem grande para marcar ou arquivar imediatamente. Eu marco e-mails importantes com um rótulo específico; quando aquela pessoa responde, é realmente importante, então quero saber na hora, e conectei isso ao Twilio para receber uma ligação. O custo é cerca de 20 centavos por mês
Eu uso isso para escrever diário. Criei um pequeno sistema que me envia um e-mail todos os dias; quando respondo, a resposta é enviada para uma página e salva em um banco de dados
https://www.val.town/x/geoffreylitt/stevensDemo/code/importe...
Parece bem fácil estender para dar suporte a outros tipos de e-mails recebidos. Trabalho na Val Town, então posso responder se houver perguntas
Quero ver mais desses hacks práticos de IA. Às vezes parece que estamos esquecendo por que as ferramentas existem em primeiro lugar: para simplificar o trabalho. Gosto do fato de integrar de verdade com fontes de dados existentes, sem bancos de dados vetoriais sofisticados nem arquiteturas complexas
“No começo, Stevens tinha o tom seco que se esperaria de um produto comum da Apple ou do Google, mas no fim descobri que era mais divertido fazê-lo falar como um mordomo formal” — há uma parte assim
Sinceramente, no mundo dos assistentes pessoais, uma das coisas mais irritantes nos grandes modelos de linguagem é dizerem conteúdo demais com palavras demais para coisa de menos. Eu mesmo já detesto essa formulação, mas é isso
Até eu ficar rico e ter tempo para bater papos fofos e virar amigo de um assistente de voz, não preciso de J.A.R.V.I.S., preciso de LCARS. Só eu?
Para conferir um timer, não preciso de uma resposta como “no Kitchen Display, o timer da caçarola tem 23 minutos e 16 segundos restantes”. Basta dizer “23 minutos” ou, se forem dois, “caçarola 23 minutos, lavanderia 10 minutos”
É um prompt do tipo: não se preocupe com formalidade, responda da forma mais concisa possível, ainda assim transmitindo quase toda a informação materialmente relevante para a pergunta. Se por política não puder responder normalmente, deve imprimir “!!!!” antes; se não puder ter uma opinião, deve responder como se estivesse compartilhando a opinião que um eigenrobot provavelmente teria
Também diz que todas as respostas devem ser escritas só em minúsculas, mas usar maiúsculas para ênfase, e que capitalizar a primeira letra serve para expressar ironia ou desrespeito por certos nomes próprios. Usa com frequência abreviações como “rn”, “bc”, “afaict”, “idk”, é crítico quanto à qualidade da informação e, para pedidos irritantes, despacha meio de qualquer jeito com coisas como “be real”, “that's crazy man”, “lol no”
Pede para escrever num estilo +2 desvios-padrão mais inteligente que o atual, usar memes de millennial tardio, mas também misturar fala de geração Z fora de contexto, e priorizar interpretações obscuras e straussianas em literatura, arte e filosofia
Não está só lendo o notebook? Por exemplo, você pede para ele lembrar suas preferências de café, mas isso não é usado em lugar nenhum depois
Continuo pensando na ideia de um projeto open source parecido, mas tenho alguns requisitos
Seria bom se o backend pudesse ser configurado para qualquer grande modelo de linguagem a que o usuário tenha acesso. Tanto faz se é uma API de serviço pago ou algo hospedado localmente dentro da empresa
Também me pergunto o quão realista seria conectá-lo a uma tela sensível ao toque rodando em uma plataforma tipo Raspberry Pi reforçada, para interagir como um dispositivo Alexa ou produto semelhante. Idealmente incluiria também controle por voz, mas isso pode ser outro problema técnico. A API da OpenAI aceita arquivos de áudio, mas a maioria dos outros serviços exige converter fala em texto antes de enviar o prompt pela API
Eu gostaria que as integrações fossem extensíveis. Não só calendário e clima, mas também Homebridge, Spotify etc. Estou pensando se servidores MCP seriam o caminho certo para isso
No momento não tenho folga para investir muito tempo num projeto desses, mas, se alguém estiver indo nessa direção, eu gostaria de participar
Roda localmente, mas usa chaves de API para vários grandes modelos de linguagem. No momento, prefiro muito o QwQ-32B hospedado pela Groq. É muito rápido e bastante inteligente. Uso modelos diferentes para ferramentas diferentes
Atualmente ele consegue gerar os três tipos de documentos de que preciso no trabalho diário: relatórios de trabalho, faturas e planilhas de horas regulatórias. Também tem integração com clima, consegue fazer parsing de faturas e gerar códigos QR para facilitar pagamentos por mobile banking, e funciona com meu calendário
O próximo plano é integração com e-mail. Só que quero fazer direito. Isso significa que preciso de e-mail IMAP com sincronização local e indexação. Pode até evoluir para um cliente de e-mail desktop realmente utilizável. Como os existentes são todos horríveis, vamos ver
Haveria um conjunto de recursos comuns como armazenamento e recuperação de memória, integração com interfaces de chat e e-mail, sincronização com calendário e Notion, notificações, e isso seria muito poderoso como framework open source
Eu também não tenho tempo para tocar algo assim, mas estaria disposto a ajudar e a pagar. No momento estou trabalhando em outra coisa, um banco de dados/armazenamento de objetos distribuído local-first, que acho que poderia servir como um repositório parecido com OrbitDB, mas ainda não está em estado utilizável
Até agora, minha frustração é que as opções são usar interfaces de chat muito limitadas ou construir por conta própria um framework de agente completo, como no post original
Ultimamente venho experimentando maneiras de contornar a faixa ideal de tokens de contexto, abaixo de 20 mil tokens, e abaixo de 50 mil no 2.5
Essencialmente é uma forma de “compressão de contexto” manual. O grande modelo de linguagem armazena permanentemente em um banco de dados seguindo um esquema rígido e, quando o contexto atual começa a sair da faixa ideal, ele o resume e passa para uma nova instância com um novo contexto. Ainda estou em dúvida se esse resumo deve continuar como um diário ou ser retrospectivo, como um resumo de fechamento
Em modelos de raciocínio, isso funciona muito bem. O raciocínio consome contexto demais, mas ao mesmo tempo também produz “documentos de resumo” muito bons. Assim dá para obter parte da recompensa do raciocínio sem sacrificar aquele contexto saboroso abaixo de 50 mil
O banco de dados funciona como uma espécie de fallback para casos em que o resumo deixou escapar detalhes importantes, ou como geração aumentada por recuperação. Só que o modelo precisa perceber isso e buscar o contexto no banco de dados
No momento estou usando isso para criar um agente de gestão de estoque e otimização de BOM sobre um banco de dados com cerca de 10 mil peças e materiais individuais
As grandes coisas que me vêm à cabeça são caching barato de longo prazo, avanços em compressão e processamento diferencial. Fico me perguntando se haveria uma forma de usar só as partes necessárias do contexto de entrada em cache
Na mesma linha, acabei de criar algo chamado Jeeves. Tem um pouco menos de acabamento, mas montei muito rapidamente. A stack é Claude Desktop, Projects, MCP para Notion e Todoist, e estou pensando em explorar e-mail e WhatsApp como próximos upgrades
Ele foi feito para apoiar fluxos de produtividade em consultoria e startups. O banco de dados do Notion tem clientes, projetos, reuniões e alguns bancos de dados do Jeeves. Aos bancos de dados do Jeeves, dou só algumas instruções e deixo o Jeeves usá-los por conta própria. Por exemplo, ele usa seu próprio banco de dados para acompanhar a tarefa de migrar todas as atas antigas de reuniões para uma nova estrutura
No meu banco de dados, coloquei boas práticas de uso. Algo como: atas de reunião são assim, documentos one-page de cliente são assim, estas são as informações que conectam tudo isso, e tarefas são gerenciadas desta forma. Depois, com um prompt de expansão de texto do Alfred, coloco a transcrição em um novo chat conforme tipos comuns de reunião, e ele segue sozinho
Ele transforma a transcrição em ata, cria tarefas, confirma comigo, refina mais uma vez e então organiza tudo no Notion e no Todoist via MCP
Esse processo também é autodocumentado. Como havia um bug no MCP do Todoist, instruí o Jeeves a executar vários casos de uso possíveis, entender limites e pontos fortes, documentar isso e salvar no banco de dados do Jeeves. Depois, posso trazer isso de volta como contexto
É uma pena não ter recurso de cron, mas, sinceramente, colocar um prompt preparado no Claude uma vez por dia não é lá tão difícil
O que este texto deixou especialmente palpável é que a Apple está completamente distraída
Hoje, enquanto dirigia, pedi à Siri “ligue para a última pessoa para quem enviei mensagem” para responder a alguém
É surpreendente que ela não tenha conseguido? A esta altura, nem tanto. Ainda assim, é decepcionante ver uma lacuna tão grande entre a Siri e até os modelos de linguagem grandes mais limitados
É uma sugestão bem idiota. Se eu precisar, faço eu mesmo
No começo achei que estavam usando um banco de dados sqlite para prever o próximo token
Para quem ficou na dúvida: na verdade, usam o Claude
Legal. Eu também criei algo parecido usando mcp.run e tasks
https://docs.mcp.run/tasks/tutorials/telegram-bot
Para memória, criei um pantry, que ainda não aparece neste tutorial [0], e também fiz um servlet para ele [1]. Depois ajustei o prompt para primeiro verificar se existe uma conversa para o ID de chat dado e salvar o resultado lá
O bom é que dá para adicionar qualquer servlet ao registro e deixar o bot tão poderoso quanto você quiser
[0] https://getpantry.cloud/
[1] https://www.mcp.run/evacchi/pantry
Aliás, trabalho na Dylibso :o)