Repository navigation
Proactive reminders 3/3: 24/7 runtime and Slack/email delivery #355
Copy link
Copy link
Closed
Labels
area:automationScheduled tasks and automationScheduled tasks and automationenhancementNew feature or requestNew feature or request
Description
Why
Proactivity only counts if it works when the laptop is closed. Phase 3 makes reminders and schedules run 24/7 and reach the user outside the app.
Part of the 3-phase proactive-reminders track. Depends on phase 1 (event reminders), phase 2 (schedules) and #352 (isolated per-person deployment). Related: #349.
Scope
- 24/7 runtime: the deployed instance (Deployment step 1: official image and one isolated instance per person #352) runs schedules and event watchers continuously; reminders keep firing while the desktop app is closed.
- External channels: deliver reminders via Slack and email first (user opts in per channel), with a link back to the card or conversation.
- Reply path: approving from an external channel is allowed only through a verified, expiring link or an authenticated reply; never by an unauthenticated message.
- Reliability: at-least-once delivery with deduplication, retries with backoff, a visible delivery log, and an alert when the runtime itself is down.
- Resource limits: per-instance and per-task caps on loops, concurrency and cost ([Team] Bound agent loops and resource consumption #56) so one runaway Bot cannot flood the user.
- Privacy: external messages carry the minimum content; sensitive detail stays in the app.
- Personal vs team: team reminders go only to people with grants ([Team] Gate cross-owner agent routes by per-Bot grants (default deny; superseded the publication gate) #51); managers can see "assigned tasks stuck" for tasks they delegated; all sends are audited ([Team] Add a human-readable authorization and task audit trail #57).
Acceptance
- With the desktop app closed, a schedule fires and a reminder arrives in the opted-in channel within the expected window.
- Restarting or upgrading the instance does not lose or duplicate reminders.
- An external approval link works once, expires, and is rejected for the wrong user.
- Turning a channel off stops delivery immediately.
Open questions (decided 2026-10-21 by the Chief)
- Channel first: Slack. Email follows once the owner has supplied a credential. No real transport ships without one.
- Timezones: provisional — a reminder is rendered in the recipient's own local time; a team reminder fires on the instance's timezone. 暂定、可改 (changeable without reopening the design).
- Escalation when ignored: provisional — remind the same person once after the window, then let the assigner see it in their inbox; at most two sends per reminder. 暂定、可改.
Process (2026-10-21)
First half only: a delivery adapter with Slack's shape and a replaceable transport, tested against a fake Slack; the real Slack/email transport waits for a credential from the user (spec in the triage comment of 2026-10-21). Implemented by an agent and reviewed per .github/agent/review-policy.json. The earlier line about cloud OpenCode/Codex and "bots do not hand-write code" is void; it predates the owner decision of 2026-10-19.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area:automationScheduled tasks and automationScheduled tasks and automationenhancementNew feature or requestNew feature or request
Activity
Birfy commentedon Oct 19, 2026
Triage on main
7b9e90b, 2026-10-19 ~12:10 Asia/Shanghai: needs-human, not agent-ready. Depends on #352 (deployment) and #353/#354; external delivery (Slack/email) also needs a decision on which connector and whose credentials.Birfy commentedon Oct 20, 2026
Triage (maintenance, 2026-10-20 08:04 Asia/Shanghai)
Checked on main
a45fc8c. No container image or headless runtime on main yet. #352 is still open and needs-human, so the 24/7 part cannot start. External delivery could use the owner's existing Composio connector (Gmail / Slack) incore/src/host/connectors.js.Conflict with the owner's rules (fixed in this triage)
The body allows approving "through a verified, expiring link or an authenticated reply". Approvals are given only with explicit UI buttons, never with a typed reply. So:
Expected behavior
With your opt-in, a reminder from #353/#354 also reaches you outside the app as a short line (who, why) plus a link back. It never carries the content of the chat or the tool call.
First slice (smallest shippable step, after #352 step 1)
Details I decided (say if you disagree)
Question for the owner
(a) Keep #355 parked until #352 step 1 ships, then start with email to yourself; (b) start now from the running desktop app (works only while it is open), 24/7 later; or (c) like (a), but Slack DM to yourself first.
Recommendation: (a).
Birfy commentedon Oct 20, 2026
Owner decision (2026-10-20): Confirmed option (a): wait for #352 (official image / one instance per person), then first send email-to-self. Off-app messages only carry a link back into the app — never approve by replying to the message.
Birfy commentedon Oct 20, 2026
Not started in this run (2026-10-20 08:55 Asia/Shanghai): per the Owner decision, this waits for #352 (official image / one instance per person), which is still open.
Birfy commentedon Oct 20, 2026
Claimed by maintenance run (2026-10-20 11:55 Asia/Shanghai, main
a7adfe0): developing on branchfeat/355-email-to-selfin Birfy/FlyBot, following the Owner decision above (first slice only).Birfy commentedon Oct 20, 2026
Email to yourself, first slice: details I decided (2026-10-20 12:05 Asia/Shanghai, PR #493)
Following the Owner decision (a). #352 is merged.
Coder finished,Coder failed: <reason>,Coder is waiting for your approval, plus the group name) and a link back into FlyBot. It never includes chat text, tool names or arguments. It ends with "Approve or reject only in FlyBot. Replies to this email are not read." No email can approve anything.docs/docker.md): you use your own mail account's SMTP server, so there is no third-party service and no relay we run.FLYBOT_SMTP_URL:smtps://means TLS on port 465;smtp://host:587means STARTTLS.FLYBOT_EMAIL_TO: the only recipient.FLYBOT_URL: the link in the email. Defaulthttp://127.0.0.1:3080/, which matches the SSH-tunnel setup in the guide.compose.yamlpasses all three through only when they are set. Any malformed value means no email is sent.SMTP_535,SMTP_TIMEOUT, …), never the server's text. The UI shows only the recipient address.node:net/node:tls).Merge origin/main into feat/355-email-to-self
14 remaining items
Birfy commentedon Oct 22, 2026
Claimed by Dev4 (2026-10-22): branch
feat/355-slack-delivery-adapter, first half only per the spec of record (comment 6313181873) — a transport-agnostic delivery adapter with Slackchat.postMessageshape, a fake Slack transport for tests, at-least-once with a per-reminder idempotency key, backoff that honoursRetry-After, 3 attempts max, a permanent failure not retried. Real Slack/email transport, 24/7 runtime and external approval links stay out.fix(notify): retry the transient Slack codes instead of giving up on …
Add a Slack-shaped delivery adapter with retry and dedupe (#355)
Map user journeys to their current coverage (ThinkFlowLab#358) (Think…
Add a Slack-shaped delivery adapter with retry and dedupe (ThinkFlowL…