Skip to main content
Glama

Alfred

Alfred es un secretario personal de código abierto y local que se ejecuta en tu PC. Recuerda lo que le cuentas, mantiene un grafo de memoria temporal tipado con procedencia respaldada por evidencia, te informa desde Calendar, Gmail, Canvas y GitHub, y actúa en tu nombre—creando eventos, redactando y enviando correos, registrando incidencias—solo después de que lo revises y apruebes. SQLite es dueño de la memoria, las tareas, los horarios, el registro de auditoría y los conectores. Telegram, Slack, Claude, Cursor, ChatGPT y la CLI son interfaces reemplazables, no la fuente de la verdad.

Las credenciales permanecen en el almacén de credenciales del sistema operativo. Los tokens nunca llegan a la base de datos, al registro de auditoría, a la bóveda de Markdown ni a Git. Las escrituras son primero vista previa, luego confirmación. Los modelos son opcionales y están fuera de la ruta predeterminada.

Lo que obtienes

  • Un archivo SQLite local con un registro de auditoría de solo añadidura y copia de seguridad cifrada

  • Memoria temporal tipada (buscar, corregir, olvidar) y una bóveda bidireccional de Obsidian

  • Sincronización de solo lectura de Calendar / Gmail / Canvas / GitHub / Health que alimenta un resumen matutino

  • Escrituras con aprobación: eventos de Calendar, borradores y envíos de Gmail, incidencias de GitHub

  • Telegram (y Slack opcional) como control remoto desde el teléfono; Claude, Cursor y ChatGPT mediante MCP con políticas

  • alfred run o un servicio de Windows que mantiene el bucle activo

Consulta ARCHITECTURE.md para conocer las decisiones detrás de esto. Los comandos y la configuración están a continuación.

Configuración local

python -m venv .venv
.\.venv\Scripts\python -m pip install -e .[dev]
.\.venv\Scripts\alfred init
.\.venv\Scripts\alfred status

O ejecuta esos cuatro pasos con .\scripts\install.ps1. Es seguro volver a ejecutarlo: omite la creación del entorno virtual cuando ya existe, nunca lee ni solicita una credencial de proveedor, y cada paso de mutación respeta -WhatIf. Añade -RegisterScheduledTask para registrar también la entrada en el Programador de tareas en "Ejecución continua"; Get-Help .\scripts\install.ps1 -Full lista cada parámetro.

La base de datos predeterminada es .alfred/alfred.db, que Git ignora. Usa otra ruta con --db <ruta> o ALFRED_DB_PATH.

Las horas de silencio opcionales retienen las entregas proactivas de Telegram/Slack (recordatorios, resúmenes matutinos, avisos—cualquier cosa con un job_id de salida) dentro de una ventana local. Establece ALFRED_QUIET_HOURS_START y ALFRED_QUIET_HOURS_END en HH:MM (ventanas nocturnas como 22:0007:00 son válidas) y opcionalmente ALFRED_QUIET_HOURS_TIMEZONE con un nombre IANA (por defecto UTC). Las respuestas interactivas sin job_id siguen entregándose. Si no se establece, las horas de silencio están desactivadas.

Related MCP server: razberri MCP Server

Conectores locales

Almacena cada token bajo el servicio de administrador de credenciales del sistema operativo alfred. Alfred nunca escribe credenciales en su base de datos, registro de auditoría, bóveda ni Git.

Escrituras con aprobación (eventos de Calendar, borradores y envíos de Gmail, incidencias de GitHub, olvido de memoria, restauración de copia de seguridad) son siempre tres pasos:

  1. *-propose — vista previa local; nunca toca al proveedor.

  2. alfred approval-approve --approval-id <ID> --actor nico — imprime un token de un solo uso.

  3. *-execute --approval-id <ID> --actor nico --token <TOKEN> — consume ese token.

Reintentar con el mismo ID de aprobación y token reproduce el recibo almacenado en lugar de duplicarlo. Si la PC falla después de que el proveedor acepta pero antes de que Alfred registre el recibo, el mismo comando se recupera mediante un ID de proveedor estable y falla de forma segura si el resultado está ausente o es ambiguo. No hay ninguna herramienta MCP para aprobar: un humano (o un canal local de confianza fuera del cliente MCP, p. ej. alfred approval-approve) debe concederlo.

Conector

Credencial (cuenta)

Lectura

Escritura

Telegram

telegram-bot-token

chats emparejados

respuestas, recordatorios, avisos

Slack

slack-app-token, slack-bot-token

Socket Mode, solo emparejados

igual

Google Calendar

OAuth mediante google-auth

calendarios seleccionados

creación de eventos con aprobación

Gmail

la misma concesión OAuth

cabeceras/avances no leídos

borrador y envío con aprobación

Canvas API

canvas-api-token

tareas

Canvas iCal

alfred canvas-ical-setup

tareas con fecha

GitHub

github-token / github-issue-token

notificaciones no leídas

incidencias con aprobación

Google Health

scopes OAuth adicionales

sueño, actividad, métricas

Composio

alfred composio-setup

aplicaciones de desbordamiento (Notion, Spotify, …)

escrituras con aprobación

Slack está construido y probado unitariamente contra fixtures sintéticos, pero no ha sido ejercitado contra una aplicación real de Slack. El cliente de Google Health ahora coincide con las formas publicadas de v4 (filtros tipados, cargas anidadas, name vacío en puntos no identificables, tamaño de página de sueño 25); aún conserva el punto completo sin procesar en metadata["raw"] y todavía necesita un dispositivo portátil vinculado (concesión google-auth --include-health) antes de tratar el conector como verificado.

alfred connector-status (o MCP connector_status) informa ok, stale (sin éxito en 24 horas), error o never_synced sin exponer una credencial ni contenido sincronizado.

alfred connector-capabilities responde qué puede hacer cada conector: quién puede escribir, qué scopes OAuth se solicitan realmente, qué datos sensibles almacena, y si es por sondeo, push o local. Hoy seis pueden escribir (Calendar, Gmail, GitHub, Telegram, Slack, Composio) y exactamente uno almacena datos sensibles (Google Health, los tres scopes de solo lectura). "Puede escribir" marca el límite de aprobación—nada de eso se ejecuta sin supervisión. La misma tabla está en el panel de administración y se verifica contra el código fuente mediante pruebas.

Telegram y Slack

Coloca el token del bot en telegram-bot-token, luego ejecuta alfred telegram-poll con IDs de chat/usuario explícitamente emparejados. Solo esos pares entran en Alfred.

Slack permanece local mediante Socket Mode—sin webhook público ni túnel. deploy/slack-app/manifest.yml es una aplicación de Slack lista para pegar; deploy/slack-app/README.md cubre cómo generar tokens, almacenarlos como slack-app-token/slack-bot-token, invitar al bot y encontrar los IDs. Luego añade --slack-pair CHANNEL_ID:USER_ID --slack-channel-id CHANNEL_ID a alfred run. Solo las combinaciones de usuario/canal explícitamente emparejadas entran en Alfred; las respuestas, los recordatorios y los avisos solo pueden ir a canales explícitamente permitidos.

OAuth de Google (Calendar, Gmail, Health)

Calendar y Gmail comparten un mismo flujo OAuth 2.0. En Google Cloud Console, crea un cliente OAuth de tipo "Aplicación de escritorio" (sin URI de redirección—el flujo local de Alfred está exento) y guarda su ID de cliente y secreto como google-oauth-client-id y google-oauth-client-secret. alfred google-auth abre un navegador, recibe la redirección en un puerto local y almacena un token de refresco como google-oauth-refresh-token. Las sincronizaciones posteriores generan un token de acceso nuevo a partir de ese token de refresco; no se almacena en caché ninguno. Vuelve a ejecutar google-auth si la concesión es revocada.

El ejecutor continuo lee cada evento seleccionado en la interfaz de Google Calendar: título, horario, estado y un enlace de origen—nunca descripciones de eventos ni listas de asistentes. Cada evento también conserva su ID/nombre de calendario y la identidad de solo lectura de Google del creador/organizador cuando está disponible, para que Alfred pueda decir de dónde viene un evento sin copiar la lista de invitados. Eso requiere el scope estrecho calendar.calendarlist.readonly además del acceso a eventos. Una sincronización única alfred calendar-sync aún puede apuntar a un calendario explícitamente.

Escrituras en Calendar: alfred calendar-event-propose --actor nico --summary "..." --start <ISO-8601> --end <ISO-8601>, luego aprueba, y después alfred calendar-event-execute. La recuperación usa el ID estable de evento de Calendar de Alfred.

Gmail reutiliza la misma concesión. alfred gmail-sync copia de cada mensaje no leído el asunto, el remitente y el fragmento corto de Gmail—nunca el cuerpo ni los adjuntos. Leer o archivar un mensaje lo elimina de la siguiente sincronización. La sincronización está limitada a los mensajes no leídos más recientes según --limit (500 por defecto, en el orden del más nuevo al más antiguo de Gmail) en lugar de todo el backlog. Un mensaje puede desaparecer porque fue leído/archivado o porque quedó fuera de esa ventana—ambos se ven igual en connector-status.

Los borradores y el envío de Gmail son escrituras separadas con aprobación: gmail-draft-propose / gmail-draft-execute crea un borrador y nunca llama a un endpoint de envío. Para enviar, usa gmail-send-propose con el mismo destinatario, asunto y cuerpo, aprueba por separado, y luego gmail-send-execute. Alfred nunca envía desde una sincronización, un trabajo programado o una propuesta por sí sola. La recuperación usa un Message-ID estable y solo acepta una coincidencia exacta.

Alfred también puede recibir comandos desde tu bandeja de entrada. alfred gmail-inbound-poll --sender tu@ejemplo.com convierte un asunto de Task: <título> en una tarea local, o Remind: <hora ISO-8601> <título> en una tarea con esa fecha de vencimiento. Solo se actúa sobre el correo de un --sender explícitamente listado; el correo ordinario se deja intacto. Un comando reconocido de un remitente que no está listado es rechazado y auditado (la misma regla de denegación predeterminada que usa el emparejamiento de Telegram). Añade --destination telegram:123 para entregar también los recordatorios Remind: allí. Alfred nunca responde por correo desde esta ruta. Pasa --gmail-inbound-sender (y opcionalmente --gmail-inbound-destination) a alfred run para sondear continuamente.

Google Health reutiliza la misma concesión pero necesita scopes adicionales que Calendar/Gmail no solicitan por defecto. Habilita la API de Google Health en el proyecto de Cloud, añade los tres scopes googlehealth.*.readonly en la página de Acceso a datos de OAuth, y luego:

alfred google-auth --include-health

Eso mantiene todos los valores predeterminados de Calendar/Gmail (incluido calendar.calendarlist.readonly) y añade sueño, actividad y signos vitales de solo lectura. Health nunca está implícito en un google-auth simple. Google Health rechaza los tokens de acceso que también llevan scopes de Calendar/Gmail, por lo que alfred health-sync renueva un subconjunto de esa concesión solo para health. La cuenta de Google también debe estar vinculada a Fitbit (Google Health devuelve ACCOUNT_NOT_LINKED hasta que lo esté). Copia los últimos 14 días (--lookback-days para cambiarlo) de pasos, sesiones de sueño y frecuencia cardíaca diaria en reposo como eventos etiquetados sensitive—las métricas de salud nunca heredan el alcance de recuperación predeterminado de personal. El BPM a nivel de muestra no se almacena; es demasiado denso para el registro de eventos. Las escrituras de Health permanecen deshabilitadas.

Canvas

Si tu escuela permite un token personal de Canvas, guárdalo como canvas-api-token y ejecuta alfred canvas-sync --base-url https://tu-escuela.instructure.com. Copia las tareas próximas/atrasadas más el historial accesible de tareas de cursos actuales/completados: título, fecha límite, etiqueta del curso, enlace de origen y estado compacto de workflow de entrega. Las calificaciones, los contenidos de las entregas, los archivos y el texto del cuerpo de las tareas quedan fuera.

Si la escuela deshabilita los tokens de API personales, usa el Feed de Calendario privado de Canvas. Trata esa URL como una contraseña e introdúcela en el Administrador de credenciales de Windows; nunca la pongas en Git, en un argumento de comando, en un registro ni en un chat:

.\.venv\Scripts\alfred.exe canvas-ical-setup

El comando de configuración avisa cuando está listo para la URL, oculta el texto pegado, repara un doble pegado accidental exacto, valida el feed antes de reemplazar la credencial guardada y realiza la primera sincronización. Con --canvas-ical, alfred run revisa el feed cada 15 minutos, usa solicitudes condicionales ETag/Last-Modified, y almacena solo el título de la tarea, la fecha límite, la etiqueta del curso cuando esté presente, un enlace de origen sin consultas, el estado y evidencia versionada. Nunca almacena la URL del feed ni la descripción del evento.

Si el mismo elemento llega también a través de una suscripción de Google Calendar, las coincidencias exactas de título y hora se muestran una sola vez en los resúmenes y en la memoria académica, con preferencia por la evidencia nativa de Canvas. La exportación iCal de Canvas es menos completa que la API: omite el estado de Tareas pendientes/entregas y Canvas la limita a 30 días hacia atrás, 366 días hacia adelante y 1000 elementos. Elimina después la misma suscripción de Canvas de Google Calendar si no quieres la evidencia bruta de calendario redundante; ya no es necesaria para evitar entradas duplicadas en los resúmenes o en la memoria.

GitHub

El endpoint de notificaciones de GitHub necesita un token de acceso personal clásico con el ámbito notifications; guárdalo como github-token y ejecuta alfred github-sync. Solo copia el título, el repositorio, el motivo (mención, revisión solicitada, etc.), el tipo de asunto y un enlace profundo del navegador de cada notificación no leída; nunca el texto del cuerpo de issues/PR ni los comentarios. Las notificaciones resueltas o leídas desaparecen automáticamente en la siguiente sincronización.

La creación de issues es un ámbito de escritura independiente. Un token de grano fino necesita Issues: write solo en el repositorio que elijas; guárdalo como github-issue-token. alfred github-issue-propose --actor nico --repository owner/repo --title "..." crea una vista previa local; tras aprobarla, github-issue-execute crea ese issue exacto una sola vez. Nunca crea issues durante la sincronización ni sin un token de aprobación reciente. Cada issue creado incluye un marcador de recuperación invisible de Alfred para que un fallo entre la aceptación de GitHub y el almacenamiento del recibo por parte de Alfred pueda seguir encontrando ese issue exacto. Los comentarios de PR usan el mismo proceso de recuperación.

Composio (aplicaciones adicionales)

Úsalo para aplicaciones que Alfred no posee ya — Notion, Spotify, Linear, Discord y el resto del catálogo de Composio. Gmail, Calendar, GitHub, Slack, Telegram y Fitbit siguen siendo de primera parte.

  1. Crea un proyecto gratuito en dashboard.composio.dev (sin tarjeta; los nuevos registros tienen un tope máximo de 100 000 llamadas de herramientas al mes).

  2. Copia una clave de API desde Ajustes y ejecuta alfred composio-setup.

  3. alfred composio-connect notion imprime un enlace de conexión; ábrelo, inicia sesión y luego ejecuta alfred composio-search "list pages" --toolkit notion.

  4. Concede a Hermes las cuatro herramientas (composio_search, composio_status, composio_connect, composio_execute) en la client-grant existente.

Las lecturas se ejecutan de inmediato. Las escrituras siguen mostrando una vista previa y esperan al botón de aprobación de Telegram. No añadas la URL MCP alojada de Composio a Hermes: cada turno de Telegram se ejecuta a ciegas, por lo que esa ruta aprobaría automáticamente escrituras de terceros.

alfred composio-status muestra las cuentas conectadas y el recuento local de llamadas de este mes UTC con respecto al límite del plan gratuito.

Resumen matutino

Programa un resumen matutino local diario para un chat de Telegram vinculado con, por ejemplo, alfred schedule-brief --chat-id 123 --at 07:30 --timezone America/New_York.

Copia de seguridad y restauración cifradas

Crea la clave AES-256 local una vez con alfred backup-key-generate; se guarda solo en el Administrador de credenciales de Windows como backup-encryption-key. Después, alfred backup-create --output D:\Backups\alfred.backup escribe una instantánea SQLite cifrada. La restauración consta de dos pasos: backup-restore-propose --backup ... --actor nico, aprueba la vista previa y luego backup-restore-execute. El SHA-256 de la copia de seguridad queda fijado en la aprobación, por lo que no se puede restaurar un archivo modificado con una confirmación obsoleta. La restauración no es reproducible: cualquier restauración adicional necesita una vista previa y una aprobación nuevas.

scripts/backup.ps1 crea instantáneas cifradas con marca de tiempo en .alfred/backups. La instalación desplegada lo ejecuta mediante la tarea programada Alfred Backup a diario a las 02:30.

Prueba esas instantáneas con alfred backup-verify --latest-in .alfred\backups (o --backup <archivo>). Ensaya una restauración completa en una copia desechable y nunca toca tu base de datos real. La única otra forma de probar una restauración es backup-restore-execute, que sobrescribe la base de datos que intentas proteger.

Comprueba que la clave almacenada sigue descifrando, que la integridad de SQLite es correcta, que las migraciones se aplican, que la cadena de hash de auditoría se verifica y que los datos están realmente ahí:

{"ok": true, "schema_version": 15, "audit_chain_verified": true,
 "row_counts": {"events": 3402, "tool_runs": 5369, "memories": 2592}}

Una copia de seguridad que se descifre en una base de datos vacía superaría todas las comprobaciones excepto la última. Las copias de seguridad dañadas se notifican en lugar de lanzarse como excepción, por lo que es seguro programarlo, y el comando sale con código distinto de cero en caso de error.

scripts/verify-backup.ps1 es el envoltorio programado. La instalación desplegada lo ejecuta como Alfred Backup Verify cada cuatro semanas a las 03:15, 45 minutos después de la instantánea nocturna. Cada ejecución añade una línea JSON a .alfred\backup-verify.log, y un error lanza una excepción para que el Programador de tareas registre una ejecución fallida. Regístralo con:

$ps = (Get-Command powershell.exe).Source
$action = New-ScheduledTaskAction -Execute $ps `
  -Argument '-NoProfile -ExecutionPolicy Bypass -File "C:\path\to\alfred\scripts\verify-backup.ps1"'
$trigger = New-ScheduledTaskTrigger -Weekly -WeeksInterval 4 -DaysOfWeek Sunday -At 3:15AM
Register-ScheduledTask -TaskName "Alfred Backup Verify" -Action $action -Trigger $trigger -Force

Tareas y recordatorios

Enviar /task <título> o /remind <ISO-8601> <texto> al bot de Telegram vinculado crea una tarea (y, para /remind, un trabajo de entrega programado) vinculada a ese mensaje como evidencia. Los mismos comandos existen en la CLI:

  • alfred task-upsert "título" [--task-id ID] [--due-at ISO-8601] — crea, o actualiza el título/la fecha de vencimiento cuando se proporciona --task-id. Omitir --due-at en una actualización deja la fecha de vencimiento existente intacta en lugar de borrarla.

  • alfred task-complete --task-id ID — idempotente; completar una tarea ya completada no hace nada.

  • alfred reminder-set "texto" --run-at ISO-8601 --chat-id ID [--task-id ID] — programa un recordatorio de Telegram y crea su propia tarea si no se proporciona --task-id. Los canales nuevos usan --destination canal:destinatario (por ejemplo, slack:D123); el trabajo duradero y la bandeja de salida conservan ese destino en lugar de enrutarlo silenciosamente a Telegram. Los trabajadores de entrega solo existen para Telegram por ahora.

Los tres son también herramientas MCP (task_upsert, task_complete, reminder_set). reminder_set necesita un chat_id explícito porque Telegram es hoy el único canal de entrega de Alfred.

Ejecución continua

Cada comando anterior es una invocación CLI única. alfred run es el proceso siempre activo: cada ciclo gestiona la recepción/entrega de Telegram y los trabajos pendientes (recordatorios, el resumen matutino), y cada conector configurado se sincroniza en su propio intervalo (15 minutos por defecto). Una credencial que falta o un conector con errores se registra en el registro de auditoría y se omite; nunca detiene el bucle ni a ningún otro conector.

.\.venv\Scripts\alfred run --pair 123:456 --chat-id 123 --canvas-ical

alfred run limita Gmail a los 50 mensajes no leídos más recientes (--gmail-unread-limit), menos que los 500 de gmail-sync de una sola vez. Cada sincronización bloquea este bucle de un solo subproceso; en una cuenta real, 500 se midieron en 45 segundos frente a 7 para 50, lo que supone un tiempo muerto en el que ni siquiera se consulta un mensaje entrante de Telegram. Súbelo si prefieres una ventana más amplia a la capacidad de respuesta.

La sincronización de Calendar, GitHub y Gmail siempre se intenta y se omite a sí misma si su credencial aún no está configurada. La sincronización de la API de Canvas necesita --canvas-base-url, la sincronización nativa de Canvas Calendar Feed necesita --canvas-ical, los comandos entrantes de Gmail necesitan al menos un --gmail-inbound-sender y Google Health necesita --google-health. Omite --pair/--chat-id para ejecutarlo con Telegram deshabilitado. Detenlo con Ctrl+C.

alfred run también funciona como un proceso en primer plano mantenido activo por el Programador de tareas de Windows ("Al iniciar sesión", ejecutando pythonw.exe con este mismo comando) o una terminal abierta. .\scripts\install.ps1 -RegisterScheduledTask -RunArgs "--pair 123:456 --chat-id 123" registra esa entrada; inspecciónala con Get-ScheduledTask -TaskName Alfred y elimínala con Unregister-ScheduledTask -TaskName Alfred. En cualquier caso, Alfred solo se ejecuta mientras hay una sesión de usuario iniciada.

Respuestas conversacionales (--hermes-profile)

De forma predeterminada, un mensaje de Telegram que no sea /task ni /remind recibe un breve recibo de ayuda. Añade --hermes-profile alfred y pasará al agente: Hermes lo entiende, llama a las herramientas MCP de Alfred y responde en el mismo chat.

.\.venv\Scripts\alfred run --pair 123:456 --chat-id 123 --hermes-profile alfred

Instala hermes-profile/ y registra primero su conexión MCP (consulta hermes-profile/README.md). Alfred es el propietario del transporte de Telegram; Hermes es un subproceso único (hermes -p <perfil> -z <mensaje>) y nunca toca Telegram en sí: la pasarela de Telegram del propio Hermes no funciona actualmente en esta plataforma. La producción permanece en ese ejecutor único, acotado y con datos redactados: Hermes ACP/serve fija la superficie de herramientas al inicio de la sesión, mientras que Alfred reduce las herramientas MCP por turno, y una sesión ACP nueva sin herramientas superó los 30 segundos antes de que se ejecutara un prompt.

  • Los turnos de trabajo reciben primero un acuse de recibo con palabras clave (checking your agenda..., drafting email to you@example.com...); los turnos informales lo omiten. Los acuses de recibo no son llamadas de modelo: se producen dentro de la transacción de escritura de entrada, y el turno del agente tiene que esperar a que esa transacción se cierre.

  • El typing... de Telegram es de mejor esfuerzo y nunca bloquea la respuesta duradera.

  • Las respuestas llegan como mensajes consecutivos de dos a cuatro (SOUL.md pide párrafos cortos; el puente envía cada uno como mensaje propio).

  • Las preguntas de la bandeja de entrada/GitHub obtienen un paquete de contexto acotado de los registros locales ya sincronizados antes de que Hermes comience. Promociones, Social y Foros se cuentan pero se omiten de forma predeterminada. El contexto de Gmail sigue siendo solo de cabeceras/fragmentos. El contenido de los mensajes sincronizados sigue siendo un dato no fiable.

  • Los turnos de trabajo incluyen dos intercambios completados recientes para que sí, márcalo conserve su referente. Los turnos informales usan hasta ocho intercambios de la última semana, poolside/laguna-xs-2.1:free con el razonamiento deshabilitado, memoria solo FTS y una superficie de herramientas MCP vacía (sin espera de incrustación de Ollama en los saludos). Las preguntas respaldadas por herramientas y de memoria explícita mantienen la recuperación vectorial híbrida y stepfun/step-3.7-flash:free. Sobrescribe el modelo informal con --hermes-conversation-model.

  • Cada turno de Hermes permite de forma independiente un máximo de ocho herramientas MCP. alfred-mcp registra solo esa lista; una lectura de bandeja de entrada/GitHub ya incluida en el paquete no expone herramientas. Esto no reduce Claude, Cursor, HTTP ni otros clientes MCP.

  • --hermes-command (por defecto hermes; ruta completa cuando PATH difiere en el servicio de Windows), --hermes-timeout (por defecto 120 s; el tiempo de espera agotado/el código distinto de cero/el vacío siguen recibiendo una respuesta honesta, nunca se reintenta), --hermes-python para invocar -m hermes_cli.main en lugar del lanzador de consola, --embedding-model nomic-embed-text para la recuperación híbrida, --hermes-monthly-call-limit (límite máximo, 1000 por defecto). En Windows, los procesos secundarios usan CREATE_NO_WINDOW.

  • El contexto del puente se acota antes del lanzamiento; la PII común se redacta en el límite del subproceso. El perfil incluido usa el nivel gratuito de Nous con respaldo local de Ollama; sin respaldo de proveedor de pago.

alfred latency-status --limit 20 informa de los tiempos p50/p95 sin contenido (acuse de recibo, ensamblaje del contexto, llamada a Hermes, respuesta lista, primera respuesta entregada). Las muestras contienen solo un ID de actualización, el recuento de ejecuciones/herramientas, el resultado y los tiempos. Las marcas de tiempo de Telegram tienen una resolución de un segundo, por lo que debes tratar los totales de extremo a extremo como orientados al operador, no como un microbenchmark.

Para las preguntas de la bandeja de entrada/GitHub, el puente ensambla un paquete de contexto acotado a partir de los registros locales ya sincronizados antes de iniciar Hermes. Eso evita un segundo bucle de descubrimiento/llamada a herramientas MCP en la ruta en frío. Las categorías de Gmail Promociones, Social y Foros se cuentan pero se omiten del paquete de forma predeterminada, y se incluyen dos intercambios de chat completados recientemente para los turnos de trabajo, de modo que un seguimiento preciso como sí, márcalo conserve su referente. Los turnos informales usan hasta ocho intercambios completados de la última semana, poolside/laguna-xs-2.1:free con el razonamiento deshabilitado, recuperación de memoria FTS local exacta y una superficie de herramientas MCP de Alfred vacía. Omitir la búsqueda vectorial opcional evita esperar una incrustación de Ollama en los saludos; las preguntas respaldadas por herramientas y de memoria explícita mantienen la recuperación vectorial híbrida y el valor predeterminado más potente del perfil, stepfun/step-3.7-flash:free. Sobrescribe el modelo informal con --hermes-conversation-model. El contenido de los mensajes sincronizados sigue siendo un dato no fiable, y el contexto de Gmail sigue siendo solo de cabeceras/fragmentos, nunca el cuerpo completo de un mensaje.

El puente también reduce la superficie MCP de Alfred de forma independiente en cada turno de Hermes. Un clasificador determinista utiliza la solicitud actual más los dos intercambios recientes para seleccionar como máximo ocho herramientas de tarea, calendario, comunicación, memoria o estado. alfred-mcp registra solo esa lista de permitidos en el proceso hijo; una bandeja de entrada/GitHub ya satisfecha por el paquete de contexto no expone herramientas. Esto es defensa en profundidad sobre las comprobaciones de política por cliente existentes y no reduce Claude, Cursor, HTTP u otros clientes MCP.

alfred latency-status --limit 20 informa tiempos p50/p95 sin contenido para el acuse de recibo de Telegram, el ensamblado de contexto local, la llamada a Hermes, el punto de respuesta lista y la primera respuesta entregada. Las muestras recientes contienen solo un ID de actualización, recuento de runtime/herramientas, resultado y tiempos; el contenido de mensajes y conectores nunca entra en el informe. La marca de tiempo de origen de Telegram tiene resolución de un segundo, por lo que los totales de acuse y entrega deben tratarse mejor como mediciones de extremo a extremo orientadas al operador que como un microbenchmark.

alfred evaluation-status --window-days 30 cierra la otra mitad de ese bucle. Alfred ya registraba comentarios de respuesta, resultados de recuperación de memoria, decisiones de propuesta de flujo de trabajo y promoción de candidatos implícitos; esto los lee como un resumen en lugar de dejar cuatro tablas que nadie consulta. También informa qué fuentes de contexto estaban presentes cuando se registró cada voto de comentario — un punto de partida para "por qué esa respuesta era incorrecta", no una prueba de causa, ya que un turno agrupa varias fuentes a la vez. El mismo resumen es una página en la interfaz de administración. Nada aquí ejecuta un modelo, escribe una fila o cambia la clasificación, y la salida no tiene contenido (resultados, recuentos, nombres de fuentes, IDs de registros opacos), por lo que es seguro pegarla en un issue. Una métrica sin votos aún informa null en lugar de 0 — un sistema que nadie ha calificado no es un sistema que obtuvo cero.

Hermes ACP y serve se evaluaron como formas de eliminar el inicio de proceso de un solo disparo. ACP pasa su comprobación de compatibilidad, pero su superficie de herramientas es fija cuando se crea una sesión, mientras que Alfred reduce las herramientas MCP en cada turno. Crear una sesión nueva sin herramientas preservaba ese límite pero superó los 30 segundos en dos pruebas acotadas antes de que siquiera se ejecutara un prompt, porque Hermes construye un agente nuevo por sesión. Reutilizar una sesión sería más rápido solo reteniendo una transcripción oculta sin límite y una superficie de herramientas fija. Por lo tanto, la producción permanece en el ejecutor de un solo disparo acotado y redactado hasta que el upstream exponga una anulación de herramientas por prompt o sesiones aisladas baratas; los fallos y tiempos de espera continúan produciendo una respuesta honesta sin reintentar.

Aprendizaje persistente

Cuando las respuestas conversacionales están habilitadas, Alfred también ejecuta un pase de aprendizaje local después de que la respuesta ya se haya entregado. Las declaraciones explícitas remember that ... se convierten en recuerdos confirmados inmediatamente. Las preferencias ordinarias, los hechos de identidad y los objetivos entran como candidatos en cuarentena y necesitan el mismo hecho en un evento de origen separado antes de la promoción. Los candidatos sensibles nunca se auto-promueven, los secretos reconocibles no se almacenan, y cada observación mantiene su procedencia inmutable de evento de origen.

Los recuerdos confirmados relevantes para una solicitud se colocan directamente en el paquete de contexto acotado del puente, evitando otro viaje de ida y vuelta de herramientas del agente. Los recuerdos candidatos, superados, rechazados, eliminados, sensibles y secretos se excluyen de esa ruta automática. memory_correct preserva la versión anterior mientras instala una corrección; memory_feedback registra recuperaciones relevantes, irrelevantes o incorrectas como datos de evaluación de solo anexión. Ese comentario ahora reordena solo los recuerdos ya seleccionados para una consulta coincidente; no puede inyectar un recuerdo popular no relacionado en el conjunto de candidatos.

Alfred califica sus propias respuestas en lugar de pedirte que lo hagas. Cada respuesta exitosa solía terminar con botones de helpful, missing context y wrong context; calificar a un secretario después de cada respuesta es trabajo, así que quedaron mayormente sin pulsar, y la corrección ya estaba en el chat de todos modos. Dos detectores ahora producen los mismos tres veredictos. El primero lee tu siguiente mensaje en busca de una reacción inequívoca — "te perdiste el de sam", "esa es la semana equivocada", "gracias, perfecto" — usando reglas nombradas en lugar de una llamada a un modelo, para que pueda leerse y discutirse, y permanece en silencio ante cualquier cosa que no reconozca claramente. El segundo es algo que no podrías notar en absoluto: cuando una respuesta se construyó a partir de un conector que nunca se sincronizó o se sincronizó por última vez hace un día, la respuesta ya carecía de contexto, y ese turno se marca tal como se almacena.

Cada veredicto registra un rastro sin contenido de nombres de fuentes, frescura de conectores, el nombre de la regla que se activó e IDs de registros clasificados opacos; ni el prompt ni la respuesta se almacenan. Las señales de útil e incorrecto pueden reordenar registros de Gmail o GitHub solo dentro de su nivel de prioridad determinista existente, mientras que missing context sigue siendo una señal de evaluación en lugar de adivinar qué faltaba. Una respuesta contiene un veredicto por detector y aún cuenta una vez en la clasificación, los veredictos inferidos se atribuyen solo al turno reciente del propio remitente emparejado, y nada de esto puede aprobar o ejecutar una acción. Los botones ahora están reservados exactamente para eso: aprobar o cancelar una escritura.

alfred evaluation-status y la interfaz de administración dicen cómo se alcanzó cada veredicto, para que la señal inferida nunca se confunda con algo que dijiste. Las respuestas que Alfred marcó contra sí mismo se cuentan por separado de tus veredictos y se mantienen fuera de la tasa de utilidad — un conector que se queda en silencio es salud del conector, y incluirlo haría que una semana de Gmail obsoleto se leyera como una semana de respuestas que no te gustaron.

El historial de Calendario y Canvas usa una capa académica derivada separada. Los eventos de conector inmutables siguen siendo autoritativos; después de la sincronización del conector, Alfred deduplica las revisiones en resúmenes JSON diarios y perfiles de curso/calendario, clasificando exámenes, cuestionarios, tareas y eventos ordinarios mientras retiene cada ID de evento de origen. Las preguntas académicas recuperan solo unos pocos resúmenes coincidentes (en lugar de escanear el historial bruto), y la reconstrucción se omite cuando la huella digital de la fuente no ha cambiado. Un segundo pase determinista promueve los elementos actuales a recuerdos semánticos vinculados a la fuente, reemplaza las versiones de proveedor cambiadas y conecta las entidades de calendario/curso al grafo del propietario. Este trabajo en segundo plano nunca retrasa una respuesta de chat.

El ejecutor continuo actualiza una ventana de Calendario de tres años semanalmente por defecto sin reemplazar el cursor incremental en vivo de Calendario. Canvas mantiene la lectura pequeña de próximos/faltantes en el intervalo de conector normal y escanea las tareas de cursos activos/completados accesibles solo una vez al día. Usa --calendar-history-days 0 para deshabilitar el historial de Calendario, o ajusta --calendar-history-interval y --canvas-history-interval cuando sea necesario. El mantenimiento de un solo disparo está disponible a través de calendar-history-sync --all-selected --days 1095 y academic-memory-rebuild.

El JSON en los resúmenes es una caché reemplazable, no el archivo canónico. Esto mantiene las exportaciones portátiles mientras preserva ediciones, cancelaciones, procedencia y comportamiento de olvido/corrección en SQLite. Por lo tanto, Cognee no es una fuente de verdad para Alfred hoy: sus ideas de recuperación de grafo/vector son útiles, pero su ingesta respaldada por LLM y su superficie adicional de runtime/base de datos son innecesarias para hechos deterministas de Calendario/Canvas. Puede evaluarse más tarde como un backend de recuperación opcional contra las mismas pruebas de memoria vinculadas a la fuente. alfred evaluation-status --window-days 30 resume comentarios de respuesta, resultados de recuperación de memoria, decisiones de propuesta de flujo de trabajo y promoción de candidatos implícitos—más qué fuentes de contexto estaban presentes cuando se registró cada voto (un punto de partida para "por qué esa respuesta era incorrecta", no prueba de causa). Misma página en la interfaz de administración. Nada aquí ejecuta un modelo, escribe una fila o cambia la clasificación. La salida no tiene contenido (resultados, recuentos, nombres de fuentes, IDs opacos), segura para pegar en un issue. Una métrica sin votos aún informa null, no 0.

El paso del agente se ejecuta entre la ingesta y la entrega, no como un conector. Cuando un transporte de chat está configurado, los conectores periódicos se ejecutan secuencialmente en un trabajador en segundo plano acotado, por lo que un lote largo de Calendario/Gmail/Canvas no puede detener el sondeo de Telegram. El sondeo largo del servidor de Telegram es de diez segundos por defecto; el presupuesto de lectura HTTP es solo dos segundos más largo, y un sondeo fallido se reintenta después de un segundo.

Aprendizaje persistente

Después de que se entrega una respuesta conversacional, Alfred ejecuta un pase de aprendizaje local:

  • remember that ... explícito se convierte en un recuerdo confirmado inmediatamente.

  • Las preferencias, hechos de identidad y objetivos entran como candidatos en cuarentena y necesitan el mismo hecho en un evento de origen separado antes de la promoción.

  • Los candidatos sensibles nunca se auto-promueven; los secretos reconocibles no se almacenan; cada observación mantiene procedencia inmutable de evento de origen.

  • Los recuerdos confirmados relevantes para una solicitud van en el paquete de contexto. Los recuerdos candidatos, superados, rechazados, eliminados, sensibles y secretos no.

  • memory_correct preserva la versión anterior. memory_feedback registra recuperaciones relevantes/irrelevantes/incorrectas como datos de evaluación de solo anexión y reordena solo recuerdos ya seleccionados para una consulta coincidente.

Telegram ya no pone botones de helpful / missing context / wrong context en cada respuesta. response_context todavía se almacena; un pase posterior debería inferir esas etiquetas de la conversación siguiente en lugar de pedir al propietario que las toque. Los votos existentes aún reordenan registros de Gmail o GitHub solo dentro de su nivel de prioridad determinista.

El historial de Calendario y Canvas usa una capa académica derivada. Los eventos de conector inmutables siguen siendo autoritativos. Después de la sincronización, Alfred deduplica las revisiones en resúmenes JSON diarios y perfiles de curso/calendario (exámenes, cuestionarios, tareas, eventos ordinarios), reteniendo cada ID de evento de origen. Las preguntas académicas recuperan unos pocos resúmenes coincidentes en lugar de escanear el historial bruto; la reconstrucción se omite cuando la huella digital de la fuente no cambia. Un segundo pase promueve los elementos actuales a recuerdos semánticos vinculados a la fuente, reemplaza las versiones de proveedor cambiadas y conecta las entidades de calendario/curso al grafo del propietario. Esto nunca retrasa una respuesta de chat.

El ejecutor actualiza una ventana de Calendario de tres años semanalmente por defecto sin reemplazar el cursor incremental en vivo de Calendario. Canvas mantiene próximos/faltantes en el intervalo normal y escanea las tareas de cursos accesibles una vez al día. --calendar-history-days 0 deshabilita el historial de Calendario; --calendar-history-interval y --canvas-history-interval lo ajustan. De un solo disparo: calendar-history-sync --all-selected --days 1095 y academic-memory-rebuild. El JSON de resumen es una caché reemplazable, no el archivo canónico—las ediciones, cancelaciones, procedencia y olvido/corrección permanecen en SQLite. Cognee no es una fuente de verdad; puede evaluarse más tarde como un backend de recuperación opcional contra las mismas pruebas de memoria vinculadas a la fuente.

Como un servicio real de Windows (sobrevive al cierre de sesión/reinicio)

alfred-service empaqueta exactamente el mismo bucle como un servicio de Windows, independiente de cualquier sesión iniciada, usando las opciones de recuperación propias de Windows para reiniciar en caso de fallo. Es un envoltorio delgado, no una ruta de código separada: impulsa la lógica idéntica de construcción/limpieza que usa alfred run, construida a partir de argumentos analizados por el mismo analizador.

# 1. Store the exact 'alfred run' arguments the service will launch.
.\.venv\Scripts\alfred service-configure run --pair 123:456 --chat-id 123

# 2. Install and start the service (requires an Administrator prompt).
.\.venv\Scripts\alfred-service --username ".\<your-windows-username>" --password "<your-windows-password>" install
.\.venv\Scripts\alfred-service start

--username/--password no son opcionales. Cada credencial de conector vive en el Administrador de credenciales protegido por DPAPI de tu cuenta de Windows, que solo la sesión de inicio de sesión de tu propia cuenta puede descifrar. Instalar sin --username (o mediante el valor predeterminado del complemento MMC de Servicios) se ejecuta como LocalSystem: el servicio se instalará y arrancará "correctamente" y luego morirá de inmediato con missing local credential-store secret: .... Las opciones deben preceder al verbo; getopt deja de analizar en el primer argumento que no es una opción, por lo que alfred-service install --username ... ignora silenciosamente las banderas. La contraseña es visible en el historial del shell una vez escrita de esta manera; bórrala después (Clear-History y/o elimina la línea correspondiente de (Get-PSReadLineOption).HistorySavePath), o usa el complemento MMC de Servicios (services.msc → Alfred Personal Secretary → pestaña Iniciar sesión) para configurar la cuenta sin que toque un shell.

alfred-service debug ejecuta la lógica del servicio en tu consola actual en lugar de bajo el SCM, imprimiendo las excepciones directamente en lugar de enrutarlas a través de Get-WinEvent.

Compruébalo con Get-Service Alfred, detenlo con .\.venv\Scripts\alfred-service stop y elimínalo con .\.venv\Scripts\alfred-service remove. Cambiar los argumentos configurados (volver a ejecutar service-configure) requiere un restart para que surta efecto. Opcionalmente, configura el reinicio automático ante un fallo inesperado—los servicios de Windows no reintentan por defecto—con:

sc.exe failure Alfred reset= 86400 actions= restart/60000

alfred-service necesita pywin32, que ya se incluye de forma transitiva con el paquete mcp en Windows; si la importación falla, ejecuta python .\.venv\Scripts\pywin32_postinstall.py -install una vez. Instalar, iniciar, detener y eliminar el servicio son acciones de Administrador que ejecutas tú mismo—Alfred nunca se eleva ni se registra por sí solo.

Reiniciar Alfred desde tu teléfono

Cuando Alfred está en ejecución, Telegram acepta tres comandos de operador desde chats emparejados:

  • /status — ¿está vivo el bucle y cuándo fue su último ciclo?

  • /restart — reinicia ahora

  • /wake — igual que /restart cuando Alfred está caído

Registra el watchdog una vez (PowerShell de Administrador, después de service-configure):

.\scripts\register-watchdog.ps1

Eso crea dos entradas del Programador de tareas:

  • AlfredWatchdog — cada cinco minutos, ejecuta alfred watchdog-check. Si el latido está obsoleto, reinicia el servicio de Windows (o recurre al comando alfred run configurado desde .alfred/service.json) y hace una consulta a Telegram para /wake o /restart.

  • AlfredRestart — reinicio bajo demanda utilizado por /restart y el watchdog, con los privilegios más altos para que tu teléfono no necesite un aviso de Administrador cada vez.

El ejecutor escribe un latido en cada ciclo, por lo que un proceso colgado o muerto se detecta automáticamente en unos minutos incluso si no haces nada. Cuando Alfred está completamente detenido, envía /wake desde Telegram; la siguiente pasada del watchdog lo ve y vuelve a arrancar Alfred.

Grafo de memoria local

alfred remember "statement" almacena una memoria local confirmada; alfred memory-search "query" devuelve anclas FTS más un salto de grafo activo. Las correcciones nunca reescriben el historial: alfred memory-correct --memory-id ID "corrected statement" marca la memoria antigua como superada y crea una nueva que apunta de vuelta a ella.

Eliminar es previsualizar-y-confirmar, porque eliminar datos es confirmación fuerte y nunca sin supervisión. alfred memory-forget-propose --memory-id ID --actor nico [--reason "..."] previsualiza una eliminación de un solo elemento con alcance. Apruébala y luego alfred memory-forget-execute marca la memoria como eliminada, la retira de la búsqueda y registra una entrada de auditoría. Una memoria superada permanece visible como historial hasta que se elimina por separado.

alfred memory-alias --entity-id ID "Alternate Name" añade un nombre alternativo buscable—memory-search lo encuentra por cualquiera de los dos nombres inmediatamente después.

alfred memory-rename --entity-id ID "Real Name" cambia cómo se llama realmente una entidad. Las personas descubiertas desde tu calendario llegan etiquetadas con lo que Google haya proporcionado, que a veces es solo una dirección de correo electrónico; así es como lo arreglas. La etiqueta antigua se conserva como alias, por lo que los [[wiki links]] existentes siguen funcionando—renombrar no es olvidar.

Alfred completa los nombres por su cuenta cuando puede: si la dirección de calendario de alguien también aparece como remitente de Gmail con un nombre para mostrar, la siguiente sincronización de people lo adopta. Gmail solo se lee para nombres, nunca para decidir que alguien existe—tu bandeja de entrada es sobre todo marcas, y un nombre para mostrar allí es marca más que identidad.

Bóveda de Obsidian

alfred vault-export-entity --entity-id ID y alfred vault-export-memory --memory-id ID (ambos aceptan --vault PATH, por defecto alfred-vault) proyectan un registro del grafo en Generated/—Markdown simple y portátil con un alfred_id y managed: true en el frontmatter. Un archivo editado a mano en esa ruta nunca se sobrescribe silenciosamente; se conserva y la proyección se convierte en su lugar en una copia .alfred-conflict-<timestamp>.md para revisión.

Las exportaciones masivas seleccionan un conjunto en lugar de un solo registro:

.\.venv\Scripts\alfred vault-export-source-event --source-event-id ID
.\.venv\Scripts\alfred vault-export-range --since 2026-03-01 --until 2026-04-01
.\.venv\Scripts\alfred vault-export-topic "rowing" --limit 50
.\.venv\Scripts\alfred vault-export-person --entity-id ID

vault-export-person define "sobre una persona" estructuralmente: una memoria es sobre alguien cuando proviene de un evento que organizó, no cuando su nombre aparece en el texto. La coincidencia de texto trataría "comida cerca de la oficina de Robin" como una memoria sobre Robin—tolerable para una exportación, incorrecto para una eliminación, y este selector sirve para ambos. Encuentra el ID de la entidad con alfred memory-search "<name>".

--since/--until filtran por cuándo Alfred registró una memoria, no por cuándo el hecho se hizo realidad. El rango es semiabierto (--since inclusivo, --until exclusivo) para que los meses consecutivos no reclamen ambos una memoria en el límite. Cualquiera de los dos límites puede omitirse para un rango abierto, pero no ambos. El selector de tema ejecuta la misma búsqueda que haría una pregunta. Cada exportación masiva escribe solo memorias confirmadas, public/personal; cualquier cosa omitida se informa por ID en lugar de descartarse silenciosamente. El recibo de una exportación por tema registra que fue una exportación por tema, nunca la consulta que escribiste.

alfred vault-import --vault PATH lee en la otra dirección: cualquier nota creada por el usuario en cualquier parte de la bóveda (no solo en Generated/) se convierte en una memoria confirmada y respaldada por evidencia. Es un escaneo que invocas periódicamente—mediante la CLI, o automáticamente como conector cuando se le da --vault a alfred run—no un vigilante de archivos a nivel de sistema operativo. Alfred nunca escribe de vuelta en un archivo importado; la detección de cambios se rastrea en la base de datos de Alfred mediante hash de contenido, por lo que editar una nota supera su memoria y eliminar una nota del disco no elimina la memoria que produjo—solo forget hace eso. Los archivos que el propio Alfred generó (managed: true) nunca se reimportan como testimonio.

La importación también lee [[wiki links]] (incluyendo [[Note|display]] y [[Note#Heading]]). Cuando un enlace nombra exactamente una entidad que Alfred ya conoce—por etiqueta o alias, sin distinguir mayúsculas—se registra como evidencia de que esa nota concierne a esa entidad. Un nombre desconocido no crea ninguna entidad, un nombre ambiguo se resuelve a nada en lugar de adivinar entre dos entidades "Alex", y no se crea ninguna arista de relación. El resultado informa de linked y unresolved_links.

Sincronización móvil opcional

Alfred no usa Obsidian Sync de pago. deploy/couchdb/ configura el servicio CouchDB autoalojado; lee deploy/couchdb/README.md antes de ejecutarlo. El propio código de Alfred nunca sincroniza la bóveda con un teléfono; un plugin de la comunidad de Obsidian, de código abierto y verificado (Self-hosted LiveSync), lo hace completamente del lado del cliente, replicando solo alfred-vault/, nunca alfred.db, secretos o registros. alfred vault-sync-status --url http://127.0.0.1:5984 confirma que el lado del servidor es accesible.

Servidor MCP

alfred-mcp ejecuta el servidor MCP stdio de Alfred para Claude Desktop/Code, Cursor y otros clientes MCP locales. Cada herramienta es denegada por defecto: un cliente no recibe nada hasta que se le concede explícitamente, p. ej. alfred client-grant --client-id local-mcp --sensitivity public --sensitivity personal --tool memory_search --tool remember --tool forget --tool calendar_event_propose --tool message_draft --tool action_commit --tool brief_get --tool connector_status --allow-write. alfred-mcp --client-id <id> lo ejecuta bajo una identidad diferente (por defecto: local-mcp) para que un segundo cliente stdio—por ejemplo el Secure MCP Tunnel de OpenAI—obtenga su propia concesión con alcance separado.

Herramientas actuales: system_status, agenda_get, memory_search, profile_get, remember, forget, calendar_event_propose, message_draft, action_commit, brief_get, connector_status, task_upsert, task_complete y reminder_set—las 12 herramientas documentadas de la sección 7, más system_status y calendar_event_propose (que action_commit necesita, ya que la sección 7 nunca nombra una herramienta para previsualizar una escritura de calendario). remember/forget además comprueban la sensibilidad de la memoria solicitada contra el propio alcance del cliente, por lo que un cliente con solo public/personal no puede escribir ni borrar una memoria secret ni siquiera con --allow-write.

forget, calendar_event_propose, message_draft y message_send_propose solo previsualizan. action_commit realiza lo que una llamada de herramienta anterior previsualizó, una vez que se le da un token de aprobación nuevo. Deliberadamente no hay ninguna herramienta MCP para aprobar uno. action_commit acuña un token de acceso de Google nuevo por sí mismo al finalizar una escritura de calendario, un borrador de Gmail o un envío de Gmail; no se almacena nada en caché. Los envíos de Gmail siguen siendo acciones explícitas, de aprobación única y controladas, y nunca se ejecutan desde la sincronización o un trabajo programado.

Propuestas de flujos de trabajo repetidos

Cuando Hermes está habilitado, Alfred realiza un escaneo local de flujos de trabajo una vez al día. Busca la misma secuencia exitosa de dos a ocho herramientas al menos tres veces en dos días. Almacena solo metadatos estructurales: nombres de herramientas, nombres de argumentos y etiquetas de enrutamiento en lista blanca, como el tipo de conector. No almacena prompts, cuerpos de correo, títulos de tareas o eventos, personas, direcciones, fechas, identificadores ni valores de argumentos arbitrarios. Los turnos fallidos y los turnos que contienen action_commit no son elegibles.

.\.venv\Scripts\alfred workflow-scan
.\.venv\Scripts\alfred workflow-list --state pending
.\.venv\Scripts\alfred workflow-show --version-id <ID>
.\.venv\Scripts\alfred workflow-accept --version-id <ID>
.\.venv\Scripts\alfred workflow-reject --version-id <ID>

Cada sugerencia es un SKILL.md inerte y versionado más un diff unificado y un registro de revisión con caducidad. Aceptar el diff registra esa decisión, pero esta primera versión no puede activar ni ejecutar una habilidad generada; el aprendizaje sin supervisión puede producir material de revisión pero no puede modificar el perfil de Hermes. Las instantáneas JSON diarias sin procesar de Calendar/Canvas no se usan aquí: sus registros fuente normalizados ya preservan la procedencia y el historial de cambios.

Streamable HTTP (clientes remotos/privados)

alfred-mcp es solo stdio. Para un cliente que no puede lanzar un proceso local—o que debería ejecutarse como una identidad separada de local-mcpalfred mcp-http-run --client-id <id> sirve la misma superficie de herramientas sobre Streamable HTTP en http://127.0.0.1:8000/mcp. El host no es configurable: esto se vincula solo a loopback. <id> necesita su propio client-grant primero, exactamente como un cliente stdio.

Cada solicitud debe llevar Authorization: Bearer <token>, verificado fuera del manejo de solicitudes propio de FastMCP para que un llamador no autenticado ni siquiera pueda abrir una sesión. Genera ese token una vez con alfred mcp-http-token-generate (se niega a sobrescribir uno existente, igual que backup-key-generate); se almacena en el almacén de credenciales del sistema operativo, nunca en un archivo de configuración. Es un único secreto compartido, no OAuth—OAuth 2.1/RFC 9728 está reservado para el acceso remoto público, una empresa separada que esto no intenta. FastMCP también activa automáticamente la protección contra DNS-rebinding (validación de cabeceras Host/Origin) siempre que el host sea loopback, que aquí siempre es el caso.

ChatGPT (Secure MCP Tunnel)

ChatGPT no puede conectarse directamente a un servidor MCP local como hacen Claude Desktop/Cursor por stdio, por lo que el Secure MCP Tunnel de OpenAI es la vía de acceso privado: un retransmisor de solo salida a través del daemon tunnel-client de OpenAI, ejecutado por ti, que Alfred no distribuye ni reimplementa. Consulta deploy/openai-tunnel/README.md para el tutorial: crear un túnel y un permiso de cliente con alcance limitado, y luego apuntar tunnel-client a alfred-mcp --client-id chatgpt-tunnel por stdio (deliberadamente no al transporte Streamable HTTP anterior, para evitar conciliar dos esquemas de autenticación). El que tu plan de ChatGPT admita conectores MCP personalizados o no es un asunto entre tú y OpenAI.

Panel de administración

alfred admin-ui-run sirve un pequeño panel web de solo lectura: la agenda de hoy, las aprobaciones pendientes, la salud de los conectores, las señales de evaluación y el historial de auditoría reciente, en http://127.0.0.1:8200. Una página por tema, sin acciones de escritura (aprobar sigue pasando por alfred approval-approve, nunca por un botón en esta página). Sin fuentes ni iconos de CDN; funciona sin red.

.\.venv\Scripts\alfred admin-ui-token-generate
.\.venv\Scripts\alfred admin-ui-run

Por defecto, solo acepta loopback como mcp-http-run, pero a diferencia de este, --host es una opción real: está pensado para que lo mire una persona, a veces desde el teléfono. 127.0.0.1 no es accesible desde otro dispositivo ni siquiera a través de una VPN; para consultarlo desde tu teléfono, ejecuta alfred admin-ui-run --host <this-PC's-VPN-IP> (una IP de Tailscale, por ejemplo—tailscale ip -4), nunca --host 0.0.0.0 a menos que ya tengas reglas de firewall que restrinjan quién puede llegar al puerto. Funciona en cualquier navegador moderno; el diseño se reorganiza para una pantalla de ancho de teléfono y usa la fuente del sistema (Segoe UI en Windows, San Francisco en Safari/iOS).

La autenticación es el mismo token bearer que mcp-http-run, pero se entrega de otra forma: visitar cualquier página sin él redirige a una pantalla de inicio de sesión; al introducir el token allí se establece una cookie HttpOnly, SameSite=Strict cuyo valor es el token (sin almacén de sesión separado). El acceso mediante scripts/API todavía puede enviar Authorization: Bearer <token> directamente y omitir la cookie.

Búsqueda vectorial local (opcional)

MemoryGraph acepta un embedding_provider opcional. Sin uno, memory-search sigue siendo solo de palabras clave con FTS5. Con uno—por ejemplo alfred.embeddings.OllamaEmbeddingProvider, apuntando a un Ollama local—remember, memory-correct y forget también mantienen un vector versionado por memoria en la tabla embeddings, y memory-search incorpora coincidencias vectoriales cercanas (dentro de un límite de distancia coseno) una vez que se agotan los resultados por palabras clave. Los vectores tienen espacio de nombres por nombre de modelo, de modo que probar un modelo de embedding distinto nunca mezcla espacios incomparables; cambiar de modelo implica volver a generar los embeddings, no migrar datos. Ejecuta memory-embed-backfill --model nomic-embed-text para una reconstrucción de una sola vez, o pasa --embedding-model nomic-embed-text a alfred run para un mantenimiento local continuo.

Inferencia local de modelos (opcional)

alfred.models.OllamaClient es generación de texto local-first: apúntalo a un Ollama en ejecución y llama al endpoint /api/generate sin streaming, devolviendo el texto junto con los recuentos de tokens de prompt y completado propios de Ollama. BriefingService acepta un llm_writer opcional; sin uno, write_brief() es simplemente render()—el texto determinista, sin cambios. Con uno, el modelo solo reescribe la redacción de la salida determinista; cada hecho, fecha y enlace que ve procede de ese texto, nunca del conocimiento propio del modelo, y si el modelo falla o no es accesible, vuelve a la salida determinista en lugar de costarle al usuario su informe. Cada pasada se audita con sus recuentos de tokens. Nada en la CLI, el servidor MCP o el ejecutor de trabajos conecta un escritor en vivo de forma predeterminada.

También se han implementado piezas de nube: alfred.models.OpenAICompatibleClient y AnthropicCompatibleClient usan los formatos de OpenAI chat-completions y de Anthropic Messages API, respectivamente, pero ninguna debe construirse sin envolver: envuelve cualquiera de ellas en GuardedCloudProvider primero, que impone:

  1. Redacción. Redactor depura los patrones comunes de secretos/PII (correos electrónicos, tokens bearer, patrones de claves de OpenAI/GitHub/Slack/AWS, números de la Seguridad Social, series de dígitos similares a tarjetas, números de teléfono) del texto del prompt y del sistema antes de que cualquiera de ellos llegue al proveedor de nube. Es una limpieza de patrones de mejor esfuerzo, no una garantía: mantén el contenido realmente etiquetado como secret fuera de un prompt de nube, en lugar de confiar en que esto lo detecte.

  2. Tope mensual duro, con fallo cerrado. monthly_budget_usd es 0.0 por defecto, por lo que un GuardedCloudProvider no configurado no realiza ninguna llamada al exterior. Cada llamada comprueba el gasto acumulado en lo que va de mes (sumado a partir de sus propios registros de auditoría) antes de llamar; una vez que ese gasto está ya en el tope o por encima, lanza CloudBudgetExceeded. Esto comprueba el tope antes de cada llamada, no un límite máximo por llamada: una sola llamada muy grande puede aun así superar el total.

  3. Seguimiento de costes. Cada llamada, tenga éxito o falle, se audita con el nombre del modelo, los recuentos de tokens de prompt/completado y un coste estimado en USD (a partir de un CloudPricing proporcionado por el operador, ya que este módulo no fija ninguna tabla de precios de proveedor)—nunca el texto sin procesar del prompt ni de la respuesta. Ese historial de auditoría sirve también como el libro de gastos del que lee el requisito 2.

Al igual que con Ollama, nada en la CLI, el servidor MCP o el ejecutor de trabajos construye un proveedor de nube de forma predeterminada: un operador lo incorpora desde su propia configuración cuando lo desea.

Reglas de desarrollo

  • Lee ARCHITECTURE.md antes de cambiar el comportamiento.

  • Mantén la base de datos como fuente de verdad; los transportes no contienen lógica de negocio.

  • No coloques credenciales, datos personales sin procesar ni bases de datos locales en Git.

  • Cada herramienta MCP está controlada por PolicyStore; un cliente no registrado o con un alcance limitado no recibe nada por defecto. Las acciones con efectos importantes en la superficie MCP solo pueden crear vistas previas; una persona debe aprobarlas fuera de ese cliente MCP antes de que action_commit pueda ejecutar la vista previa aprobada exacta.

Consulta CONTRIBUTING.md para el flujo de trabajo completo de configuración local, pruebas y PR; SECURITY.md para informar de una vulnerabilidad de forma privada; y RELEASING.md junto con CHANGELOG.md para saber cómo se lanza y verifica una versión.

Licencia

Apache-2.0. Consulta LICENSE.

A
license - permissive license
-
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
2Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    -
    quality
    C
    maintenance
    A privacy-first, local-first MCP server that provides 15 ADHD/second-brain tools for capturing, prioritizing, and resurfacing tasks with context from calendar, mail, and messages.
    1
  • A
    license
    A
    quality
    B
    maintenance
    A local-first, privacy-first MCP server that passively indexes personal digital activity (screenshots, clipboard, notes, downloads, links) into a local database, enabling LLMs like Claude to access your context without cloud storage.
    4
    MIT
  • A
    license
    -
    quality
    A
    maintenance
    A self-hosted MCP server that provides any LLM with a graph-backed memory layer of your life—tasks, email, finance, contacts, calendar—plus autonomous agent offices that act on your behalf.
    1
    Apache 2.0

View all related MCP servers

Related MCP Connectors

  • Private-by-default, local-first memory/context/task orchestrator for MCP apps and agents.

  • Person-owned, portable AI memory as a remote MCP server, readable and writable by any MCP client.

  • Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ndunl075/alfred-pennyworth'

If you have feedback or need assistance with the MCP directory API, please join our Discord server