Durable Brief is a small Temporal project that runs a daily AI briefing pipeline with durable execution. It fetches data from external sources, generates a summary with an LLM, and delivers the result to Telegram.
The Workflow orchestrates each external step as a Temporal Activity so the full run is reliable and repeatable.
- Fetches Google Calendar data
- Fetches Gmail data
- Fetches USPS Informed Delivery scans
- Uses local Tesseract OCR to extract sender text from mail images
- Generates a morning brief with an LLM
- Sends the final brief to Telegram
This is the default execution flow and retry profile used by morningBriefWorkflow.
morningBriefWorkflow
├── fetchCalendar() — 30s timeout, 3 retries ┐
├── fetchEmails() — 30s timeout, 3 retries ├── parallel
├── fetchUSPSMailScans() — 45s timeout, 3 retries ┘
├── generateBrief(data) — 60s timeout, 3 retries
└── sendToTelegram(brief) — 15s timeout, 5 retries
The project is intentionally small: one Workflow, a set of Activities, one Worker, and one trigger script.
src/
├── activities.ts # Activity implementations (Google API via gog CLI, Tesseract OCR, LLM, Telegram)
├── workflows.ts # morningBriefWorkflow orchestration
├── worker.ts # Temporal Worker process
└── trigger.ts # CLI script to start a Workflow and print the result
Use the steps below to install dependencies, configure credentials, and run the Workflow locally.
Install these tools first. Durable Brief depends on them at runtime for Workflow execution, data collection, and OCR.
- Node.js 22 or newer
- Temporal CLI (for local dev server):
curl -sSf https://temporal.download/cli | sh - gog CLI installed and authenticated (for Google Calendar and Gmail access)
- Tesseract OCR installed (
brew install tesseractorsudo apt install tesseract-ocr)
Clone the repository, install packages, and build the TypeScript project.
git clone https://github.com/lenny/durableclaw.git
cd durableclaw
npm install
npm run buildCreate a local environment file and then set the required credentials and optional binary paths.
cp .env.example .env
# Edit .env with your valuesThe following environment variables control model access, delivery, and local binary paths.
| Variable | Description |
|---|---|
LLM_API_KEY |
API key for your LLM provider |
LLM_BASE_URL |
OpenAI-compatible completions endpoint (default: Venice AI) |
LLM_MODEL |
Model name (default: llama-3.3-70b) |
TELEGRAM_BOT_TOKEN |
Telegram bot token used for message delivery |
TELEGRAM_CHAT_ID |
Telegram chat ID that receives briefs |
GOG_PATH |
Path to the gog binary (default: /usr/local/bin/gog) |
TESSERACT_PATH |
Path to the tesseract binary (default: /usr/bin/tesseract) |
Run these commands in separate terminals: start Temporal, start the Worker, then trigger a Workflow Execution.
- Start the Temporal dev server.
temporal server start-dev- Start the Worker.
npm start- Trigger a Workflow.
npm run triggerIf you want this to run continuously on Linux, use the provided systemd unit files and adjust paths for your system.
The included temporal-dev.service binds the Temporal UI to 0.0.0.0, so it is reachable from other devices on your home network. This is convenient for local monitoring, but use it with caution and only on trusted networks.
sudo cp services/*.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now temporal-dev durableclaw-workerYou can reuse this pattern for any multi-step agent pipeline that calls external APIs or services.
- Model each external call as an Activity with timeout and retry settings.
- Run independent calls in parallel with
Promise.all. - Keep orchestration logic in the Workflow and side effects in Activities.
- Trigger the Workflow from your existing scheduler or agent framework.