Stevens: un asistente de IA hackeable creado solo con una tabla SQLite y tareas cron
(geoffreylitt.com)- Stevens es un asistente personal de IA que cada mañana resume por Telegram la agenda, el clima, el correo postal y los recordatorios de la familia, y ofrece ayuda práctica sin agentes complejos ni RAG
- La clave es una única tabla SQLite de memoria sobre Val.town y varias tareas cron, que pasan recuerdos relevantes como contexto al LLM para generar el briefing
- Guarda por separado recuerdos con fecha e información de contexto sin fecha; el briefing matutino incluye los elementos de la próxima semana junto con la memoria de contexto siempre necesaria
- Google Calendar, una API del clima, OCR de USPS Informed Delivery, entradas por Telegram y correo electrónico, y fun facts semanales se conectan como tareas de importación que llenan la misma tabla de logs
- Las herramientas personales de IA se vuelven más útiles cuando reúnen en una memoria compartida el contexto de vida disperso entre apps; si el volumen de información es pequeño y los límites temporales son claros, se puede empezar con una estructura simple
Qué hace Stevens
- Stevens es un asistente de IA familiar cuyo nombre viene del mayordomo de la novela Remains of the Day de Ishiguro
- Cada mañana entrega en Telegram un briefing con toda la información necesaria para el día
- Los eventos del calendario del día
- Un adelanto del pronóstico del clima
- Correo postal o paquetes esperados
- Recordatorios que el usuario le pidió seguir
- El briefing está escrito con un tono formal de mayordomo
- Además del briefing diario, los usuarios pueden interactuar directamente con Stevens
- Reenviar correos electrónicos con información importante
- Dejar recordatorios por chat de Telegram
- Hacer preguntas en Telegram
- Aunque su estructura es simple, se considera que como asistente personal familiar ya es más útil que Siri
Una estructura simple montada sobre Val.town
- Todo el sistema está alojado en Val.town
- Val.town ofrece en un solo lugar las funciones básicas que este proyecto necesita
- Almacenamiento SQLite
- Manejo de solicitudes HTTP
- Tareas cron programadas
- Correo electrónico entrante y saliente
- Stevens lee el contenido del briefing matutino desde un log que equivale al “cuaderno del mayordomo”
- Ese cuaderno es un registro de todo lo que Stevens sabe, y su contenido puede revisarse desde una pantalla de administración
Crear briefings con una sola tabla de memoria
- La implementación real del cuaderno es una única tabla SQLite con unas pocas columnas
- Cada entrada del log contiene texto y, si corresponde, una fecha con la que se espera que esté relacionada
- Las entradas sin fecha se tratan como información general de contexto y siempre se incluyen en el contexto
- Durante la configuración inicial, se pueden crear recuerdos de contexto mediante una entrevista de ingreso por Telegram
- El flujo de generación del briefing matutino es simple
- Se ejecuta una tarea cron
- Se llama a la API de Claude para redactar el mensaje de actualización
- El texto resultante se envía a un hilo de Telegram
- El contexto que se pasa al modelo se compone de dos tipos de información
- Entradas del log con fecha para la próxima semana
- Entradas de contexto sin fecha
Tareas de importación que llenan el mismo log
- Varias tareas de importación de datos llenan la misma tabla SQLite
- Actualmente, las fuentes de las entradas del log son las siguientes
- Trae datos cada hora desde la API de Google Calendar
- Consulta cada hora el pronóstico del clima local mediante una API del clima
- Si se reenvían correos de USPS Informed Delivery, Stevens usa Claude para hacer OCR de las imágenes escaneadas del correo postal
- Los mensajes entrantes de Telegram y los correos electrónicos pueden crear entradas en el log
- Cada semana se agregan “fun facts” al log para dar más color a las actualizaciones diarias posteriores
- Es una estructura a la que resulta fácil conectar nuevas tareas de importación
- Una tarea de importación puede ser cualquier proceso que agregue o modifique recuerdos del log
- Basta con que el contenido de la memoria sea texto arbitrario que luego se volverá a pasar al LLM
Por qué se puede empezar con una memoria simple
- Las herramientas personales de IA se vuelven útiles cuando acceden a un contexto más amplio traído desde otras fuentes de información
- Si conoce el calendario y el pronóstico del clima, incluso un chatbot simple se convierte en un asistente más práctico
- ChatGPT agregó recientemente memoria de conversaciones pasadas, pero hay mucha información que no está guardada dentro de ese silo
- La forma de largo plazo del software personal basado en IA se parece menos a más silos de apps y más a pequeñas herramientas que funcionan sobre un pool compartido de contexto sobre la vida de una persona
- El caso de uso de Stevens es acotado y la información tiene límites temporales por naturaleza, por lo que es fácil encontrar el contexto relevante para pasarle al LLM
- Las ventanas de contexto largas de los modelos más recientes también hacen posible un enfoque simple
- Si el volumen de información crece, quizá hagan falta RAG u otros enfoques de memoria más complejos, pero no es necesario empezar con complejidad desde el inicio
Un proyecto personal donde es fácil cambiar el tono y la UI
- Al principio, Stevens tenía un tono seco, similar al de productos de Apple o Google
- Cambiarlo a un tono formal de mayordomo solo requirió modificar unas pocas líneas del prompt
- También se hizo que el panel de administración se sintiera como un videojuego
- Los recursos de imagen se generaron con ChatGPT, y la UI se hizo con vibe coding usando Cursor y Claude 3.7 Sonnet
- Con un pequeño esfuerzo adicional, el proyecto pudo hacerse más divertido
Cómo verlo por cuenta propia
- Stevens no es un producto listo para ejecutar, sino un proyecto personal
- El código puede consultarse y forkeare en stevensDemo
- El patrón de una sola tabla de memoria y un conjunto extensible de tareas cron también puede aplicarse a otras herramientas personales útiles
- Para editar el código, se recomienda usar el editor de IA que prefieras y Val Town CLI para sincronizarlo con el sistema de archivos local
1 comentarios
Opiniones de Hacker News
No sé si es por su utilidad pura o por el tono exagerado de “Proper English Butler”, pero me encanta
Lo que más llama la atención es por qué estoy leyendo algo así en el blog de un ingeniero brillante, y no en una presentación de producto de Apple o Google. Aunque pusieran como condición usar su ecosistema cerrado —email, calendario y hasta el teléfono—, es vergonzoso que esas dos empresas no puedan lanzar ni siquiera un pequeño conjunto de funciones como este. Solo queda disimulado porque les falta ambición para aplicar tecnología de IA en áreas que ya están cerca de ser “problemas resueltos”, como los resúmenes y las preguntas y respuestas
Si hay una oportunidad de sacudir este duopolio torpe y anticompetitivo, seguramente tendrá que ver con la IA
De vez en cuando uno lee en el periódico la historia de dos programadores en un garaje adaptado que crean un programa importante, mejor que el mejor esfuerzo de un equipo grande, y todos los programadores están listos para creer esas historias. Porque saben que pueden crear casi cualquier programa mucho más rápido que la productividad industrial de 1000 sentencias al año por equipo
Entonces, ¿por qué no se han reemplazado todos los equipos industriales de programación por dúos dedicados en garajes? Hay que mirar qué se está produciendo
Que datos personales entren en una base de datos manejada por software altamente experimental quizá no sea un gran problema para este desarrollador, pero para empresas como Google o Apple podría ser un riesgo grave
El equipo de HA lanza actualizaciones realmente útiles todos los meses; por ejemplo, incluso existe una función para que el asistente pueda preguntar algo primero
Creo que Google y Apple tienen grandes problemas de colaboración entre equipos de producto, y colaborar con empresas externas es casi imposible
Lo único que intentan hacer las grandes empresas es sacarle huevos más rápido a su propia gallina de los huevos de oro
Me hace pensar qué pasaría si un pequeño programa asistente utilitario como mi Stevens tuviera acceso al buzón de correo
Tengo una pequeña utilidad a la que puedo pedirle que obtenga el clima o que ejecute comandos frecuentes específicos de mi sistema. Es práctica y, si quiero, también puede ejecutarse periódicamente con cron
Si además tuviera su propio buzón, podría enviarle información por email, y la IA podría parsearla y responder o enviar un nuevo mensaje. Eso la volvería bastante útil. Sin arruinar mi buzón personal: bastaría con leer el correo, guardarlo en un almacén interno y borrar el mensaje
Mi agente completó con éxito 18 desafíos. El artículo publicado después de la final está aquí
https://msrc.microsoft.com/blog/2025/03/announcing-the-winne...
Con esto se puede hacer todo tipo de automatización. Puedes pasarlo a un modelo de lenguaje grande para etiquetar o archivar de inmediato. Tengo emails importantes marcados con una etiqueta específica; si esa persona responde, es realmente importante y quiero enterarme al instante, así que lo conecté con Twilio para que me llame. El costo es de unos 20 centavos al mes
Yo lo uso para escribir un diario. Armé un pequeño sistema que me manda un email todos los días, y cuando respondo, la respuesta se envía a una página y se guarda en una base de datos
https://www.val.town/x/geoffreylitt/stevensDemo/code/importe...
Creo que sería bastante fácil ampliarlo para soportar otros tipos de emails entrantes. Trabajo en Val Town, así que puedo responder preguntas si tienen
Me gustaría ver más de este tipo de hacks prácticos con IA. A veces siento que olvidamos por qué existen las herramientas en primer lugar: para simplificar el trabajo. Me gusta que esto se integre de verdad con fuentes de datos existentes, sin bases de datos vectoriales vistosas ni arquitecturas complicadas
“Al principio, Stevens tenía el tono seco que esperarías de un producto común de Apple o Google, pero al final descubrí que era más divertido hacerlo hablar como un mayordomo formal”, dice una parte.
Sinceramente, una de las cosas más irritantes del mundo de los asistentes personales es que los modelos de lenguaje grandes usan demasiadas palabras para decir muy poco. Yo mismo ya odio esta expresión, pero así es.
Hasta que sea rico y tenga tiempo para tener conversaciones simpáticas y hacerme amigo de un asistente de voz, no necesito J.A.R.V.I.S., necesito LCARS. ¿Soy el único?
Para consultar un temporizador no necesito una respuesta como “En Kitchen Display quedan 23 minutos y 16 segundos para el temporizador del casserole”. Basta con “23 minutos”, o si hay dos: “casserole 23 minutos, lavado 10 minutos”.
Es un prompt del estilo: no te preocupes por la formalidad y responde con la mayor brevedad posible, transmitiendo casi toda la información realmente relevante para la pregunta. Si por política no puede responder con normalidad, primero debe imprimir “!!!!”, y si no puede tener una opinión, debe responder como si compartiera la opinión que tendría eigenrobot.
También indica que todas las respuestas se escriban solo en minúsculas, usando mayúsculas para enfatizar, y que la capitalización inicial se use para expresar sarcasmo o falta de respeto hacia ciertos nombres propios. Usa con frecuencia abreviaturas como “rn”, “bc”, “afaict”, “idk”; es crítico con la calidad de la información, y ante solicitudes molestas las despacha con frases como “be real”, “that's crazy man”, “lol no”.
Pide escribir con un estilo +2 desviaciones estándar más inteligente que el actual, usar memes de millennials tardíos pero mezclar también, de forma algo fuera de lugar, jerga de la Gen Z; y en literatura, arte y filosofía priorizar interpretaciones oscuras y straussianas.
¿No está simplemente leyendo la notebook? Por ejemplo, le pides que recuerde tu preferencia de café, pero eso no se usa después en ningún lado.
Llevo tiempo pensando en una idea de proyecto open source parecido, con algunas condiciones.
Me gustaría que el backend pudiera configurarse con cualquier modelo de lenguaje grande al que el usuario tenga acceso. Da igual si es la API de un servicio pago o algo alojado localmente dentro de la empresa.
También me pregunto qué tan realista sería conectarlo a una pantalla táctil que corra sobre una plataforma tipo Raspberry Pi reforzada, para poder interactuar con él como con un dispositivo Alexa o algo similar. Idealmente también incluiría control por voz, aunque eso podría ser otro problema técnico. La API de OpenAI acepta archivos de audio, pero la mayoría de los otros servicios requieren convertir voz a texto antes de enviar el prompt por API.
Quisiera que las integraciones fueran extensibles. No solo calendario y clima, sino también Homebridge, Spotify, etc. Estoy pensando si los servidores MCP son el camino correcto para eso.
Ahora mismo no tengo margen para dedicarle mucho tiempo a un proyecto así, pero si alguien va en esa dirección, me gustaría participar.
Se ejecuta localmente, pero usa claves de API para varios modelos de lenguaje grandes. Ahora prefiero por mucho QwQ-32B alojado en Groq. Es muy rápido y bastante inteligente. Uso modelos distintos para herramientas distintas.
Actualmente puede generar tres tipos de documentos que necesito para el trabajo diario: reportes de trabajo, facturas y horarios para cumplimiento regulatorio. También tiene integración de clima, puede parsear facturas y generar códigos QR para facilitar pagos de banca móvil, y funciona con mi calendario.
Lo siguiente será integrar email. Pero quiero hacerlo bien. Eso significa que necesito correo IMAP con sincronización local e indexación. Incluso podría convertirse en un cliente de email de escritorio realmente usable. Como todos los existentes son horribles, ya veremos.
Si tuviera un conjunto de funciones comunes como almacenamiento y recuperación de memoria, integración de interfaces de chat y email, sincronización de calendario y Notion, notificaciones, etc., y eso se convirtiera en un framework open source, sería muy potente.
Yo tampoco tengo tiempo para operarlo, pero estaría dispuesto a ayudar y a pagar. Ahora estoy trabajando en otra cosa, una base de datos/almacenamiento de objetos distribuido con enfoque local-first, que podría servir como almacenamiento parecido a OrbitDB, aunque todavía no está en estado usable.
Hasta ahora me frustraba que las únicas opciones fueran usar interfaces de chat muy limitadas o construir uno mismo un framework de agentes completo, como en el post original.
Últimamente estoy experimentando con formas de esquivar el rango ideal de tokens de contexto, por debajo de 20 mil tokens, y en 2.5 por debajo de 50 mil tokens.
En esencia, es una forma de hacer “compresión de contexto” manual. El modelo de lenguaje grande almacena datos de forma permanente en una base de datos siguiendo un esquema estricto y, cuando el contexto actual empieza a salir del rango ideal, lo resume y se lo pasa a una nueva instancia con un contexto nuevo. Todavía tengo dudas sobre si mantener ese resumen como una bitácora continua o hacerlo de manera retrospectiva, como un resumen de cierre.
En modelos de razonamiento esto funciona bastante bien. El razonamiento consume muchísimo contexto, pero al mismo tiempo produce muy buenos “documentos de resumen”. Así que se puede obtener parte de la recompensa del razonamiento sin sacrificar ese delicioso contexto por debajo de 50 mil.
La base de datos funciona como una especie de fallback para cuando el resumen omite detalles importantes, o como generación aumentada por recuperación. Eso sí, el modelo tiene que darse cuenta de ello y traer contexto desde la base de datos.
Ahora lo estoy probando para crear un agente de gestión de inventario y optimización de BOM sobre una base de datos de unas 10 mil piezas y materiales individuales.
Los grandes temas que se me ocurren son caché barato de largo plazo, avances en compresión y procesamiento diferencial. Me pregunto si habrá alguna forma de usar solo las partes necesarias del contexto de entrada cacheado.
En una línea similar, acabo de armar algo llamado Jeeves. Tiene un poco menos de adornos, pero lo monté muy rápido. El stack es Claude Desktop, Projects, MCP para Notion y Todoist, y estoy viendo la exploración de email y WhatsApp como próximas mejoras.
Lo hice para apoyar flujos de productividad de consultoría y startups. La base de datos de Notion tiene clientes, proyectos, reuniones y algunas bases de datos de Jeeves. A las bases de datos de Jeeves solo les doy unas pocas instrucciones y dejo que Jeeves las use por su cuenta. Por ejemplo, usa su propia base de datos para dar seguimiento a la tarea de migrar todas las actas de reuniones antiguas a una estructura nueva.
En mi base de datos tengo mejores prácticas de uso. Algo como: así se ven las actas de reunión, así se ve un documento de una página de un cliente, esta es la información que conecta todo esto, y así se gestionan las tareas. Luego, con un prompt de expansión de texto de Alfred, meto en un chat nuevo la transcripción según tipos comunes de reunión y se encarga del resto.
Convierte la transcripción en actas, crea tareas, lo revisa conmigo, lo pule una vez más y luego, mediante MCP, lo deja todo ordenado en Notion y Todoist.
Este proceso también se autodocumenta. Como el MCP de Todoist tiene un bug, le pedí a Jeeves que ejecutara varios casos de uso posibles, identificara límites y fortalezas, los documentara y los guardara en la base de datos de Jeeves. Después puedo volver a cargarlo como contexto.
Es una pena que no tenga funcionalidad de cron, pero honestamente no es tan difícil pegar una vez al día un prompt preparado en Claude.
Lo que este artículo hizo sentir especialmente real es que Apple está completamente desprevenida.
Hoy, mientras manejaba, le dije a Siri “llama a la última persona a la que le mandé un mensaje” para responderle a alguien.
¿Sorprende que no haya podido? A estas alturas, ya ni sorprende mucho. Aun así, decepciona que haya una brecha tan grande entre Siri y hasta los modelos de lenguaje grandes más flojos.
Es una sugerencia bastante tonta. Si lo necesito, lo puedo hacer yo.
Al principio pensé que habían usado una base de datos sqlite para predecir el siguiente token.
Para los demás: en realidad usan Claude.
Genial. Yo también hice algo parecido usando mcp.run y task.
https://docs.mcp.run/tasks/tutorials/telegram-bot
Para memoria, aunque todavía no aparece en este tutorial, hice un pantry [0], y también hice un servlet para eso [1]. Luego modifiqué el prompt para que primero revise si hay una conversación correspondiente al ID de chat dado y guarde ahí el resultado.
Lo bueno es que puedes agregar cualquier servlet al registro y hacer que el bot sea tan potente como quieras.
[0] https://getpantry.cloud/
[1] https://www.mcp.run/evacchi/pantry
Por cierto, trabajo en Dylibso :o)