An AI data analyst in your Slack. Drop a data file, ask a question, get back an interactive HTML report with charts — all in the thread.
A Val Town port of Anthropic's Slack data-analyst-bot cookbook, powered by Claude Managed Agents.
- Responds to
@mentionsin channels and to DMs, with full thread context across follow-ups - Reads CSV, Excel, Word, PowerPoint, PDF, JSON, TSV, Parquet, and more — and can produce reports in any of those same formats
- Interactive HTML reports with embedded Plotly charts, hosted at a permanent Val Town URL and uploaded as a Slack thread attachment
- Long-running session memory — pick up a Slack thread days later and the bot still remembers the conversation and the file you uploaded
- One-click Slack app setup — no manual scope or event configuration
- Easily extensible: swap the model, add skills, change the system prompt
- Click Remix to get your own copy of this val.
- Open your val's HTTP endpoint in a new tab (you'll see the URL in the header of your remixed val), then click Create Slack App. The app manifest — scopes, events, and webhook URL — is pre-filled, so just click Next → pick workspace → Create.
- Install to Workspace in the Slack app's Install App tab.
- Paste 3 secrets into your val's
environment variables
(the slots are already created — just fill the values):
SLACK_BOT_TOKEN— Slack app → OAuth & Permissions → Bot User OAuth Token (xoxb-…)SLACK_SIGNING_SECRET— Slack app → Basic Information → Signing SecretANTHROPIC_API_KEY— from the Claude console (Managed Agents beta access required)
- DM the bot — open a DM, attach a data file with a question. No
@-mentionneeded; just send. @mentionin a channel — the bot replies in a thread on your message. Follow-ups in that thread don't need a new file or another@-mention— the same Anthropic session continues.
⚠️ Invite the bot to the channel first (
/invite @Junior Analyst). Without channel membership, the bot receives the mention event but can't read attached files.
The bot accepts any file you drop in Slack and produces any format the Anthropic skills support — the same file types work in both directions (you can upload an Excel file or ask the bot to produce one; same for Word, PowerPoint, PDF, etc.).
| Format | Extension | Handled by |
|---|---|---|
| CSV | .csv | pandas.read_csv |
| TSV | .tsv | pandas.read_csv with separator |
| JSON | .json | pandas.read_json |
| Excel | .xlsx | xlsx skill + openpyxl |
| Word | .docx | docx skill + python-docx |
| PowerPoint | .pptx | pptx skill + python-pptx |
.pdf | pdf skill + pdfplumber (tables) / pypdf (text) | |
| Plain text / Markdown | .txt, .md | direct read |
| Code or log files | .py, .log, .yaml, etc. | direct read |
| Parquet | .parquet | pandas.read_parquet — installs pyarrow on first use (~5–10s) |
| Legacy Excel | .xls | pandas.read_excel — installs xlrd on first use |
Not supported: images, audio, video.
Every file the agent writes to /mnt/session/outputs/ is uploaded as a Slack
file attachment and stashed in Val Town blob storage with a hosted URL
({val}/reports/{uuid}) so recipients can open it in a browser, share the link
externally, or preview HTML / Plotly charts natively.
| Format | When you get it |
|---|---|
report.html | Default for data-file analysis — interactive Plotly charts + narrative summary |
.md | Ask for "a markdown summary" or "a brief" |
.docx | Ask for "a Word doc" — uses the docx skill |
.xlsx | Ask for "an Excel workbook" — uses the xlsx skill |
.pptx | Ask for "a slide deck" or "a 5-slide presentation" — uses the pptx skill |
.pdf | Ask for "a PDF report" — uses the pdf skill |
.csv / .json | Ask for "the cleaned dataset" or "raw data as CSV" |
The bot can produce any of these from scratch without an input file too —
e.g., @Junior Analyst build me a 5-slide deck on coffee brewing temperatures
works without uploading anything.
data-analyst-slackbot/
├── main.ts # HTTP entry point: setup page + /events + /process
├── setup.tsx # JSX setup page (Twind for styling)
├── prompt.md # System prompt for the agent
├── sales.csv # Bundled sample dataset for testing
├── README.md
└── lib/
├── flow.ts # Orchestrator: route inbound messages to new / existing sessions
├── session.ts # Anthropic agent + environment, cached in blob
├── stream.ts # Lossless-reconnect SSE consumer; posts progress + summary to Slack
├── outputs.ts # Pull agent-generated files; upload to Slack with hosted URL
├── thread-sessions.ts # Per-val SQLite map of thread_ts → session_id
└── slack-utils.ts # Slack web client, signature verification, file download
Slack POSTs events to /events. The handler verifies the signature, then
dispatches the heavy work to /process as a separate HTTP request — Val Town
kills detached promises after the response is sent, so the
early-return pattern gives the
real handler its own full execution lifecycle.
- Edit the system prompt →
prompt.md. BumpSIGNATUREinlib/session.tsto invalidate the cached agent so the next message rebuilds with the new prompt. - Add or remove Anthropic skills (xlsx, docx, pdf, pptx) →
skillsarray inlib/session.ts. - Change the model →
MODELconstant inlib/session.ts. - Add pip packages to the sandbox →
piplist inlib/session.ts. - Tune progress messages ("On it.", "Running analysis.") →
lib/flow.tsandlib/stream.ts. - Change Slack scopes, events, or app metadata → the
manifestobject at the top ofmain.ts. Re-create the Slack app from the updated setup page.
- Long sessions can outlast a Val Town request. The lossless-reconnect
pattern in
lib/stream.tshandles SSE drops within a single/processcall, but if/processitself dies (Val Town's request-lifetime cap), the Anthropic session continues on Anthropic's side and your thread goes silent. A future addition: a cron val that scansthread_sessionsfor running-but-orphaned sessions and re-attaches. - Hosted reports don't expire. Every report is stored in blob storage indefinitely under a UUID. Add a cleanup cron if you want them to expire after N days.
- Cookbook is
app_mention+ DM only. Channel follow-ups still need an@-mention. Listening tomessage.channelswould let follow-ups continue without re-mentioning, at the cost of every channel message hitting the bot.
Pinned imports to avoid breaking changes:
@anthropic-ai/sdk@0.96.0@slack/web-api@7.14.1hono@4.12.0
Based on Anthropic's
Slack data-analyst-bot cookbook
and the
Val Town templates/ai-slackbot
chassis (one-click Slack setup, /events → /process early-return pattern).