Personal Assistant Scheduled Automation Event Automation Workflow Agent Runtime Notification Knowledge Base

Morning Notion Task Digest to Telegram

A personal assistant recipe where Notion rules define scheduled and event-driven jobs, Upstash runs the orchestration, and Telegram receives the morning report.

Notion Telegram Bot API Upstash | QStash Upstash | Workflow Upstash | Redis Upstash | Search Upstash | Box

What This Builds

This recipe builds a small personal automation system. Notion is the human-editable source of truth for rules, tasks, and inbox items. Upstash holds the runtime registry and executes scheduled or event-driven work. Telegram receives morning summaries and follow-up notifications.

The first useful behavior is simple: every morning at 09:00, the system reads today’s Notion tasks, prepares a short digest, writes the digest to a Notion inbox, and sends the same summary to Telegram.

Product Shape

This is an assistant system, not just a cron job. The scheduled worker can be lightweight, but the output lands in a shared inbox that the main assistant can read later. If the user continues the conversation in Telegram, the assistant can use the same Notion inbox, task database, rule database, Redis registry, and optional Search index as context.

Architecture

flowchart TD
  NotionRules["Notion: Automation Rules"] --> SyncHook["Rule sync webhook"]
  SyncHook --> Redis["Upstash | Redis runtime registry"]
  Redis --> QStash["Upstash | QStash schedules"]
  Redis --> EventRouter["Event router"]

  QStash --> MorningWorkflow["Upstash | Workflow: morning digest"]
  NotionEvents["Notion task/page events"] --> EventRouter
  EventRouter --> MorningWorkflow
  EventRouter --> HeavyAgent["Upstash | Box: heavy agent run"]

  MorningWorkflow --> NotionTasks["Notion: Tasks DB"]
  MorningWorkflow --> Search["Upstash | Search indexed context"]
  MorningWorkflow --> Inbox["Notion: Assistant Inbox"]
  MorningWorkflow --> Telegram["Telegram Bot API"]

  HeavyAgent --> Inbox
  HeavyAgent --> Telegram

Components

Notion

Use Notion as the source of truth for human-editable state:

  • Automation Rules database: enabled rules, cron expressions, event filters, target executor, prompt, and runtime status.
  • Tasks database: the real task source for morning digests and status-change reactions.
  • Assistant Inbox database: generated summaries, pending suggestions, and notifications that the assistant can read later.
  • Runs database: execution logs, last success, errors, and links to generated inbox items.

Upstash | Redis

Use Redis for runtime state that should not require re-reading Notion on every tick:

  • rule:{id} stores the normalized rule payload.
  • schedule:{rule_id} maps a Notion rule to the provider schedule id.
  • snapshot:{page_id} stores the last known Notion task status for event matching.
  • lock:{rule_id} prevents duplicate runs.
  • run:{run_id} stores short-lived execution state.

Upstash | QStash

Use QStash for real schedules and HTTP delivery. When a Notion schedule rule is created or changed, the sync webhook creates, updates, pauses, or deletes the matching QStash schedule. QStash then fires independently. It should not poll Notion every minute to discover due jobs.

Upstash | Workflow

Use Workflow for light durable work:

  1. Load the normalized rule from Redis.
  2. Fetch tasks from Notion.
  3. Optionally query Upstash | Search for relevant context.
  4. Call a small LLM prompt or lightweight assistant handler.
  5. Write a Notion inbox item.
  6. Send a Telegram message.
  7. Write a run log.

Use Search for indexed context, not as the source of truth. A sync job can upsert selected Notion pages, inbox entries, project notes, and rule descriptions into Search. The assistant then asks Search for relevant context instead of scanning everything.

Upstash | Box

Use Box only for heavy work: coding-agent loops, shell access, git operations, Playwright, filesystem-heavy jobs, or custom agent harnesses. Most morning digest jobs should stay in Workflow. If a rule says executor = heavy-agent, the router can wake a Box and run a prompt or command.

Telegram

Telegram is the notification and continuation surface. The morning digest message should include enough context to act immediately, plus stable links back to Notion inbox items. Follow-up messages can be routed to the main assistant, which reads the same inbox and Search context.

Rule Examples

Daily Morning Digest

name: Morning task digest
enabled: true
trigger:
  type: schedule
  cron: "0 9 * * *"
  timezone: "Asia/Ho_Chi_Minh"
executor:
  type: workflow
  handler: morning-task-digest
inputs:
  taskDatabase: notion_tasks
  inboxDatabase: assistant_inbox
  telegramChat: personal

Task Ready For Review

name: Review task when status changes
enabled: true
trigger:
  type: notion-event
  database: notion_tasks
  when:
    property: Status
    from: In Progress
    to: Ready for Review
executor:
  type: heavy-agent
  box: personal-assistant
  prompt: "Review the task, inspect linked context, and write a concise review note."
outputs:
  inbox: true
  telegram: true

Why This Shape Works

The important boundary is that Notion remains the place where the user edits rules, but runtime execution is not based on constant Notion polling. Rule changes are synced into QStash schedules, Redis registry records, and event-router indexes. Scheduled jobs then run from the scheduler. Event jobs run from webhook signals and compare against stored snapshots only when a relevant Notion event arrives.

Minimal Prototype

Start with four pieces:

  1. A Notion Automation Rules database with one daily digest rule.
  2. A tiny webhook/sync endpoint that registers the QStash schedule and stores the normalized rule in Redis.
  3. One Upstash Workflow endpoint that reads Notion tasks, writes an inbox item, and sends Telegram.
  4. A Telegram bot token and chat id.

Add Upstash | Search after the first digest works. Add Upstash | Box only when the task requires a real agent runtime rather than a simple workflow.