Five Stages to One Brain—How I Connected My AI Agent Across Devices
I built an AI assistant that handles my daily workflow—research, content publishing, code reviews. It's all terminal based, and it worked fine until I wanted to check things from my phone.
So connecting Telegram to an AI agent sounds simple, right? It took me five tries.
Stage 1: Groq + Llama 3
I started with Groq—fast inference, free tier. I connected it to Telegram and asked about my project pipeline.
It made up task names. It listed projects I never created and gave me project data that didn't match my database.
For a status tool, wrong data is worse than no data. So Groq was out.
Stage 2: Claude Haiku with Tools
I switched to Claude Haiku through the Anthropic API and gave it tools to search memory, read files, and check the database. Now it could look things up instead of guessing.
The answers were better, but it could only read. It couldn't edit files, run scans, or do real work. When I asked it to run an automated task, it said "switching to Claude Code now." It didn't actually do that—it hallucinated the action.
A read-only assistant isn't what I needed.
Stage 3: Haiku Front, Claude Code Backend
I thought I could fix this with two tiers. Haiku handles light questions—status checks, quick lookups, chat. Heavy requests like "generate reports" or "run analysis" get routed to Claude Code for the full toolchain.
Both tiers had access to the same files. Haiku could read memory files and query the database through tools—read_file, list_files, search_memory. Same data sources.
It still didn't work.
The problem wasn't memory, it was context. Haiku had its own conversation thread and Claude Code had its own. When I told Haiku "pull the analysis results from yesterday," it could search memory and find the data. But it didn't have the nuance—it didn't know the rejected approaches or the reasoning behind decisions. It had summaries, not understanding.
So here's the thing: two brains with shared memory isn't the same as one brain. Memory gives you facts, but conversation gives you context.
Stage 4: Pure Claude Code, No Haiku
I removed everything—all the Haiku code, the API calls, the tool routing, the chat history, the system prompts. About 350 lines deleted. Telegram messages went straight to Claude Code CLI through claude --print.
Full tool access, file editing, memory search, accurate answers. A macOS scheduled task checks Telegram every 60 seconds. No daemon, no open ports.
But each claude --print call was a one-shot subprocess (starts with zero context, processes one message, dies). The next message started fresh.
When I asked "what did we just discuss?" from Telegram, it didn't know. Each message was a stranger.
I tried a conversation log—write every Telegram exchange to a file, load recent exchanges as context on the next call. But that's just summaries again. And when I switched from Telegram to my terminal, the terminal had no idea what happened on Telegram. Two interfaces, separate threads, same problem.
Stage 5: One Brain, Two Interfaces
The fix was one flag: --continue.
Claude Code has a session resume feature. Most people use it to pick up where they left off in the terminal. Convenience feature. That's how the community talks about it.
But combine
--continue with --print and something different happens. --print makes Claude Code non-interactive—takes a prompt, returns a response, exits. Add --continue and it runs inside your existing conversation. Same transcript. Same context. Same tools.Telegram → watcher → claude --continue --print → same session
Terminal → claude --continue → same session
When I discuss something on Telegram at night, then open my terminal in the morning, the conversation is already there. No replay, no memory search. Same brain.
If a terminal session is active when a Telegram message arrives, the watcher detects the conflict and queues the message. Heavy work requests—"generate reports," "run analysis"—get auto-queued for terminal regardless. We're talking 25 lines of Python for the concurrency guard.
At this stage, the Telegram bot was a cron job. It fires every 60 seconds, checks for messages, calls Claude Code, sends the response, and exits. Between messages: zero CPU, zero memory, zero attack surface. No webhook, no Docker.
I later replaced the cron job with a persistent daemon for performance, but the one-brain architecture stayed the same.
What Other Tools Offer
I checked what other LLM CLIs do for session persistence.
Claude Code is the only one where a bot and a terminal can operate on the same conversation. The others are heading there—Codex has exec resume, Gemini has the flags but they're broken—but none work from start to finish today.
Why the Cheap Model + Expensive Model Pattern Fails
The recommended architecture is to route 60% of requests to a cheap model and send heavy work to the full model. That saves 50–60% on tokens.
For agents that need to take action, this breaks. The cheap model makes routing decisions without the context the expensive model has. Haiku decides a query is "light" and handles it, but the query was a follow-up to a complex conversation. The cheap model gives a plausible but wrong answer.
I lived through this. Haiku answered project questions with data from memory search, and the answers looked correct. But they missed nuance from recent conversations—rejected approaches, decisions made for specific reasons. The expensive model would've caught these because it was in the conversation when those decisions happened.
A January 2026 paper—Agent Drift—measured this formally. Over extended interactions, agent task success rates dropped 42%. They called it agent drift. For multi-interface agents, each channel adds context fragmentation.
One model, one session, no routing avoids this.
The cost argument for tiered models disappears when you use a flat-rate subscription instead of pay-per-token API. An average session is 429,000 tokens. At API rates that's $6–15 per session. On a $100/month subscription, it's zero marginal cost. No reason to route to a cheaper model when all models cost the same.
Interface Routing Still Makes Sense
There's one place where routing works—not between models, but between interfaces.
Some work belongs on a phone: status checks, quick questions, project updates. Some work needs a terminal: code reviews, analysis results, generating reports.
My bot detects work requests—anything starting with "build," "create," "scan," "update"—and queues them for terminal instead of processing on a phone. This isn't model routing, it's recognizing that a 4-inch screen is the wrong tool for reviewing 200 results.
Why does everyone route by model cost when nobody routes by interface capability?
The Lesson
The temptation with multi-interface AI agents is to use a cheap model as the front door and an expensive model as the backend. Share memory between them and hope they stay in sync.
This doesn't work—not because memory is bad, but because conversation context isn't the same as memory retrieval. Two models with shared memory still have different understandings of the same facts.
The real solution is one model, one session, multiple interfaces. Sometimes a CLI flag and a cron job is the right architecture. Hope this helps.
Read the Series
20 years building production systems. From embedded hardware to AI platforms. Currently building multi-agent tools for personal and small-team use.
