$ cd ../projects

~/projects/executive-assistant/README.md

LIVEPRIVATE# AI Automation

Executive Assistant & Second Brain

Two halves of one personal operating system. The Executive Assistant is a Telegram bot backed by n8n, Claude and a pgvector memory: a weekday morning brief, scheduled nudges, voice notes turned into tasks, and questions answered from my own history. MangJoseOS is the long-term memory, an Obsidian vault run by Claude Code with an evidence layer, a synthesized wiki, and skills that turn repeated work into one-command procedures.

n8nClaude CodeTelegram Bot APIPostgreSQL + pgvectorOllamafaster-whisperObsidianDocker
n8n workflows
12
bot unit tests
77
weekday brief
07:30
custom Claude Code skills
10+

cat architecture.flow

System Architecture

architecture.flow

Morning brief

Cron 07:30
Traffic · weather · news · mail · staff
Prompt builder (byte-capped)
Claude → JSON
Telegram + task buttons

Capture

Telegram voice / text
Whisper (local)
Claude classify
TALA task / diary note
pgvector memory

Second brain

raw/ (evidence)
Ingest skill
wiki/ (synthesis)
index + log
Vault-first answers

cat problem.md

Business Problem

Every morning started with the same manual triage: check the commute and flood conditions, scan two mailboxes, review open tasks, check what my staff were waiting on, and skim the news. Deadlines buried in email were easy to miss.

Ideas and to-dos captured by voice or chat had nowhere reliable to land, and nothing remembered what had happened last week, so the same questions got re-answered from scratch.

AI coding sessions have the same problem at a larger scale. Each session starts with no memory of past decisions, incidents or procedures, so the same lessons get relearned.

cat solution.md

Solution

The Executive Assistant is a set of n8n workflows that fan out to traffic, weather, news, mail, calendar and my task system on a schedule. Claude writes the brief as structured JSON that becomes a Telegram message with one-tap "add as task" buttons. Afternoon nudges and a Monday finance report follow the same pattern.

Voice notes are transcribed by a local Whisper service with a mixed English and Tagalog vocabulary. Claude classifies each one as tasks or a note. Tasks go to TALA, and notes go to a diary and a pgvector memory that powers retrieval-based Q&A over my own history.

MangJoseOS is the long-term layer. It is an Obsidian vault with three tiers: immutable raw sources, a synthesized and cross-linked wiki, and PARA folders for live work. Claude Code is instructed to check the vault before answering from general knowledge, and to write back what it learns.

Repeated work becomes Claude Code skills: capturing knowledge into the vault, publishing to the blog, adding dated reminders to TALA, building n8n workflows, and ingesting YouTube tutorials. A harvester skill watches for repeated tasks and proposes new skills, which are only created after I approve them.

ls ./components

Architecture Decisions

n8n as the orchestrator

Schedules, the Telegram trigger, mail, calendar and HTTP calls all live in n8n. Each data source retries on its own and degrades to "unavailable" instead of failing the whole brief.

Claude via a restricted key

Claude runs as the CLI on the homelab under my subscription. n8n reaches it over SSH with a forced-command key, so no API key sits on the host and the key can't run arbitrary commands.

Tested logic, inlined into n8n

Brief, nudge, ageing and date logic live in plain JS modules with unit tests. A build script inlines them into n8n Code nodes, and a test checks that the build matches the source.

pgvector memory

Diary entries and notes are embedded locally with Ollama (nomic-embed-text) and stored in PostgreSQL with pgvector, so retrieval Q&A never sends my history to a third-party embedding API.

Read-only business access

The weekly finance report reads the Liquidation Tracker through a dedicated read-only role with explicit column grants. The assistant can report on the business but can't change it.

Vault schema as an instruction set

The vault's CLAUDE.md defines the operations (ingest, query, lint, new client project), page types and logging rules, so every session works the vault the same way.

./run --trace

Weekday Morning Brief

  1. 01

    Fan out

    At 07:30 the workflow fetches live and predicted commute time, weather, news, both mailboxes, staff status from TALA, and the diary, with per-source retries.

  2. 02

    Build the prompt

    Sections that failed are listed as unavailable, and the whole prompt is trimmed to a byte budget.

  3. 03

    Generate

    Claude returns JSON: the brief as escaped Telegram HTML plus up to five suggested tasks.

  4. 04

    Deliver

    The brief is sent to Telegram with one-tap buttons that create the suggested tasks in TALA.

./run --trace 2

YouTube Tutorial → Verified Knowledge

Videos are treated as a source of claims, never a source of truth.

  1. 01

    Fetch transcript

    A skill calls an n8n workflow that runs a locked-down container (yt-dlp, with faster-whisper as a fallback when captions are missing) through a forced-command SSH key.

  2. 02

    Extract

    Concepts, procedures and factual claims are pulled from the timestamped transcript.

  3. 03

    Verify independently

    Each claim is checked against official documentation and recorded in a claim ledger as verified, contradicted or unverified.

  4. 04

    Write back

    Source, concept and entity pages are written with cross-links, and the index and log are updated.

ls ~/.claude/skills

Skills Built Along the Way

Each skill encodes a procedure we did more than once, with its guardrails, so it runs the same way every time.

vault-capture

Records what a session learned or built into the right page type, with cross-links and an index and log entry.

skill-harvester

Notices repeated multi-step work and proposes turning it into a skill. Nothing is created without approval.

youtube-ingest

Transcript → claims → independent verification → provenance-tracked wiki pages.

blog-post

Writes a session up in my voice, generates a feature image and publishes to Ghost. It drafts by default.

tala-reminder

Turns any date that comes up in a session into a dated TALA task through its machine API.

n8n-workflow-builder

Builds, validates, deploys and tests n8n workflows on the homelab instance, with error alerting wired in.

tail -f incidents.log

Engineering Challenges

Briefs failing on one flaky source

Symptom
Outbound calls from containers timed out intermittently, and one failed source could sink the whole brief.
Root cause
Container MTU (1500) was larger than the host uplink (1400), so some responses were silently dropped.
Fix
Fixed the network path, added per-source retries, and made every section degrade to a visible "unavailable" line instead of failing.

Prompt injection through email

Symptom
Email content flows into an LLM prompt whose output becomes clickable Telegram HTML.
Fix
Strict HTML escaping, a hard length cap, and links taken only from news items, never from email bodies.

One bot token, two consumers

Symptom
An unrelated bot went silent for three days, crash-looping with 409 Conflict.
Root cause
A workflow registered a webhook on a token another service was long-polling. Telegram allows only one delivery mode per token.
Fix
Every bot now gets its own token, the assistant uses its own dedicated bot, and "check getWebhookInfo first" is recorded in the vault as a runbook step.

Knowledge that silently goes stale

Symptom
Wiki pages built from tutorials can be wrong, or right only for an old version.
Fix
Every claim carries a verification status and source. Pages that are version-bound or more than six months old are re-checked against official docs before being trusted.

cat package.json | jq .stack

Technology Stack

Assistant

n8nTelegram Bot APIClaude CLINode.jsNode test runner

Memory & AI

PostgreSQL 16pgvectorOllamafaster-whisperclaude-mem

Data sources

GmailGoogle CalendarGoogle TasksTomTomMET Norway

Second brain

ObsidianMarkdown + wikilinksClaude Code skillsyt-dlpDocker

echo $EXIT_STATUS

Project Outcome

outcome.log

My weekday starts with one Telegram message instead of six apps, and anything I say into my phone ends up as a task or a searchable memory within seconds.

The second brain changed how I work with AI. Decisions, incidents and procedures persist across sessions, and repeated work becomes a reviewed, reusable skill instead of a re-explained prompt.