Skip to content
Conduit

skill

AgenticWiki

Personal second-brain Telegram bot — voice/text/link → LLM-maintained wiki on GitHub. Karpathy LLM Wiki pattern + Telegram capture.

Enabridge/AgenticWikicommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/Enabridge/AgenticWiki itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 26, 2026

AgenticWiki

ขี้เกียจจด → AI ถามเอง → Wiki โตเอง

Personal second-brain Telegram bot. Voice / text / link → committed as raw on GitHub → Claude compiles to a wiki nightly → Telegram brief in the morning.

Implements Karpathy's LLM Wiki pattern with a full autonomous loop: voice-in via Telegram (or LINE) → morning ingest → research sub-loop → Telegram brief. You touch nothing. The wiki grows while you sleep.

Status — v0.1 production

Working: Telegram bot, voice/text/link dump, Gemini 3.1 STT/TTS, GitHub commits, evening escalation with /eod marker, Cloudflare named tunnel for local dev, Railway auto-deploy on push.

In progress: Cowork morning Routine (manual one-time setup per user), full wiki layer auto-compile on first real production day.


⚠️ Before you copy this for yourself

This is a personal data system. Your instance will hold your raw voice transcripts, late-night thoughts, TODOs, and unfiltered notes. Adopt with care:

  1. Don't fork — clone + push to a fresh private repo. GitHub forks stay linked to upstream; you don't want your private dumps relatable to the public template. Use the "Setup Step 1" pattern below.
  2. Make your repo private. Non-negotiable.
  3. Rotate every secret. Don't paste tokens in commits, PRs, or issues — even on your own private repo.
  4. PRs upstream are welcome — but only for code/doc/feature fixes, never with personal data. See CONTRIBUTING.md.

Visual references

Three illustrated posters render the system at a glance — architecture, daily flow, and setup. Each is brand-locked to Enabridge palette + Newsreader/Inter typography, generated from prompts/ via Nano Banana Pro.

Architecture

Components and where each runs

ComponentRuntimeTalks toWhy
Telegram botRailway (FastAPI)Telegram, GitHub, GeminiReceive messages, transcribe voice, commit raw, Q&A on demand
evening-prompt.ymlGitHub ActionsTelegram, GitHubPing at 21/22/23 BKK with smart escalation
morning RoutineClaude CoworkGitHub, Web06:30 BKK compile + research + brief
LINE Cloudflare Worker (optional)CloudflareLINE, GitHub, GeminiVoice-only LINE ingest path

3rd-party services and what each is for

ServiceUsed forCost
TelegramPrimary user interfaceFree
Google AI Studio (Gemini)STT, TTS, Q&A LLMFree tier 1500 req/day on Flash
GitHubSource of truth — raw/, wiki/, outputs/Free for private repos
RailwayBot hostingFree or $5/mo credit
Claude Cowork (Pro/Max)Scheduled morning Routine$20/mo Pro or $200 Max
Cloudflare (optional)Named tunnel for local devFree

Setup — 30 minutes total

1. Create your private repo (3 min)

Don't fork. Clone the source, then push to a fresh private repo so there's no upstream link to leak personal commits:

gh repo create your-name/AgenticWiki --private
mkdir AgenticWiki && cd AgenticWiki
curl -L https://github.com/Enabridge/AgenticWiki/archive/refs/heads/main.tar.gz \
  | tar xz --strip-components=1
git init -b main
git add .
git commit -m "init: AgenticWiki from upstream"
git remote add origin https://github.com/your-name/AgenticWiki.git
git push -u origin main

2. Create your Telegram bot (5 min)

  1. In Telegram, search @BotFather → /newbot
  2. Choose a display name then a username ending in bot (e.g. yoh_brain_bot)
  3. Copy the token → save as TELEGRAM_BOT_TOKEN (looks like 8706...:AAG...)
  4. Send /start to your new bot in Telegram (so it's allowed to message you back)
  5. Get your chat ID:
    curl "https://api.telegram.org/bot<TOKEN>/getUpdates"
    # find the integer in result[0].message.chat.id
    
    Save as TELEGRAM_OWNER_CHAT_ID. Only this ID will be allowed to use the bot.
  6. Generate a webhook secret:
    openssl rand -hex 16
    
    Save as TELEGRAM_WEBHOOK_SECRET.

3. Get a Gemini API key (1 min)

  1. https://aistudio.google.com → top-right Get API key → Create API key
  2. Save as GEMINI_API_KEY

4. Generate a GitHub PAT (2 min)

  1. https://github.com/settings/personal-access-tokens/new (logged in as the repo owner)
  2. Token name: AgenticWikiBot
  3. Resource owner: your account
  4. Repository access: Only select repositories → tick AgenticWiki
  5. Repository permissions:
    • Contents: Read and write
    • Metadata: Read-only (auto)
  6. Generate → copy → save as GITHUB_TOKEN

5. Deploy to Railway (5 min)

  1. https://railway.com → New Project → Deploy from GitHub repo
  2. Configure GitHub App for your account → select AgenticWiki only → Install
  3. Pick the repo → Deploy. Railway auto-detects Dockerfile + railway.json
  4. Tab Variables → Raw Editor → paste:
    TELEGRAM_BOT_TOKEN=8706...
    TELEGRAM_OWNER_CHAT_ID=...
    TELEGRAM_WEBHOOK_SECRET=...
    GEMINI_API_KEY=AIza...
    GITHUB_TOKEN=github_pat_...
    GITHUB_REPO=your-name/AgenticWiki
    
    That's the 6 required vars. Everything else has sensible defaults in agentic_wiki/config.py (see Reference below).
  5. Wait for build (~2 min) → Settings → Networking → Generate Domain → copy the *.up.railway.app URL
  6. Set the Telegram webhook to your Railway domain:
    curl -X POST "https://api.telegram.org/bot<TOKEN>/setWebhook" \
      -d "url=https://<railway-domain>/webhook/telegram" \
      -d "secret_token=<webhook-secret>" \
      -d "drop_pending_updates=true"
    
    Should return {"ok":true,"description":"Webhook was set"}.
  7. Send /start to your bot in Telegram. You should see the DUMP keyboard.

6. Add GHA secrets for evening prompt (1 min)

The 21/22/23 BKK ping fires from GitHub Actions, separate from the bot:

gh secret set TELEGRAM_BOT_TOKEN -b "<token>" --repo your-name/AgenticWiki
gh secret set TELEGRAM_OWNER_CHAT_ID -b "<id>" --repo your-name/AgenticWiki

Test: https://github.com/your-name/AgenticWiki/actions/workflows/evening-prompt.yml → Run workflow. You should get the 3-question ping in Telegram within 10s.

7. Set up the Claude Cowork morning Routine (5 min)

Requires Claude Pro ($20/mo, 5 daily routines) or Max ($200/mo, 15 daily routines). Cowork = Claude's scheduled-task workspace.

  1. Install Claude's GitHub App on your account first. This is the step the Claude.ai OAuth flow often skips silently — without it, Cowork's repo dropdown will be empty no matter how many times you reconnect. Open:
    https://github.com/apps/claude/installations/new
    
    Choose your account → Only select repositories → tick AgenticWiki → Install. After this, https://github.com/settings/installations should list Claude under Installed GitHub Apps.
  2. https://claude.ai → switch to Cowork → New Routine
  3. Schedule: Daily 06:30 Asia/Bangkok
  4. Connectors:
    • GitHub (write access to your-name/AgenticWiki)
    • Web Search
  5. Secrets / env to inject in the Routine:
    • TELEGRAM_BOT_TOKEN = same value
    • TELEGRAM_OWNER_CHAT_ID = same value
  6. Prompt: copy the block below the --- from routines/00-morning.md. It's ~6 lines — the actual procedure lives in .claude/skills/morning/SKILL.md so you can update it via PR without touching the Routine.
  7. Save → Test run → review the first PR on mobile and merge if it looks right.

8. (optional) Local dev with Cloudflare named tunnel

If you want to run the bot locally for development, see agentic_wiki/README.md. Polling mode is the zero-config default; the named-tunnel script is for webhook parity with prod.

9. (optional) Add a LINE channel

See SETUP.md — the LINE Cloudflare Worker handles voice ingest directly without the Python bot. Useful as a backup channel or if you prefer LINE OA on iOS.


Daily user journey

21:00 BKK    📩 GHA pings Telegram with 3 questions
             "วันนี้ทำอะไรไปบ้าง / อะไรหลุดไป / เรื่องไหนน่าสนใจ"

21:00–       you reply throughout the night — voice, text, links, forwards
late-night   each message → bot → Gemini STT (if voice) → committed to
             raw/sessions/{date}/{HHMM}-{type}.md  +  .ogg for audio
             bot replies with the file path so you know it landed

22:00 BKK    GHA checks: does raw/sessions/{date}/daily-log-{date}.md exist?
             - yes → silent skip
             - no  → softer ping: "ยังไม่เห็น /eod"

23:00 BKK    same check → last-call ping if marker still missing

[when ready] you type:   /eod ดีๆเลยวันนี้, นอนล่ะ
             bot writes raw/sessions/{date}/daily-log-{date}.md with
             a marker, your optional note, and the list of today's items
             → GHA stops escalating tonight

00:00+       no more pings until tomorrow

06:30 BKK    🤖 Claude Cowork Routine fires
             reads yesterday's raw + the daily-log marker (your note seeds
             the recap) → compiles wiki updates, researches flagged links,
             writes outputs/daily/{yesterday}.md, opens PR, sends Telegram brief

             plus on Sunday: outputs/weekly/{YYYY-WW}.md
             plus on month-end: outputs/monthly/{YYYY-MM}.md

morning      📅 you wake up to a Telegram brief on your phone
             review the PR → merge → wiki grows

TODOs + reminders

Every dump message goes through a quick Gemini classifier. If it looks actionable (action verb + maybe a deadline), the bot ALSO writes a markdown file under todos/open/ with frontmatter:

---
created: 2026-04-27T18:30:00+07:00
due_at: 2026-04-28T14:00:00+07:00
tag: HMN          # HMN | ENB | PERS
status: open
source: raw/sessions/2026-04-27/1830-voice.md
confidence: 0.92
summary: "โอนเงิน Supplier A"
pinged_at: null
---

Tags:

  • HMN — Hanuman: factory ops, supplier, machine, packaging, production
  • ENB — Enabridge: client, proposal, OpenBridge, AI agent, deck, business
  • PERS — personal: family, health, errand, hobby, weekend, friends

The bot reply on a recognized TODO looks like:

📥 voice บันทึก
_ทดสอบบันทึก_
raw/sessions/2026-04-27/1830-voice.md

⚡ TODO [HMN] · _โอนเงิน Supplier A_ · 📅 28 Apr 14:00
todos/open/2026-04-27-1830-supplier-a.md

If confidence < TODO_CONFIDENCE_THRESHOLD (default 0.7), only the raw dump is committed — no todo file. Adjust the threshold in your env.

Listing + completing

  • List: just ask via /ask — "วันนี้มีอะไรต้องทำอีก" — the Q&A handler pulls todos/open/* into context automatically (grouped by tag).
  • Done: /done <fuzzy> finds the best matching open TODO by summary text and moves it to todos/done/.
  • Voice/text done: speak/type a completion ("supplier A เสร็จแล้ว", "เพิ่งจ่ายเงิน") and the classifier auto-detects action_type=done, fuzzy-matches an open TODO, and closes it. No /done command needed.
  • Cancel: /cancel_todo <fuzzy> same logic, target is todos/cancelled/. History is preserved — you can mine "what I gave up on" later.

Notes by tag (status logs)

Not every dump is a TODO. "เพิ่งจ่าย supplier A 635k เรียบร้อย", "เครื่องเดินพะโล้มีปัญหา", "ลูกค้าใหม่ 5 ราย" — all worth tracking but not actionable.

The classifier outputs action_type as one of:

  • todo — saves to todos/open/
  • done — auto-closes a matching open TODO; falls back to a note if none
  • note — saves to notes/{HMN|ENB|PERS}/{date}-{HHMM}-{slug}.md
  • none — only the raw dump is saved (no extra)

Notes are pulled into /ask context just like TODOs, so questions like "เดือนนี้ HMN ทำอะไรไปบ้าง" work out of the box.

Links — auto-fetched + summarized

When a dump message is a pure URL, the bot fetches it, asks Gemini to extract {title, summary, body}, and writes the summary into the raw markdown alongside the URL. The Telegram reply previews the title + 3–5-sentence Thai summary. This protects against link rot and gives the morning routine cleaner content to work with.

Reminders

A separate GHA workflow todo-reminder.yml runs every 30 minutes between 08:00–21:30 BKK. It:

  1. Lists todos/open/*.md via the GitHub API
  2. Filters for due_at within the next 30 minutes AND pinged_at == null
  3. Sends Telegram: ⏰ อีก N นาที: {summary} [{tag}]
  4. Stamps pinged_at on the file (no double-ping)

Stateless, no in-bot scheduler needed. Cost: ~28 runs/day on GHA, well within the 2000 min/mo free tier.

Q&A on demand (/ask mode)

Anytime, type /ask to switch to Q&A mode. The bot fetches your current wiki + recent daily summaries, stuffs them as context, and answers via Gemini chat. Multi-turn (rolling 5 turns of history). Voice-in works — ask while driving, get text back + voice reply via Gemini TTS.

/done returns to DUMP mode. Idle 10 min in ASK auto-reverts.


Reference

Environment variables

Required (6):

VarSource
TELEGRAM_BOT_TOKEN@BotFather
TELEGRAM_OWNER_CHAT_IDgetUpdates after sending /start
TELEGRAM_WEBHOOK_SECRETopenssl rand -hex 16
GEMINI_API_KEYaistudio.google.com
GITHUB_TOKENfine-grained PAT, Contents r/w
GITHUB_REPOyour-name/AgenticWiki

Optional (have defaults; override in Railway/.env to change):

VarDefaultOverride when
GITHUB_BRANCHmainworking in a feature branch
GEMINI_CHAT_MODELgemini-3.1-flash-lite-previewwant gemini-3.1-pro-preview (smarter, costlier) or gemini-flash-latest (Google-managed alias)
GEMINI_STT_MODELgemini-3.1-flash-lite-previewrarely; this model handles audio fine
GEMINI_TTS_MODELgemini-3.1-flash-tts-previewwant a different voice tier
GEMINI_TTS_VOICEKorecheck Google's voice catalog for alternatives
TIMEZONEAsia/Bangkoklive elsewhere
ASK_IDLE_TIMEOUT_MIN10want longer ASK sessions
QA_HISTORY_TURNS5want longer/shorter conversation memory
WIKI_CACHE_TTL_SEC3600how long the bot caches wiki content in memory between /ask calls (1 hour default — wiki only really changes at the 06:30 PR merge; /refresh forces invalidate at any time)
TODO_CONFIDENCE_THRESHOLD0.7classifier needs ≥ this to actually create a todo file from a dump
TODO_DEFAULT_HOUR9when classifier extracts a date with no time (e.g. "พรุ่งนี้"), default the hour to this
DUMP_SESSION_TIMEOUT_MIN5consecutive dump messages within this gap share a session id in frontmatter — morning routine reads them as one continuous thought
LOG_LEVELINFOwant DEBUG

Local-dev only (don't put in Railway): CF_API_TOKEN, CF_ACCOUNT_ID, CF_ZONE_ID, TUNNEL_NAME, TUNNEL_HOSTNAME — for scripts/dev_tunnel.sh.

Bot commands

CommandModeEffect
/startanyshow keyboard + intro
/helpanyshow current mode + command list
/ask [q]DUMP → ASKenter Q&A; with q answers immediately
/doneASK → DUMPexit Q&A back to default
/clearASKreset Q&A context (stay in ASK)
/eod [note]DUMPmark today complete — write daily-log-{date}.md, cancel evening escalation
/done <fuzzy>DUMPfuzzy-match an open TODO, move it to todos/done/
/cancel_todo <fuzzy>DUMPfuzzy-match an open TODO, move it to todos/cancelled/
/refreshanyinvalidate the wiki cache — next /ask re-fetches from GitHub

Repo structure

AgenticWiki/
├── README.md                       ← you are here
├── SETUP.md                        ← optional LINE setup
├── CLAUDE.md                       ← wiki schema (read by Routine)
├── agentic_wiki/                  ← Python bot package
│   ├── README.md                   ← dev/architecture doc
│   ├── main.py                     ← FastAPI + webhook
│   ├── config.py                   ← env settings
│   ├── state.py                    ← in-memory mode + Q&A history
│   ├── adapters/telegram.py        ← aiogram dispatcher
│   ├── handlers/                   ← ingest, qa
│   └── integrations/               ← github_client, gemini_client
├── line-webhook/                   ← (optional) LINE Cloudflare Worker
├── routines/00-morning.md          ← Cowork Routine prompt (paste this)
├── .claude/skills/morning/SKILL.md ← canonical procedure (Routine reads this)
├── .github/workflows/
│   └── evening-prompt.yml          ← 21/22/23 BKK ping
├── scripts/
│   ├── dev_polling.py              ← local dev: bot in polling mode
│   └── dev_tunnel.sh               ← local dev: Cloudflare named tunnel
├── raw/                            ← (immutable) voice/text/link dumps
│   └── sessions/{YYYY-MM-DD}/
│       ├── {HHMM}-text.md
│       ├── {HHMM}-voice.md
│       ├── {HHMM}-voice.ogg
│       ├── {HHMM}-link.md
│       └── daily-log-{date}.md     ← /eod marker
├── wiki/                           ← (LLM-maintained) interlinked pages
├── outputs/                        ← (LLM-generated) daily/weekly/monthly
└── followups/                      ← research queue

Mode states

[Mode.DUMP] (default for any user_id)
   │
   │  /ask [q]
   ▼
[Mode.ASK]  ──────  multi-turn Q&A, rolling 5-turn history
   │                voice replies via TTS
   │
   │  /done OR idle 10 min
   ▼
[Mode.DUMP]

State is in-memory (single Railway replica). Restart resets all sessions — accepted for v0.1; /eod markers persist on GitHub.

How /ask reads the wiki — data flow

The bot is stateless with respect to wiki content. Nothing is preloaded on Railway. Each /ask call:

  1. Fetches wiki/*.md, outputs/daily/{recent}.md, todos/open/*, notes/* from GitHub via the Contents API
  2. Caches the result in-memory for WIKI_CACHE_TTL_SEC (default 5 min)
  3. Stuffs everything as context into a single Gemini call
  4. Returns the answer; rolls a 5-turn history per chat

Cache is per-process, lost on Railway restart — that's fine because GitHub is the source of truth. The bot never holds the canonical copy.

The 06:30 Cowork morning routine runs in Anthropic's cloud, not Railway. It uses Claude's GitHub connector (separate from the bot's PAT) to read the same repo fresh, write a PR back. Bot and Cowork don't talk to each other directly — they coordinate through GitHub commits.

GitHub repo ── single source of truth
   │
   ├─ Bot (Railway)  : pulls /ask context (5-min cache), pushes raw + todos
   └─ Cowork (cloud) : pulls all (fresh each run), opens morning PR

Cost estimate

Free tier is plenty for personal use if you stay inside it. Concrete math at moderate use (50 voice + 20 text dumps + 10 ASK + 10 TTS replies/day):

FlowTokens/dayPaid-tier cost/day
STT (50 × 30s voice = 37.5K audio in)37,500 in$0.019
Classifier on 70 dumps14K in / 3.5K out$0.009
ASK input (10 × 50K wiki context)500K in$0.125
ASK output5K out$0.008
TTS audio out (10 × 30s)7,500 out$0.150
URL fetch + summarize (5/day)150K in$0.038
Total~$0.35/day = ~$10.50/month

Free vs paid:

  • Free tier project key → $0 if you stay under quota; preview models hit rate limits you'll feel as ⏳ Gemini quota... Telegram replies
  • Paid tier → ~$10/mo for the above use, no rate-limit anxiety

Force free-tier-only by creating the API key in a Google Cloud Project that doesn't have billing enabled. AI Studio → API keys → choose project → key is bound to that project's billing state. Update GEMINI_API_KEY in Railway + .env to switch.

Other costs:

  • Railway free credit ($5/mo) → 0
  • GitHub private repo → 0
  • Claude Pro/Max → $20 / $200 (one routine/day = 1/5 or 1/15 quota)
  • Cloudflare named tunnel → 0

Optimization (if you go paid)

  • Context cache for ASK — wiki is stable within a day; cache once, reuse → ASK input cost drops 10× ($0.025/M instead of $0.25/M)
  • Disable TTS — set GEMINI_TTS_MODEL= empty if you don't want voice replies; saves the largest single line item
  • Batch tier for classifier — 50% cheaper but adds 1–2 min latency, trade-off depending on whether you want immediate ⚡ TODO reply

Customization

Different LLM for Q&A

Set in Railway:

GEMINI_CHAT_MODEL=gemini-3.1-pro-preview     # smarter, costlier
# or
GEMINI_CHAT_MODEL=gemini-3-flash-preview     # full Gen 3 Flash (vs lite-preview)

Different schedule

  • Evening prompt: edit .github/workflows/evening-prompt.yml cron lines
  • Morning routine: edit the schedule in Cowork directly
  • Q&A idle timeout: ASK_IDLE_TIMEOUT_MIN=20 in Railway

Different language for prompts/replies

  • Bot replies: edit strings in agentic_wiki/adapters/telegram.py and agentic_wiki/handlers/
  • Morning compile output language: edit .claude/skills/morning/SKILL.md
  • Evening prompt text: .github/workflows/evening-prompt.yml

Disable voice replies (TTS)

Don't set GEMINI_TTS_MODEL or set it to empty in Railway. Voice replies in ASK mode will silently skip; text-only replies still work.

Add a new skill the Routine can use

Drop .claude/skills/{name}/SKILL.md. Reference it from the Routine prompt or call from morning/SKILL.md.


Troubleshooting

Telegram says Failed to resolve host when setting webhook

  • Telegram blacklists *.trycloudflare.com. Use a named Cloudflare tunnel (free with any zone) or just deploy to Railway.

Bot returns 500 on every webhook

  • Check Railway Deploy Logs for event: bot.start_failed. Usually TELEGRAM_BOT_TOKEN got pasted with quotes / extra chars.

webhook.bot_not_initialized in logs

  • The bot started but couldn't init the Telegram client. Same root cause as above — fix the token env.

Push refused: "Personal Access Token cannot update workflow"

  • Fine-grained PATs default without Actions:write. Either add Actions r/w to the PAT, or push workflow files using gh CLI (which has workflow scope via OAuth) instead of the PAT.

Railway healthcheck fails on first deploy

  • Container probably bound to wrong port. Make sure your Dockerfile CMD expands ${PORT} (the repo's Dockerfile does this — sh -c "..." shell form is required for variable expansion).

Cowork "Connect GitHub" works but the repo dropdown is empty

  • The Claude.ai OAuth flow authorizes Claude on your GitHub account but often skips installing the GitHub App, which is what actually grants repo access. Symptom: github.com/settings/installations shows no Claude entry; only Authorized GitHub Apps does.
  • Fix: open https://github.com/apps/claude/installations/new directly, pick your account, select the AgenticWiki repo, install. The repo will then appear in Cowork.

Repo not visible in Cowork after transferring it between accounts

  • Same root cause as above — the App installation is per-account and doesn't follow a transferred repo. Re-install on the new owner account via the URL above.

Related repos / inspiration

↑↓ navigate openesc close