StandupLine is a voice-first async standup system for teams.
Team members submit standups through an ElevenLabs conversational agent or the built-in web widget. The app stores the transcript, extracts yesterday / today / blockers with Workers AI, and gives the manager a clean dashboard plus a daily Telegram brief. It also includes a Cloudflare Agent so the team coordination state lives inside the app, while ElevenLabs handles the voice runtime.
- Creates and manages teams, members, call logs, standups, and task assignments
- Receives post-call webhooks from ElevenLabs conversational agents
- Extracts structured standup data with Cloudflare Workers AI
- Generates audio briefs with ElevenLabs Text to Speech
- Stores audio files in Cloudflare R2
- Sends the final brief and reminders through Telegram
- Lets you provision or link an ElevenLabs agent from the app UI
- Uses a Cloudflare Agent to track per-team coordination state
Employee / Manager
|
v
ElevenLabs Conversational Agent
|
v
Cloudflare Worker (Hono)
|
+--> Durable Object SQLite per team
+--> Cloudflare Agent state sync
+--> Workers AI extraction
+--> R2 audio storage
+--> Telegram delivery
- Cloudflare Workers
- Cloudflare Durable Objects with SQLite
- Cloudflare Agents SDK
- Cloudflare Workers AI
- Cloudflare R2
- ElevenLabs Conversational AI
- ElevenLabs Text to Speech
- Telegram Bot API
- Hono
- Tailwind CDN + static dashboard pages
Before running the app, you need:
- A Cloudflare account with Workers initialized
- A Cloudflare API token or
wrangler login - An ElevenLabs API key
- A Telegram bot token
- An R2 bucket named
standupline-audio
Recommended Cloudflare token permissions:
Workers Scripts: EditWorkers R2 Storage: EditWorkers AI: Edit
Recommended ElevenLabs key permissions:
Text to Speech: AccessElevenAgents: WriteUser: ReadVoices: Readoptional
npm installEither log in interactively:
npx wrangler loginOr export your Cloudflare API token:
export CLOUDFLARE_API_TOKEN='your_token_here'npx wrangler r2 bucket create standupline-audioCreate a .dev.vars file locally:
ELEVENLABS_API_KEY=your_elevenlabs_key
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
DEFAULT_TEAM_ID=defaultThis file is ignored by git.
npm run devWhen Wrangler starts, open:
http://localhost:8788/http://localhost:8788/setup
Open /setup and create a team with:
- team name
- timezone
- brief time
- manager Telegram chat ID
Add the employees and manager with:
- name
- phone number
- role
- optional Telegram chat ID
In the ElevenLabs Voice Agent section of /setup, you can:
- create an ElevenLabs agent from the app
- or link an existing
agent_id
You will also see the webhook URL the ElevenLabs side should call.
For MVP, use ElevenLabs Conversational AI runtime.
Inside ElevenLabs:
- Create an agent
- Use a standup prompt
- Enable post-call webhooks
- Point the webhook to:
https://YOUR-WORKER.workers.dev/webhook/elevenlabs/YOUR_TEAM_ID
If you already imported a phone number into ElevenLabs, assign it from the app UI.
Create a bot with BotFather and get the bot token.
To find your manager chat ID:
- Message your bot once
- Open:
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates
- Copy
message.chat.id
That numeric chat_id is what the app needs, not the Telegram username.
Set Worker secrets in Cloudflare:
npx wrangler secret put ELEVENLABS_API_KEY
npx wrangler secret put TELEGRAM_BOT_TOKENThen deploy:
npm run deployGET /GET /setupGET /call-logGET /standupsGET /widget/:teamId
POST /api/:teamId/initGET /api/:teamId/teamPOST /api/:teamId/membersGET /api/:teamId/membersDELETE /api/:teamId/members/:idGET /api/:teamId/call-logsGET /api/:teamId/standups/:dateGET /api/:teamId/tasksGET /api/:teamId/stats
POST /api/:teamId/elevenlabs/setupPOST /api/:teamId/elevenlabs/provisionGET /api/:teamId/elevenlabs/configGET /api/:teamId/elevenlabs/agentsGET /api/:teamId/elevenlabs/phone-numbersPOST /api/:teamId/elevenlabs/phone-number/assignPOST /api/:teamId/elevenlabs/speak
POST /webhook/elevenlabs/:teamId
POST /api/:teamId/telegram/brief
npm run dev
npm run typecheck
npm test
npm run deploy.dev.varsis local-only and should never be committed.wrangler/is local-only and ignorednode_modules/is ignored- Exposed keys or tokens should be rotated if they were ever shared publicly
If you want to build your own version:
- fork this repo
- plug in your Cloudflare, ElevenLabs, and Telegram credentials
- update the team and delivery logic to match your workflow
- deploy your Worker and point ElevenLabs webhooks at it
That is enough to get a working async voice standup system running quickly.