The Claude-In-Slack Feature Everyone Missed: 4-Day Memory

Everyone's replaying the clip where a user tags Claude in Slack and Claude replies four days later with a finished task. The mention is cosmetic. The thing that makes it work — the reason it doesn't forget on Tuesday what you asked on Monday — is a boring state table that most breakdowns skip entirely. I build this exact pattern for clients every week. Here's the schema, the code, and the honest math on when to buy the wrapper vs. build it.
What Claude-in-Slack is actually doing under the hood
A user tags Claude in a channel, Claude replies. That's a chatbot. The demo goes further: Claude picks up a task, waits on an external event (an email reply, a calendar trigger, a timer), and comes back days later with the output — in the right thread, with the right context. That's not a chat feature. That's a state machine with a scheduler in front of it.
Three things have to be true for a task to survive across days:
- The system remembers exactly where it left off.
- It knows what event it's waiting for.
- When the event fires, it resumes in the right channel with the right context, so the human doesn't feel like they're talking to a goldfish.
The at-mention is the interface. The persistence layer is the product. One of those you can copy in an afternoon; the other one you're paying $30/user/month for, plus a Slack Business+ seat on top.
The 4-column table that makes multi-day tasks work
Here's the schema I use when a small business asks me to build an AI ops assistant inside Telegram, WhatsApp, Slack, or plain email:
CREATE TABLE agent_tasks (
task_id UUID PRIMARY KEY,
channel_id TEXT NOT NULL,
status TEXT NOT NULL, -- pending | waiting | resumed | done | failed
resume_context JSONB NOT NULL,
wake_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_wake ON agent_tasks (status, wake_at);
Four columns doing all the work:
- task_id — unique ID for the piece of work. UUIDs are fine.
- channel_id — where the conversation lives. Slack channel, Telegram chat ID, Gmail thread ID. When the task wakes up, this is how it knows where to speak.
- status — a small closed set of values.
pending,waiting,resumed,done,failed. That's it. - resume_context — a JSON blob with everything the model needs to pick up the thread: original request, partial output, the trigger it's watching for, tool call history if relevant.
wake_at and updated_at are convenience columns for the scheduler. The state model itself is the four columns above.
A real scenario: 48-hour lead follow-up
Small business owner says in Slack: "Follow up with this lead if they don't reply in 48 hours."
Step by step, here's what actually happens:
- Assistant drafts the initial email, sends it via Gmail API.
- Writes a row to
agent_tasks:
{
"task_id": "8f2a...",
"channel_id": "C07ABCD1234",
"status": "waiting",
"resume_context": {
"kind": "lead_followup",
"lead_email": "sarah@acme.com",
"gmail_thread_id": "18c9f...",
"original_ask": "Follow up if no reply in 48h",
"requested_by": "U01XYZ"
},
"wake_at": "2026-09-11T14:30:00Z"
}
- A cron job runs every 15 minutes. It looks for rows where
status = 'waiting'ANDwake_at <= now(). - When it finds one, it checks the trigger — did the lead reply on that Gmail thread?
- If yes: mark
done, post a summary in the Slack channel. If no: flip toresumed, hand the resume context back to the model, and the model writes the follow-up in the same email thread.
The scheduler in Python, in about 40 lines:
import psycopg, json, time
from datetime import datetime, timezone
def tick():
with psycopg.connect(DB_URL) as conn, conn.cursor() as cur:
cur.execute("""
SELECT task_id, channel_id, resume_context
FROM agent_tasks
WHERE status = 'waiting' AND wake_at <= NOW()
FOR UPDATE SKIP LOCKED
LIMIT 25
""")
for task_id, channel_id, ctx in cur.fetchall():
try:
if ctx["kind"] == "lead_followup":
replied = gmail_has_reply(ctx["gmail_thread_id"],
ctx["lead_email"])
if replied:
post_slack(channel_id, f"Lead {ctx['lead_email']} replied.")
mark(cur, task_id, "done")
else:
reply = claude_followup(ctx)
gmail_send(ctx["gmail_thread_id"], reply)
mark(cur, task_id, "resumed")
except Exception as e:
mark(cur, task_id, "failed", error=str(e))
def mark(cur, task_id, status, error=None):
cur.execute("UPDATE agent_tasks SET status=%s, updated_at=NOW() "
"WHERE task_id=%s", (status, task_id))
if __name__ == "__main__":
while True:
tick()
time.sleep(60 * 15)
Total infrastructure: one Postgres table, one cron loop. Total cost on a $5 VPS or a home server: effectively zero on top of what you're already paying.
Buy vs. build: the honest math for a 5-person team
I'm not going to tell you Anthropic's product is bad — it's genuinely good and the distribution inside Slack is unmatched. But if you're a solopreneur or a small shop, run the numbers before you sign:
| Item | Buy (Claude in Slack) | Build (self-hosted state layer) |
|---|---|---|
| Claude Team seats, 5 × $30/mo | $150/mo | $0 (use API pay-as-you-go) |
| Slack Business+ upgrade, 5 seats | ~$75-125/mo | $0 (existing Slack tier fine) |
| Claude API usage (moderate) | included in seat | ~$20-60/mo |
| Hosting (VPS or home server) | — | $5-15/mo |
| Engineering time to build | 0 hours | 6-10 hours once |
| Monthly total | $225-275 | $25-75 |
Over a year that's a $2,400-$3,000 delta for a 5-person team. That gap is only worth paying if you also need SSO, audit logs, enterprise DLP, and a support contract. If you don't, you're paying $2,500/year for the at-mention UI.
The Anthropic pricing page lists current tiers; the Claude API rate card shows what you actually pay per million tokens if you go direct.
Why the at-mention gets commoditized in 6 months
Every AI vendor is about to ship a version of "tag the AI in the tool you already use." Gmail already has it. Notion has it. Linear, Teams, Jira, HubSpot — all shipping their variant. The surface is going to look identical across products by mid-2026.
The moat isn't the mention. The moat is the state layer that makes tasks survive across sessions, across days, across process restarts. If your assistant can't remember what it was doing yesterday, it's a demo. If it can, it's an operator.
Half the tools being marketed as "autonomous agents" right now are stateless request-response loops with a nice UI. The other half have a real persistence layer and they're not talking about it, because a database table doesn't demo well on X. The quiet half is going to eat the loud half.
Persistence isn't a premium feature. It is the feature.
Where this pattern breaks (and how to catch it)
The four-column table is not a magic schema. Things I've watched go wrong in production:
- Duplicate resumes. Two cron ticks pick up the same row. Fix:
FOR UPDATE SKIP LOCKEDon the SELECT, as in the snippet above. Not optional. - Context blob rot. You change the shape of
resume_contextin a new deploy and old rows crash the resumer. Version the blob:{"v": 2, ...}and keep the old handler around. - Silent failures. Task flips to
failedand nobody sees it. Ship a daily digest to the requesting channel: "3 tasks failed yesterday, here are the IDs." Two lines of SQL. - Trigger drift. You wait for an email reply, but the lead replies from a different address. Widen the trigger check (match on thread ID, not sender) and log what fired.
- Runaway wake_at. A bug sets
wake_atin 2035. Add a sanity clamp: reject anywake_atmore than 90 days out unless explicitly flagged.
None of this is glamorous. All of it is what separates a working system from a Loom video.
Where bizflowai.io fits into this
I build this exact pattern for clients through bizflowai.io — usually inside Telegram or WhatsApp for solopreneurs, and inside Slack or email for 5-15 person teams. The state table, the scheduler, the trigger handlers, and the model calls are all standard building blocks now; the real work is mapping your recurring workflows (lead follow-up, invoice chasing, quote approvals, hiring pipeline nudges) into resume contexts that survive a week. If you're already paying $200-plus a month for an AI-in-Slack subscription and only using it for a handful of workflows, the buy-vs-build math almost always tips toward a small custom layer.
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 a stateful AI assistant?
A stateful AI assistant is one that can pause a task, wait for an external event like an email reply or timer, and resume days later in the correct conversation with full context. Unlike a chatbot, it uses a state machine with a scheduler, remembering where it left off, what trigger it's watching for, and how to pick up the thread when that event fires.
How do I build a state machine for a long-running AI task?
Create a database table with four columns: Task ID (unique identifier), Channel ID (where the conversation lives), Status (pending, waiting, resumed, done, or failed), and Resume Context (a JSON blob with the original request, partial output, and trigger). Run a cron job every fifteen minutes to find waiting rows whose trigger fired, then hand the context back to the model to continue.
Why does the state layer matter for AI agents?
The state layer matters because AI vendors are commoditizing the at-mention feature across Gmail, Notion, Linear, and Teams within months. The real moat is persistence: making tasks survive across sessions, days, and restarts. If an assistant can't remember what it was doing yesterday, it's a demo. If it can, it's an operator capable of running real workflows for a business.
When should I build my own AI ops assistant vs pay for Claude Team?
Claude Team costs thirty dollars per user monthly, plus a Business or Enterprise Slack tier, totaling four to six hundred dollars monthly for a five-person team. If you're a solopreneur or small shop, build your own using a Postgres table and scheduler on a five-dollar VPS. If you need enterprise distribution, compliance, and Slack-native UX at scale, pay for the wrapper.
How much does a DIY stateful AI assistant cost to run?
Effectively zero infrastructure cost. The state machine requires about forty lines of code, one Postgres table with four columns, and a scheduler that polls every fifteen minutes. It runs on a home server or a five-dollar VPS. This replaces the roughly four to six hundred dollars monthly a five-person team would pay for Claude Team plus Slack Business or Enterprise seats.