Inspiration
Every team runs on rituals — the Monday pipeline review, the sprint summary, the on-call report. Each one lives or dies on someone remembering to run it, so the numbers go stale and the ritual quietly dies. Slack can already schedule recurring prompts — but the standard approach re-runs the model every single time, paying inference again and hoping the answer comes out the same shape. We wanted scheduled AI that doesn't re-run AI: ask once, and it posts forever — deterministically, and governed.
What it does
Relay turns any question you ask in Slack into a standing, scheduled digest. @-mention it and it answers with live data pulled over MCP, with a chart rendered right into the message. Reply "schedule this every weekday at 9" and that exact answer becomes a recurring digest — same shape, fresh data, no human required.
- Zero-inference fire. At fire time there is no LLM call at all. The frozen view re-renders against live data. Spend tokens once, when you ask; every fire after that is fast, identical, and free.
- Each channel is its own agent — its own model, tools, and admin-sanctioned
MCP servers.
#salesruns Salesforce;#prod-enggruns Linear + PostHog. - One governance boundary. Sensitive actions pause at the gateway and route to a policy-designated owner who is not the person who asked.
- Silent until it matters. A compiled CEL condition can keep a digest quiet for weeks and speak only when something's worth saying ("post only if pipeline drops more than 10%").
Itinerary Tracking — scheduled AI that doesn't re-run AI
When you say "schedule this," Relay freezes the shape of the answer already in front of you into a deterministic template. At fire time only the data leg re-runs: live MCP tool calls fetch fresh numbers that re-render into the frozen shape. The authoring conversation costs its tokens once; every fire after that runs no model and costs zero tokens.
- No drift — week 12 has the same structure as week 1.
- No hallucination surface — there's no model between your data and your channel at fire time.
- Marginal cost of zero — a digest that fires 52×/year costs one authoring conversation, not 52 inference calls.
A fidelity gate protects the freeze: if an answer's shape can't be captured losslessly, Relay says so at scheduling time and routes that digest to an agentic tier instead — it never silently degrades your post.
MCP end to end
The chart in every digest isn't an LLM-generated image or a hand-built integration — it's a real MCP App (SEP-1865) tool view, rendered server-side into a Slack-native image at fire time. The data arrives over MCP tool calls and the pixels come from an MCP App view. Remove MCP and there's no product.
Agent identity via attribute-based access control
Relay binds MCP at the channel, not the workspace — each channel with its own servers, per-tool allowlist, model, and credentials, on top of each user's own identity. Whether a server is one we host or a vendor's official one, the same policy governs it. The channel itself becomes an attribute policies scope on: agent identity, built with ABAC.
How we built it
Slack app (Block Kit, modals, native streaming API, MCP Apps tool views) → Ferentin governed agent runtime (Java 25 / Spring WebFlux, reactive end to end) → MCP gateway (Streamable HTTP, per-user OAuth token exchange) → digest scheduler (frozen templated tier with fidelity gate, agentic fallback tier, CEL condition evaluation) → server-side MCP App renderer for the chart images. Governance — per-user identity, DLP on every output, full audit trail, gateway-level approval — runs across all of it.
Challenges we ran into
- Slack's chat-streaming API docs lag its behavior. In timeline mode, content chunks are silently dropped, so the final reply had to be delivered via a separate update after the stream freezes — found only by probing a live workspace.
- Freezing an answer losslessly. Not every answer's shape survives into a deterministic template, so we built the fidelity gate to route un-freezable digests to an agentic tier instead of degrading silently.
- Rendering an interactive MCP App view as a reliable Slack image (settled- event → capture), theme-aware and non-flaky.
- Per-channel governance + per-user OAuth identity + separation-of-duties approval at a single gateway boundary.
What we learned
- MCP can carry both data and UI — treating the chart as an MCP artifact rather than a bespoke integration made it portable and governed for free.
- The cheapest and most trustworthy scheduled agent is one that doesn't call a model at fire time.
- Governance — identity, DLP, audit, and approvals where the asker can't approve their own action — is what makes an unattended agent posting into a channel safe to run.
What's next
Editing the frozen shape before confirming, more condition templates, and scheduled digests that trigger approved actions — not just reports — so a standing watchdog can propose a fix and route it to the right owner the moment a threshold trips.
Built With
- block-kit
- cel
- docker
- java
- mcp
- mcp-apps
- model-context-protocol
- oauth2
- openai
- postgresql
- project-reactor
- r2dbc
- redis
- server-sent-events
- slack
- slack-api
- spring-boot
- spring-webflux
- streamable-http
Log in or sign up for Devpost to join the conversation.