Slack Deep Research — AGNT5 Template
A Slack bot that researches a question in the thread it was asked in. It posts a research plan with Approve and Reject buttons first, and only researches after someone approves.
What it does
- Claim — The bot posts "Planning research…" to the thread, tagged with Slack's
event_id. A second delivery of the same Slack event finds the tag and stops. - Plan — A scoping agent turns the question into subtopics. The bot edits its message into the plan with Approve and Reject buttons.
- Approve — The workflow pauses on
ctx.wait_for_user(). A button click reaches the same AGNT5 integration, and the workflow resumes the paused run through AGNT5's resume API. - Research — A research agent searches Wikipedia and reads the most relevant pages.
- Report — A writing agent writes a Slack-formatted report, and the bot posts it to the thread once.
Key concepts
- Human-in-the-loop —
ctx.wait_for_user()pauses the run until the plan is approved or rejected. - Recorded steps — Each stage is a
ctx.step. Completed steps are restored instead of running again, for example when the run resumes after the click. A step that was interrupted may run again. - Posting once — Slack's
chat.postMessagehas no idempotency key and AGNT5 doesn't deduplicate Slack retries, so every bot message carries Slack message metadata and the bot reads the thread before it posts (slack_once.py).
Setup
Install uv (Python package manager):
curl -LsSf https://astral.sh/uv/install.sh | shCreate the project from this template:
agnt5 create --template python/slack_deep_research my-research-bot cd my-research-botInstall dependencies:
uv syncCopy
.env.exampleto.envand fill inOPENAI_API_KEYandAPPROVAL_SERVICE_KEY. Create the service key with:agnt5 service-keys create --name slack-approver --project <project-id> --scopes run,workflow
Run locally without Slack
agnt5 dev -d
agnt5 run workflow slack_deep_research --input '{"body":{"event":{"type":"app_mention","text":"<@U0BOT> compare Raft and Paxos: leader election, and which systems use each","channel":"C0TEST","ts":"1"}}}'
The run plans, then pauses. Approve it the way the button does:
curl -X POST "https://gw.agnt5.com/v1/workflows/resume/<run-id>" \
-H "Content-Type: application/json" \
-H "X-API-KEY: $APPROVAL_SERVICE_KEY" \
-H "X-DEPLOYMENT-ID: $(cat .agnt5/dev-deployment-id)" \
-d '{"user_response": "approve"}'
The run continues and returns the full report. Nothing is posted to Slack locally.
Connect to Slack
- Add the keys as project secrets and deploy:
agnt5 secrets set --name OPENAI_API_KEY --type api_key agnt5 secrets set --name APPROVAL_SERVICE_KEY --type api_key agnt5 deploy --env production - Follow the Slack integration guide and choose:
- Bot token scopes:
app_mentions:read,chat:write,channels:history(andgroups:historyfor private channels) - Bot events:
app_mention - Interactivity: on, with the same Request URL as Event Subscriptions
- Target in Studio: your production deployment and the
slack_deep_researchworkflow
- Bot token scopes:
- Mention the bot in a channel it's in, and approve the plan it posts.
Tests
uv run --extra dev pytest
The tests run the post-once logic against a fake Slack.
See the Slack deep research cookbook for a walkthrough.