← Back to the blog

Advisors on Telegram

Series: How I built a second brain · part 5

Until the end of July, my six AI advisors and their council only answered me at the keyboard. To talk to an advisor, I had to sit at the computer and open a terminal. But questions don't come up at the computer. So at the end of July I moved them to my phone: seven ordinary contacts in Telegram, one for each advisor and one for the council.

The bot is only transport

The whole decision rests on one sentence: the bot must not contain any of the advisors' logic. It takes a message, passes it on, returns the answer and saves what changed. Who is who and what they remember stays in the wiki and its instructions, just as at the keyboard. A different input device, the same contract.

Technically it is one process on my own machine that serves all seven bots. It hands every message to Claude Code, started without a screen right in the wiki's folder, so it loads the instructions itself, whole and unchanged.

There was an obvious alternative: OpenClaw, which was already running on the same machine, Telegram included. I explained in part two why I turned it down: its connection to Claude deliberately switches off the project instructions. And my instructions are the whole second brain. A separate bot was both the smaller build and the more faithful one.

When a conversation ends

At the keyboard, a conversation ends when I close the window. A chat has no end, so I had to define one.

  • The first message opens a new session.
  • Further messages continue the same session; the advisor remembers what we are talking about.
  • After thirty minutes of silence, or on the /wrap command, the session closes.

Closing is a separate call to the model with a single job: write down in the wiki what happened and update the state. Before, it was a rule the model had to remember in the middle of a conversation. Now it is a step with nothing else in it. When the conversation was trivial, the model answers in one word that there is nothing to write, and nothing is written.

Then the session is thrown away. The next message starts clean and loads the state from the wiki.

The memory is the wiki, not the chat history.

That also keeps the cost under control: every conversation starts with the same amount of context, not with a growing conversation from last week.

Three questions that changed the build

The bot worked within one afternoon. Only then did I start asking awkward questions, and each one exposed a hole.

What if the credits run out just as a session closes?

The first version deleted the session in that case. A conversation that hadn't been written down was gone. On top of that, Claude Code reports an error with an is_error flag, while another field keeps saying "success". The code was looking at the other one.

Today a failed close never deletes the session. It retries after ten minutes, after thirty, then every hour without end, because credits come back. It warns me once. The retry continues the same session, so the model sees what it has already half written and doesn't write it twice.

What if one prompt eats the whole limit?

The only safeguard was a time limit per turn. I added two layers: a spending cap on every turn, enforced by Claude Code itself, and a rolling counter across all the bots that keeps a reserve for closing sessions. Even when chat is cut off, the write-up still happens.

What if the service crashes?

By default, systemd gives up on a service that crashes five times in quick succession and leaves it dead, silently. Today it restarts it forever. The bot also signals every minute that it is alive, but only when all seven bots are really listening. A process that runs but doesn't hear is just as dead to me. A separate watchdog checks this every five minutes, warns me and restarts the service. But a watchdog on the machine can't tell me the whole machine has gone dark. That has to be watched from outside.

The most valuable code didn't come from the design, but from the question "what if…" asked the day after the design.

Testing turned up one more small thing: placeholder text instead of a token passed the check, because the check looked for capital letters. It would have brought down all seven bots at once. Today one bot's failure doesn't stop the others.

Advisors that speak up on their own

The phone opened a second possibility: an advisor can speak up without being asked. In August each one got scheduled checks. A check is not a conversation. It runs once, on its own, and either finds something that really needs me, or writes nothing.

A check must not change the wiki. It sends a message and a proposed entry, with two buttons under it: write it, or don't. Only my "write it" starts a second call, the only one allowed to write. All the advisors read the wiki, so one wrong conclusion written without oversight would spread into every later conversation. The bot remembers a rejected proposal so that it doesn't come back every week.

When we were planning the next wave of checks, I asked whether they would all speak up at eight on a weekday morning. That showed what the real limit is: my attention, not money. Six sensibly configured advisors, each with one check a week, produce so many messages that I stop reading them. And a check nobody reads is worse than none, because it creates the impression that something is being watched.

So unsolicited messages compete for three slots a week across the whole fleet. Every check has a priority; a tax deadline beats a content idea. Low-priority checks must leave one slot free, so that a Wednesday idea can't block a Friday deadline. And what loses isn't lost: the same advisor's next check gets it back.

What went wrong

The advisor that didn't know it had a schedule

The day after the checks went live, one advisor told me with confidence that it didn't watch my mail itself and that I should remind it. Its check was reading the mail twice a week. The conversation instructions described an advisor that only answers, because that is what it used to be. Today each advisor reads its schedule in its instructions, and that part is generated straight from the schedule. A hand-written list of checks is a second copy of the schedule, and that copy is always the one that goes stale.

Allowed tools that allow nothing

I gave a check only the calendar, and it read my mail and my drive anyway. For MCP tools, the list of allowed tools restricts nothing; only the list of denied tools works. Every access a check shouldn't have is now denied by name.

How to start

  1. Make the bot only transport. Logic and memory belong where the rest of the system reads them too.
  2. Define when a conversation ends, and make the write-up a separate step, not a rule in the middle of the conversation.
  3. A failure must not delete. Walk through every error branch and ask what disappears in it.
  4. Watch that the service is listening, not just that it is running.
  5. Give unsolicited messages a budget. Attention is the scarcest resource you have.
  6. The automation proposes, you approve, until you have a good reason to trust it.

Next time: how I started feeding my own data into the second brain, from health, the car, the bank, photos and mail.

← Back to the blog Get in touch