Your working memory for Slack.
Tempo triages the firehose, remembers what you promised, decodes what people actually meant, and protects your attention. It never stores what it reads.
400 unreads
4 things that actually need you
Priya has been blocked on you since Tuesday.
#proj-atlas — she never @-mentioned you.
You promised feedback on the handoff doc. It's overdue.
You said "by Monday" — 9 days ago.
Design review needs your sign-off by EOD.
Production incident on Thursday — already resolved.
Scary words. Engineering closed it. Not yours.
The other 396 were noise, and Tempo said so.
- 413 tests, across 55 files
- 0 messages ever stored
- 25 scopes, each justified in CI
- 3 of 3 required technologies, live
- 0 credentials needed to run it
The important part of Slack isn't in the messages. It's in between them.
The urgency the words don't state. The obligation nobody wrote down. The person waiting in silence. Neurotypical native speakers reconstruct that layer automatically and for free. Everyone else pays for it, in attention they don't get back.
Slack has no memory of you. It remembers every message, and nothing about which ones were load-bearing — so the work of deciding what matters is silently pushed onto the person least able to spare it.
Tempo is assistive technology for that. Built for the ~15–20% of knowledge workers who are neurodivergent, for people working in a second language, for anyone coming back from leave to 400 unreads — and, honestly, for everyone else on a bad week.
Three minutes, end to end.
Triage, the tone decoder in both directions, a real Do-Not-Disturb flip on the user's own
token, and the MCP server answering a live tools/list.
Nothing loads from YouTube until you press play — no cookies, no tracking scripts on this page. Open on YouTube instead.
"No rush 🙂" is not a message about rushing.
The gap between what a message says and what it means is invisible to Slack — and exhausting to compute all day if implicit subtext doesn't come to you for free. Pick a message and see what Tempo actually returns.
They say there's no rush and you can get to it whenever.
They're actually frustrated. The "🙂" and "only been a week" are sarcastic — they expected this days ago and the handoff is waiting on you.
Politely irritated / passive-aggressive.
Higher than the words suggest — treat as "needed today".
Reply soon with the feedback (or a firm ETA) and a brief acknowledgement of the delay.
"Tone is hard to read over text and I can be wrong — if it matters, a quick 'sorry for the delay, you'll have it by X' covers you either way."
They need something confirmed by end of day.
This is a real, time-boxed ask tied to something visible (a board deck). It's not optional.
Direct, businesslike, not unfriendly.
Genuinely high — there's a hard deadline.
Confirm today, clearly, even if the answer is "I'll have it by 4pm".
"If you can't make the deadline, say so early rather than going quiet."
A straightforward message.
No strong hidden subtext detected.
Neutral.
Normal.
Reply when convenient.
"I can misread tone; trust your read if you know this person well."
Look at the third one. Nothing is hidden in it, and Tempo says so — at 60%, with a caveat telling you to trust yourself over the model. A tool that confidently misreads tone is worse than no tool at all, so Tempo never pretends to certainty it doesn't have. Point it at your own draft and it works in reverse: how will this land before you hit send.
Six modules, one working memory.
Triage
The SurfaceSorts everything since you were last active into Act / Blocker / FYI / Noise — including the blocker nobody @-mentioned you on, which Slack's unread badge structurally cannot find.
Commitment Ledger
The MemoryEvery promise you made and every promise made to you, with due dates, drift, and a draft to nudge or renegotiate before it becomes a dropped ball.
Tone Decoder
The TranslatorSeparates what a message literally says from what it means. Names the real urgency and the social expectation — with an honest confidence score and a caveat.
Focus Guardian
The ShieldBooks the block: real Do-Not-Disturb and a status your team can see, flipped on your own token — plus a calendar hold via outbound MCP (mock-backed here, and it says so on the card).
Re-entry
The BridgeThe calm brief you need after time off — what was decided, what changed, and who has been waiting on you the whole time.
Conversation
The DoorEverything that isn't a command still gets a real answer — and always an offer of something Tempo can actually do. Chat is a doorway into the product, not a dead end.
The agent stops talking and does something.
Ask for two hours and Tempo flips your real Do-Not-Disturb and sets a status your team can actually see — on your own token, as you. Most agents end at a nicely-worded suggestion. This one changes the state of your workspace.
And where it can't, it says so out loud. The calendar line below prints
(mock) on the real card, because we didn't stand up third-party OAuth we
couldn't test end to end.
The one place we take the AI out of the loop.
Tempo is built for people under strain — burnt out, overwhelmed, neurodivergent. Given that audience, someone will eventually type something that isn't about Slack at all.
In that moment, a generative model is exactly the wrong thing to have in the loop. It can improvise. It can minimise. It can hallucinate a helpline that doesn't exist. So the crisis check runs before any model call and returns fixed, hand-written words. No generation. No temperature. No surprises.
And this isn't a promise in a README. The test spies on the LLM port and fails if it is touched at all — not "prompted carefully". Never reached.
// converse.test.ts — the assertion this whole file exists for
expect(llm.structured).not.toHaveBeenCalled();
The card it shows carries no product buttons either. Nudging someone toward "want me to triage your inbox?" in that moment would be grotesque.
All three required technologies, live.
Real-Time Search API
assistant.search.context runs on the user's own token — so
Tempo sees exactly what you can see, and nothing else. It's the only way to ground on
the messages that never mentioned you, which is precisely where the blockers hide.
What it reads is never stored.
MCP — and Tempo is the server
Tempo isn't just an MCP client. It is a live MCP server at
/api/mcp/server, exposing tempo_triage,
tempo_commitments, tempo_decode and tempo_focus
to Agentforce, Claude or Cursor — behind signed per-user tokens and a default-deny
gate. Anyone can call an MCP server; few expose one.
# judges can run this right now
curl -sX POST https://tempo-slack.vercel.app/api/mcp/server \
-H "Authorization: Bearer $TEMPO_MCP_SERVER_TOKEN" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
The outbound MCP clients (calendar, tasks) are built against the same port and fully tested, but ship mock-backed — we didn't stand up third-party OAuth we couldn't test end to end, and we'd rather say so than pretend.
Slack AI & agent surfaces
The Agent pane (agent_view) with suggested prompts, a live App Home
dashboard, Block Kit actions and an accessibility settings modal, four Workflow
Builder steps, Tempo Canvas, and Slack Lists.
Ports and adapters, all the way down.
The domain modules import no SDKs — they depend only on ports. So every external system has a mock and a live adapter, and the entire product runs with zero credentials. That's not a demo mode bolted on; it's the same code path, and it's the CI smoke test.
Surfaces
- SlackAgent pane, App Home, Block Kit, slash commands, Workflow steps
- WebPrivacy dashboard, settings, export & delete
- MCP serverExternal agents call in — default-deny
- CronThe morning digest
Application core
- TriageRanks, caps, explains
- LedgerPromises made and owed
- DecoderLiteral vs. implied
- Focus · Re-entry · ConversePure domain logic. No SDK imports. Ever.
Ports → adapters
- Searchmock · Slack Real-Time Search
- LLMmock · OpenAI
- Actionsmock · Slack Web API (DND, status)
- Storemock · Neon Postgres, encrypted tokens only
- Calendar · Tasksmock · outbound MCP (mock-backed today)
Open the full architecture diagram — every entrypoint, port and adapter, generated from source.
Judges deserve to know exactly where the line is.
Live and real
- RTS grounding on the user's own token
- Slack AI & agent surfaces
- The inbound MCP server — call it yourself
- Real DND + status flips
- Neon Postgres, encrypted tokens
- The Vercel cron digest
Built, tested, mock-backed
-
The outbound MCP calendar and task clients. Same port, fully exercised — we
chose not to stand up third-party OAuth we couldn't test end to end under the
deadline. The focus card literally prints
(mock). - Focus is hardened so that on the day a real MCP server is connected and goes down, the DND still lands.
Off by default, by design
- The team/manager view and the multi-source "Attention OS" (email, calendar).
- Their sources are mock-only, behind a flag that ships off. The seam is real, the integration is not, and we will not call it one.
Privacy is architectural, not a promise.
Tempo acts as you, on data you already have permission to see. It stores your encrypted token, your preferences, the facts of your commitments, and counts-only metrics. It never persists a single message it reads — enforced at the schema level and guarded by tests, not just asserted on a landing page.
You can narrow it further: only watch these channels, never track these people. That consent holds on every surface — the app, the scheduled digest, and the MCP server all go through the same code path, so an external agent can't read around it.
Curb cuts were built for wheelchairs.
They're used by everyone with a suitcase. Calm, ranked, plain-language communication is universal design — and the person who benefits from being told "three things need you, and Priya has been blocked on you since Tuesday" is, on a bad week, all of us.