Anthropic Validated My Agent Architecture — 1 Detail Missing

Anthropic's @Claude for Slack demo hit 67 million views by showing an agent that lives inside your conversation history, picks up full context, and reports back asynchronously. The pattern is correct. The surface choice is wrong for 90% of the market. Here's the architecture that actually ships for small businesses, and the one design decision Anthropic left out.
The @Claude Demo Was Architecture Validation, Not a Product Launch
When Anthropic showed @Claude working inside Slack threads — picking up who said what, what files were shared, what decisions were made, and responding with full context — they confirmed something I'd been running on a home server for months: the standalone chatbot tab is dead. The agent belongs in the channel where work already happens.
The three-layer architecture they demonstrated, probably without naming it that cleanly, is this:
- Surface integration — read and write access to a communication channel
- Persistent context — the agent reads conversation history and builds on it across sessions
- Async execution with callback — you tag it, it goes away, does work, reports back to the same thread
None of those layers require Slack. Slack is one read-write surface among many. The reason the demo went viral is that every viewer could immediately see themselves using it without changing a single thing about their workflow. No new tab, no migration, no paste-back-and-forth. That's the insight — not the platform choice.
Slack Has 35M Users. WhatsApp Has 2.7B. The Gap Is Your Opportunity.
Here's what Anthropic deliberately limited: @Claude is locked to Slack, on Enterprise plans, at $30 per user per month. For the market they're targeting, that's a reasonable price. For the market I build for, it's a non-starter.
The numbers tell the story plainly:
| Platform | Monthly Active Users | Typical User |
|---|---|---|
| Slack | ~35M DAU | Knowledge workers, tech companies |
| Telegram | ~950M MAU | Mixed — including SMB operations |
| ~2.7B MAU | Everyone, including every small business |
The solopreneurs, five-person agencies, local service companies, and independent contractors I build systems for don't use Slack. They've never heard of it. They run their entire operation through WhatsApp groups and Telegram chats. A landscaper in Texas coordinates his crew via WhatsApp. A consultant in London manages client comms through WhatsApp Business. A bookkeeping firm in Toronto shares documents in Telegram group chats because it's faster than email.
Anthropic validated an architecture for the top of the market and left the bottom completely open. That gap is where channel-resident agents on Telegram and WhatsApp become the real product.
The Three-Layer Pattern, Built For Telegram Instead of Slack
The non-obvious technical insight: the agent doesn't need to be in Slack. The real architecture is an agent core connected to a persistent context store, with N surface adapters hanging off it. Here's what that looks like in practice — working code I run daily.
Layer 1: Surface Integration
Telegram's Bot API gives you everything Slack's API gives you, for $0, with no enterprise plan. You get message webhooks, file handling, thread routing via reply chains, and inline commands.
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, ContextTypes, filters
async def agent_trigger(update: Update, context: ContextTypes.DEFAULT_TYPE):
chat_id = update.effective_chat.id
message_thread = update.message.message_thread_id # topic support
user = update.effective_user.first_name
raw_text = update.message.text
# Pass the full trigger to the agent core
job = {
"chat_id": chat_id,
"thread_id": message_thread,
"user": user,
"trigger_text": raw_text,
"timestamp": update.message.date.isoformat(),
}
await context.bot.send_message(
chat_id=chat_id,
text=f"Got it, {user}. Processing — I'll report back here.",
reply_to_message_id=update.message.message_id,
)
# Enqueue async — callback writes the result back to this chat+thread
await context.application.queue.put(job)
That's layer one: the agent has read/write access to the communication channel. When someone tags it or sends a command, the trigger is captured with full routing metadata (which chat, which thread, who asked).
Layer 2: Persistent Context
This is what Anthropic got right and what most builders get wrong. The agent doesn't start fresh. It reads conversation history before responding.
import sqlite3, json
def load_context(chat_id: int, limit: int = 50) -> list[dict]:
"""Pull recent conversation history for this channel."""
conn = sqlite3.connect("agent_context.db")
rows = conn.execute(
"""SELECT role, content, timestamp, metadata
FROM messages
WHERE chat_id = ?
ORDER BY timestamp DESC
LIMIT ?""",
(chat_id, limit)
).fetchall()
conn.close()
return [
{"role": r[0], "content": r[1], "timestamp": r[2], "metadata": json.loads(r[3])}
for r in reversed(rows)
]
def save_message(chat_id: int, role: str, content: str, metadata: dict = None):
conn = sqlite3.connect("agent_context.db")
conn.execute(
"INSERT INTO messages (chat_id, role, content, metadata) VALUES (?, ?, ?, ?)",
(chat_id, role, content, json.dumps(metadata or {}))
)
conn.commit()
conn.close()
Every message — human or agent — gets stored with the chat ID and thread ID. When the agent wakes up to process a trigger, it loads the last 50 messages from that channel as context. A conversation that started Tuesday morning is still in scope Friday afternoon. That's the persistent context layer.
Layer 3: Async Execution With Callback
The trigger comes in, the agent acknowledges immediately, then does the actual work asynchronously. The callback writes the result back to the exact same chat and thread.
async def execute_and_callback(job: dict, bot):
chat_id = job["chat_id"]
thread_id = job["thread_id"]
# Load persistent context
history = load_context(chat_id)
# Do the actual work — this could take 5 seconds or 5 hours
result = await run_agent_core(
trigger=job["trigger_text"],
history=history,
user=job["user"],
)
# Save the result to persistent context
save_message(chat_id, "user", job["trigger_text"])
save_message(chat_id, "assistant", result["answer"], metadata={"sources": result.get("sources")})
# Callback: write the answer back to the same thread
await bot.send_message(
chat_id=chat_id,
text=result["answer"],
message_thread_id=thread_id,
parse_mode="Markdown",
)
That's the entire pattern. Three layers. None of them require Slack. The hard part isn't the AI model — it's the integration plumbing, the context management, and making it reliable enough to trust with real work.
Cross-Surface Context: The Detail Anthropic Left Out
Here's the one design decision that matters more than platform choice, and it's the thing Anthropic didn't show in the demo because their product is locked to a single surface.
The agent core is surface-agnostic. The context store is shared across all surfaces. That means a conversation that starts in Telegram can continue in email, and the agent knows the full history.
In my own system — what runs daily for real operations — an agent lives in Telegram and picks up Gmail context. Someone emails me at 2am. By 7am, the agent has triaged the inbox, categorized 40+ messages, flagged 3 as urgent, drafted responses for 12, and posted a summary to my Telegram chat. When I reply to the Telegram summary, the agent knows the original email thread. When I send a follow-up email later that afternoon, the agent knows what was decided in Telegram that morning.
That cross-surface context continuity is the architecture Anthropic showed a fragment of. They showed it within Slack. The real power is when it spans surfaces.
Here's how the context store handles it:
def load_unified_context(entity_id: str, surfaces: list[str] = None) -> list[dict]:
"""Load context across all surfaces for a given entity (user/org)."""
surfaces = surfaces or ["telegram", "gmail", "whatsapp"]
placeholders = ",".join("?" * len(surfaces))
conn = sqlite3.connect("agent_context.db")
rows = conn.execute(
f"""SELECT surface, role, content, timestamp, metadata
FROM unified_messages
WHERE entity_id = ? AND surface IN ({placeholders})
ORDER BY timestamp DESC
LIMIT 100""",
(entity_id, *surfaces)
).fetchall()
conn.close()
return [
{
"surface": r[0],
"role": r[1],
"content": r[2],
"timestamp": r[3],
"metadata": json.loads(r[4]),
}
for r in reversed(rows)
]
The entity_id is what ties it together. For a client relationship, it might be the client's email address plus their Telegram user ID, mapped to a single entity. Messages from either surface get logged against that entity. When the agent loads context, it pulls from all surfaces and gets the full picture.
This is the layer that takes a single-surface bot and turns it into something that feels like a team member who's been in every conversation.
Real Numbers: What This Costs vs. @Claude's $30/Seat
Here's exactly what I run, with real costs. Not estimates.
A channel-resident agent on Telegram, processing roughly 200-400 triggers per day across a handful of small business clients, runs on a home server. The compute cost is the electricity for a mini PC — about $4/month. The model cost depends on what you route to:
| Task Type | Model | Avg Tokens/Call | Cost/Call | Daily Volume | Daily Cost |
|---|---|---|---|---|---|
| Simple triage/categorization | Haiku-class | ~800 in, ~200 out | ~$0.0004 | ~300 | ~$0.12 |
| Email summarization | Sonnet-class | ~3000 in, ~500 out | ~$0.015 | ~40 | ~$0.60 |
| Draft responses | Sonnet-class | ~5000 in, ~800 out | ~$0.022 | ~20 | ~$0.44 |
| Complex reasoning/research | Sonnet-class | ~10000 in, ~1500 out | ~$0.05 | ~5 | ~$0.25 |
Total daily model cost: roughly $1.40. Monthly: ~$42. Add server electricity: ~$46/month total. For an entire multi-client agent system that runs 24/7.
Compare that to @Claude on Slack at $30/user/month. A 5-person team pays $150/month — and that's for a single surface, locked to Slack, with no cross-channel context.
The economics work because you're not paying per seat. You're paying per token, and most triggers are simple tasks that route to cheaper models. The agent core decides which model to use based on task complexity. That's a design decision, not a pricing accident.
Where Most Builders Go Wrong
The mistake I see repeatedly — from both indie hackers and agencies selling "AI solutions" — is building standalone chatbot destinations. A website widget. A separate app. A ChatGPT tab where someone has to manually paste context. That entire pattern is what Anthropic just made obsolete with 67 million views of proof.
If your product requires someone to open a new tab or switch to a new app to talk to the AI, you're building against the grain of where this is heading. The work goes to the agent, not the other way around.
The second mistake is building for a single surface with no context abstraction. If your agent only knows about Slack messages and can't see email history, you've built a dead end. The context store should be surface-agnostic from day one, even if you only ship one adapter initially.
The third mistake — and this is the one that kills production systems — is treating reliability as an afterthought. The hard part isn't calling the model. The hard part is:
- Handling API timeouts and retries on the surface layer
- Managing rate limits across both the LLM and the messaging platform
- Dealing with message ordering when async jobs complete out of sequence
- Preventing the agent from responding to its own messages in an infinite loop
- Gracefully handling the edge cases where context exceeds the model's window
These are engineering problems, not AI problems. They're solvable, but only if you take them seriously from the start. I've lost more hours to Telegram webhook delivery quirks than to anything related to model behavior.
Why bizflowai.io helps with this
At bizflowai.io, I build exactly this pattern for small businesses — channel-resident agents on Telegram and WhatsApp that handle inbox triage, lead qualification, invoice follow-up, and daily operations reporting. The systems run cross-surface context stores so a conversation started in one channel carries through to every other channel the client uses. The agent core is already built, the surface adapters are already tested in production, and the plumbing that makes it reliable enough to trust with real client work is already solved. What takes a solo builder weeks to get working is already shipping.
Want more like this?
I publish practical AI automation, GenAI engineering, and faceless content workflows on YouTube every week.
Subscribe to bizflowai.io on YouTube — never miss a new tutorial.
Planning an AI automation project or need a second opinion on your architecture?
Connect with me on LinkedIn — Lazar Milicevic, GenAI Engineer & bizflowai.io Founder.
Visit bizflowai.io for our services, case studies, and AI consulting.
Frequently asked questions
What is Anthropic's @Claude in Slack?
@Claude is an AI agent that can be tagged into any Slack thread to do work asynchronously. When tagged, it reads the full conversation context — who said what, what files were shared, and what decisions were made — then responds directly in the thread. It requires no new tab or tool. It launched as a beta for Enterprise customers at $30 per user per month.
What are the three architectural layers behind @Claude in Slack?
The three layers are: surface integration (the agent has read and write access to a communication channel like Slack, Telegram, or WhatsApp), persistent context (the agent reads conversation history and builds on it rather than starting fresh), and async execution with callback (you tag the agent, it does work over seconds or hours, and reports back to the same thread when done).
Why does the standalone chatbot tab model not work anymore?
Anthropic proved at scale that AI agents work best where conversations already happen. Standalone chatbot tabs require users to switch apps, manually paste context, get an answer, and switch back. By embedding the agent directly in a thread with existing context, the agent eliminates all of that friction. The value proposition is that no workflow change is needed — the agent works where you already are.
When should I use a Slack-based agent vs a WhatsApp or Telegram agent?
Slack-based agents like @Claude serve Enterprise customers already on Slack, but are locked to that platform at $30 per user per month. WhatsApp (2.7 billion users) and Telegram (950 million users) are where solopreneurs, small agencies, and local service companies actually operate. If your target users have never used Slack, building the same three-layer agent architecture on WhatsApp or Telegram surfaces reaches that underserved market.
How do I build a multi-surface AI agent like @Claude?
Build an agent core connected to a persistent context store, with multiple surface adapters attached. One adapter talks to Slack, another to Telegram, another to WhatsApp Business API, another to Gmail. The agent core is surface-agnostic and the context store is shared, so a conversation that starts in one channel can continue in another with full history. This runs on a home server with no per-seat pricing.