Skip to content

Repository files navigation

daimon, a small blue clay creature in a lab coat, presenting charts at a whiteboard

daimon

Your team just hired a data scientist.

daimon is a collaborative data science agent in your team's Discord or Slack. It writes and runs code, fits Bayesian models with PyMC, and delivers charts and runnable notebooks in the thread.

CI License: MIT Python 3.12+

Add it to your server in one click → or self-host it from this repo.

It's yours. And it's open.

Most chat bots are one agent shared across a workspace. daimon is many-to-many: you deploy it once, on your own Anthropic API key, and any number of Discord servers install it from that single deployment. Every server is isolated: one tenant, its own data, scoped to that server. Adding a server takes about two minutes: invite the bot, @mention it, and it sets itself up. From there, everyone in the server can just ask it for things.

Built on Anthropic Managed Agents by PyMC Labs, the team behind the PyMC project.

Status: early. Self-hosting works and is documented below — expect rough edges and breaking changes while things settle. The hosted version at daimon.decision.ai is the zero-setup path.

It doesn't chat. It does the work.

ChatGPT analyzes your data for you, alone, in a tab. daimon does it with your whole team, in the thread — and hands back a notebook anyone can run.

  • @daimon in a channel starts (or continues) a threaded conversation with session continuity
  • Everything happens in conversation — setup, scheduling, billing: @mention the bot and ask. Slash commands (/agent-setup, /routines, /billing, /privacy, /help) still exist if you prefer them; setup and routines require Discord's Manage Server permission
  • Scheduled routines: recurring agent runs dispatched headlessly
  • Slack adapter (early, not yet as battle-tested as Discord) with per-workspace OAuth install and opt-in per-user access (docs/slack.md)
  • CLI and MCP adapters sharing the same core turn pipeline
  • Tenant isolation enforced at the database tenant_id layer, so one shared Anthropic key can safely power every guild

What you can ask it

"Here's last quarter's sales export — we changed pricing in week 6. Did it actually help?"

"Is variant B actually better than A, or is that just noise?"

"Forecast next month's signups, with uncertainty bands."

"Every Monday at 9am, pull the weekend's numbers and post a summary here."

Answers come back in the thread: a fitted model, a chart, a plain-English read on the uncertainty, and a runnable marimo notebook that reproduces the analysis.

How it works

flowchart LR
    a["your Discord server"] --> d
    b["another Discord server"] --> d
    c["a Slack workspace"] --> d
    d["daimon<br>one deployment, your Anthropic key"] --> e["Claude<br>(Anthropic Managed Agents)"]
Loading

You run one copy of daimon. Every community that installs it gets its own agent with its own memory, and none of them can see each other's data. When someone @mentions the bot, daimon hands the conversation to Claude and posts the replies back into the thread.

Technical architecture
flowchart LR
    subgraph adapters
        direction TB
        Discord
        Slack
        CLI
        MCP
        Scheduler
    end
    adapters --> core["daimon core<br>turn pipeline"]
    core <--> ma["Anthropic Managed Agents<br>agents &middot; sessions &middot; skills"]
    core --> pg[("Postgres<br>tenants &middot; thread&harr;session map")]
Loading

A turn: the adapter derives the tenant from platform identity, core opens or resumes a Managed Agents session, streams its events, and the adapter renders deltas into the thread until the session goes idle.

  • daimon.core owns schema, stores, and the turn pipeline, and imports no adapters. Each adapter owns one platform's I/O and auth, and adapters never import each other. import-linter enforces both rules in CI.
  • Managed Agents holds the agents, environments, sessions, and skills themselves. Postgres holds only metadata about them: tenant identity, thread-to-session mappings, config, credentials, and billing.
  • One Discord guild (or Slack workspace) is one tenant. Isolation lives at the database tenant_id layer, not the API-key boundary.

Run it yourself

You need an Anthropic API key in a workspace dedicated to this deployment (daimon manages the workspace's Managed Agents resources as its own, so sharing the workspace with anything else causes collisions) and Docker.

1. Configure environment

cp .env.example .env

Open .env, then uncomment and fill in:

  • DAIMON_ANTHROPIC__API_KEY: your Anthropic API key
  • DAIMON_MCP__JWT_SECRET: any random string (e.g. openssl rand -hex 32)
  • DAIMON_MCP__PUBLIC_URL: http://localhost:8765/mcp is fine for local use
  • POSTGRES_PASSWORD: a strong, URL-safe value (avoid @ : / % #)

All four must be set before your first docker compose command: docker-compose.yml interpolates them for every service with fail-fast ${VAR:?...} guards. You'll add the Discord bot token in step 2. .env is gitignored, so secrets never get committed.

2. Create the Discord application

  1. Create an application in the Discord Developer Portal.
  2. Under Bot, create a bot user and copy its token into .env as DAIMON_DISCORD__BOT_TOKEN.
  3. Still under Bot, enable the Message Content Intent. It's a privileged intent, and without the portal toggle the bot can't read mentions.
  4. Under OAuth2 → URL Generator, select the bot and applications.commands scopes, then under Bot Permissions select at least Send Messages, Send Messages in Threads, Create Public Threads, Manage Threads, and Read Message History.
  5. Open the generated URL in a browser and invite the bot to a test server you control.

3. Start the stack

docker compose up --build -d

One command brings up Postgres, runs migrations and seeds the default agents, environments, and skills (the init service does both automatically), then starts the mcp, discord, and scheduler services.

Once it settles, send a message that @mentions the bot. It replies in a new thread, and that's a working deployment. If the bot stays silent, check docker compose logs discord — an unset DAIMON_DISCORD__BOT_TOKEN is the usual cause.

Prefer to run the processes by hand?

Requires uv:

uv sync --all-extras --all-packages
docker compose up -d postgres
export DAIMON_DATABASE_URL=postgresql+asyncpg://daimon:<your-POSTGRES_PASSWORD>@localhost:5432/daimon
uv run alembic upgrade head
uv run daimon defaults apply
uv run python -m daimon.adapters.discord

The export is required because the alembic CLI reads the shell environment and does not auto-load .env.

Layout

  • packages/core/daimon-core library (MA client, stores, turn pipeline)
  • packages/adapters/cli/ — the daimon admin CLI
  • packages/adapters/discord/ — the Discord bot adapter
  • packages/adapters/mcp/ — the MCP server adapter
  • packages/adapters/slack/ — the Slack adapter (optional)
  • packages/adapters/scheduler/ — the routines scheduler adapter
  • packages/testing/ — shared test fixtures/harness
  • apps/notebook-host/ — standalone marimo notebook host service
  • defaults/ — YAML defaults seeded into Managed Agents + local DB
  • tests/ — cross-package integration tests

Contributing

See CONTRIBUTING.md for dev environment setup and the quality gates every PR must keep green.

Security

See SECURITY.md for how to report a vulnerability.

License

MIT

About

The open source data science agent for Discord and Slack

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages