- Deployed Calendar Agent (n8n ID: 4ZIEGck9n4l5qaDt) - 12 Google Calendars via HA proxy, cron 06:30 - GPT-4.1 batch classification -> memory_facts - Telegram daily briefing - DB: added source_ref column + dedup index on memory_facts - DB: created ha_sensor_config table (IoT Agent sensor allowlist) - 9 seed entries (Pixel 10, Pixel Watch, EY HP, Spotify, GPS) - README: full IoT Agent design documentation - Sensor allowlist (regex), LLM-based activity inference - Three-layer data flow, confidence-gated clarification - README: Calendar Agent design + workflow diagram - README: updated infra table, ADR broker, credentials - CHANGELOG: Calendar Agent milestone Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
11 KiB
ALPHA_PROJECT — Changelog
Tutte le modifiche significative al progetto ALPHA_PROJECT sono documentate qui.
[2026-03-20] Calendar Agent — primo workflow Pompeo in produzione
Cosa è stato fatto
Primo agente Pompeo deployato e attivo su n8n: 📅 Pompeo — Calendar Agent [Schedule] (ID 4ZIEGck9n4l5qaDt).
Design
- Sorgente dati: Home Assistant REST API usata come proxy Google Calendar — evita OAuth Google diretto in n8n e funziona per tutti i 25 calendari registrati in HA.
- Calendari tracciati (12): Lavoro, Famiglia, Spazzatura, Pulizie, Formula 1, WEC, Inter, Compleanni, Varie, Festività Italia, Films (Radarr), Serie TV (Sonarr).
- LLM enrichment: GPT-4.1 (via Copilot) classifica ogni evento: category, action_required, do_not_disturb, priority, behavioral_context, pompeo_note.
- Dedup:
memory_facts.source_ref= HA event UID;ON CONFLICT DO NOTHINGsu indice unico parziale. - Telegram briefing: ogni mattina alle 06:30, riepilogo eventi prossimi 7 giorni raggruppati per calendario.
Migrazioni DB applicate
ALTER TABLE memory_facts ADD COLUMN source_ref TEXT— colonna per ID esterno di dedupCREATE UNIQUE INDEX memory_facts_dedup_idx ON memory_facts (user_id, source, source_ref) WHERE source_ref IS NOT NULLCREATE INDEX idx_memory_facts_source_ref ON memory_facts (source_ref) WHERE source_ref IS NOT NULL
Credential n8n create
| ID | Nome | Tipo |
|---|---|---|
u0JCseXGnDG5hS9F |
Home Assistant API | HTTP Header Auth |
mRqzxhSboGscolqI |
Pompeo — PostgreSQL | Postgres (pompeo/martin) |
Flusso workflow
⏰ Schedule (06:30) → 📅 Range → 🔑 Token Copilot
→ 📋 Calendari (12 items) → 📡 HA Fetch (×12) → 🏷️ Estrai + Tag
→ 📝 Prompt (dedup) → 🤖 GPT-4.1 → 📋 Parse
→ 💾 Postgres Upsert (memory_facts) → 📦 Aggrega → 📱 Telegram
[2026-03-21] ADR — Message Broker: nessun broker dedicato
Decisione
Non verrà deployato un message broker dedicato (né NATS JetStream né Redis Streams). Il blackboard pattern viene implementato interamente su PostgreSQL + webhook n8n.
Ragionamento
Al momento della progettazione iniziale, il broker era necessario per disaccoppiare gli agenti dall'Arbiter. Con l'introduzione della tabella agent_messages nel database pompeo, questo obiettivo è già raggiunto:
Agente n8n → INSERT agent_messages (arbiter_decision = NULL)
Arbiter → SELECT WHERE arbiter_decision IS NULL (polling a cron)
→ UPDATE arbiter_decision = 'notify' | 'defer' | 'discard'
Il flusso high-priority (bypass immediato dell'Arbiter) viene gestito con una chiamata diretta al webhook n8n dell'Arbiter da parte dell'agente — zero infrastruttura aggiuntiva.
Alternative valutate
| Opzione | Esito | Motivazione |
|---|---|---|
agent_messages su PostgreSQL |
✅ Adottata | Già deployata, persistente, queryabile, audit log gratuito |
| Redis Streams | ⏸ Rimandato | Già in cluster, valutabile se volume cresce |
| NATS JetStream | ❌ Scartato | Nuovo componente da operare, overkill per il volume attuale (pochi msg/ora) e per il caso d'uso single-household |
Impatto su README.md
La sezione "Message Broker (Blackboard Pattern)" rimane valida concettualmente. Il campo agent e il message schema definiti nel README vengono rispettati nella tabella agent_messages — cambia solo il mezzo di trasporto (Postgres invece di NATS/Redis).
[2026-03-21] PostgreSQL — Database "pompeo" e schema ALPHA_PROJECT
Overview
Creato il database pompeo sul cluster Patroni (namespace persistence) e applicato lo schema iniziale per la memoria strutturata di Pompeo. Seconda milestone della Phase 0 — Infrastructure Bootstrap.
Modifica manifest Patroni
Aggiunto pompeo: martin nella sezione databases di infra/cluster/persistence/patroni/postgres.yaml. Il database è stato creato automaticamente dallo Zalando Operator senza downtime sugli altri database.
Script DDL idempotente disponibile in: alpha/db/postgres.sql
Design decision — Multi-tenancy anche in PostgreSQL
Coerentemente con la scelta adottata per Qdrant, tutte le tabelle includono il campo user_id TEXT NOT NULL DEFAULT 'martin'. I valori 'martin' e 'shared' sono seedati in user_profile come utenti iniziali del sistema.
Aggiungere un nuovo utente in futuro non richiede modifiche allo schema — è sufficiente inserire una riga in user_profile e usare il nuovo user_id negli INSERT.
Design decision — agent_messages come blackboard persistente
La tabella agent_messages implementa il blackboard pattern del message broker: ogni agente n8n inserisce le proprie osservazioni con arbiter_decision = NULL (pending). Il Proactive Arbiter legge i messaggi in coda, decide (notify / defer / discard) e aggiorna arbiter_decision, arbiter_reason e processed_at.
Rispetto a usare solo NATS/Redis come broker, questo approccio garantisce un audit log permanente di tutte le osservazioni e decisioni, interrogabile via SQL per debug, tuning e analisi storiche.
Schema creato
5 tabelle nel database pompeo:
| Tabella | Ruolo |
|---|---|
user_profile |
Preferenze statiche per utente (lingua, timezone, stile notifiche, quiet hours). Seed: martin, shared |
memory_facts |
Fatti episodici prodotti da tutti gli agenti, con TTL (expires_at) e riferimento al punto Qdrant (qdrant_id) |
finance_documents |
Documenti finanziari strutturati: bollette, fatture, cedolini. Include raw_text per embedding |
behavioral_context |
Contesto IoT/comportamentale per l'Arbiter: DND, home presence, tipo evento |
agent_messages |
Blackboard del message broker — osservazioni agenti + decisioni Arbiter |
15 index totali:
| Index | Tabella | Tipo |
|---|---|---|
idx_memory_facts_user_source_cat |
memory_facts |
(user_id, source, category) |
idx_memory_facts_expires |
memory_facts |
(expires_at) WHERE NOT NULL |
idx_memory_facts_action |
memory_facts |
(user_id, action_required) WHERE true |
idx_finance_docs_user_date |
finance_documents |
(user_id, doc_date DESC) |
idx_finance_docs_correspondent |
finance_documents |
(user_id, correspondent) |
idx_behavioral_ctx_user_time |
behavioral_context |
(user_id, start_at, end_at) |
idx_behavioral_ctx_dnd |
behavioral_context |
(user_id, do_not_disturb) WHERE true |
idx_agent_msgs_pending |
agent_messages |
(user_id, priority, created_at) WHERE pending |
idx_agent_msgs_agent_type |
agent_messages |
(agent, event_type, created_at) |
idx_agent_msgs_expires |
agent_messages |
(expires_at) WHERE pending AND NOT NULL |
Phase 0 — Stato aggiornato
Deploy Qdrant sul cluster✅ 2026-03-21Collections Qdrant con multi-tenancy✅ 2026-03-21user_idPayload indexes Qdrant✅ 2026-03-21Database✅ 2026-03-21pompeo+ schema PostgreSQL- Verify embedding endpoint via Copilot (
text-embedding-3-small) - Migrazione a Ollama
nomic-embed-text(quando LLM server è online)
[2026-03-21] Qdrant — Deploy e setup collections (Phase 0)
Overview
Completato il deploy di Qdrant v1.17.0 sul cluster Kubernetes (namespace persistence) e la creazione delle collections per la memoria semantica di Pompeo. Questa è la prima milestone della Phase 0 — Infrastructure Bootstrap.
Deploy infrastruttura
Qdrant deployato via Helm chart ufficiale (qdrant/qdrant) nel namespace persistence, coerente con il pattern infrastrutturale esistente (Longhorn storage, Sealed Secrets, ServiceMonitor Prometheus).
Risorse create:
| Risorsa | Dettaglio |
|---|---|
StatefulSet qdrant |
1/1 pod Running, image qdrant/qdrant:v1.17.0 |
PVC qdrant-storage-qdrant-0 |
20Gi Longhorn RWO |
Service qdrant |
ClusterIP — porte 6333 (REST), 6334 (gRPC), 6335 (p2p) |
SealedSecret qdrant-api-secret |
API key cifrata, namespace persistence |
ServiceMonitor qdrant |
Prometheus scraping su :6333/metrics, label release: monitoring |
Endpoint interno: qdrant.persistence.svc.cluster.local:6333
Manifest in: infra/cluster/persistence/qdrant/
Design decision — Multi-tenancy collections (Opzione B)
Problema affrontato: nominare le collections martin_episodes, martin_knowledge, martin_preferences avrebbe vincolato Pompeo ad essere esclusivamente un assistente personale singolo, rendendo impossibile — senza migration — estendere il sistema ad altri membri della famiglia in futuro.
Scelta adottata: architettura multi-tenant con 3 collection condivise e isolamento via campo user_id nel payload di ogni punto vettoriale.
episodes ← user_id: "martin" | "shared" | <futuri utenti>
knowledge ← user_id: "martin" | "shared" | <futuri utenti>
preferences ← user_id: "martin" | "shared" | <futuri utenti>
Il valore "shared" è riservato a dati della casa/famiglia visibili a tutti gli utenti (es. calendario condiviso, documenti di casa, finanze comuni). Le query n8n usano un filtro should: [user_id=martin, user_id=shared] per recuperare sia il contesto personale che quello condiviso.
Vantaggi: aggiungere un nuovo utente domani non richiede alcuna modifica infrastrutturale — solo includere il nuovo user_id negli upsert e nelle query.
Collections create
Tutte e 3 le collections sono operative (status green):
| Collection | Contenuto |
|---|---|
episodes |
Fatti episodici con timestamp (email, IoT, calendario, conversazioni) |
knowledge |
Documenti, note Outline, newsletter, knowledge base |
preferences |
Preferenze, abitudini e pattern comportamentali per utente |
Payload schema comune (5 index su ogni collection):
| Campo | Tipo | Scopo |
|---|---|---|
user_id |
keyword | Filtro multi-tenant ("martin", "shared") |
source |
keyword | Origine del dato ("email", "calendar", "iot", "paperless", …) |
category |
keyword | Dominio semantico ("finance", "work", "personal", …) |
date |
datetime | Timestamp del fatto — filtrabile per range |
action_required |
bool | Flag per il Proactive Arbiter |
Dimensione vettori: 1536 (compatibile con text-embedding-3-small via GitHub Copilot — bootstrap phase). Da rivedere alla migrazione verso nomic-embed-text su Ollama.
Phase 0 — Stato al momento del deploy Qdrant
Deploy Qdrant sul clusterCreazione collections con multi-tenancyuser_idPayload indexes:user_id,source,category,date,action_requiredRun PostgreSQL migrations su Patroni✅ completato nella sessione stessa