Skip to main content

Agent mesh control plane — coordinate AI coding agents from a live dashboard

Project description

Drasill

Python License Coverage Ruff FastAPI HTMX

An agent mesh control plane and dashboard server for coordinating local Claude Code sessions. Agents register, discover each other, and exchange messages through Drasill — using heimdall stdin injection for message delivery.


Why "Drasill"?

In Norse mythology, Yggdrasill is the world tree — an immense ash that connects the nine realms, carrying messages between gods, humans, and the dead through its branches and roots. The squirrel Ratatoskr runs up and down its trunk delivering messages (and insults) between realms.

Drasill is your local world tree. It connects Claude Code agents running in separate terminals, letting them discover each other, exchange tasks, and coordinate work — all through a single trunk. Each agent is a Ratatoskr, checking in at the tree for new messages whenever it finishes its current task.

The name drops the "Ygg-" prefix (meaning "terrible" or "dreadful") because there's nothing terrible about well-coordinated agents.


What It Does

Agent Mesh

The mesh turns Drasill into a control plane for local Claude Code sessions:

┌───────────────┐    ┌───────────────┐    ┌───────────────┐
│  Claude Code  │    │  Claude Code  │    │  Claude Code  │
│    (alpha)    │    │     (beta)    │    │    (gamma)    │
└──────┬────────┘    └──────┬────────┘    └──────┬────────┘
       │                    │                    │
       │  register          │  send msg          │  inbox
       │  send msg          │  check inbox       │  consume
       │  check inbox       │                    │  send msg
       │                    │                    │
       └────────────────────┼────────────────────┘
                            │
                    ┌───────┴────────┐
                    │    Drasill     │
                    │    :8400       │
                    │                │
                    │    /mesh/*     │
                    │    SQLite      │
                    │    SSE + async │
                    └────────────────┘
  • RegisterPOST /mesh/agents joins the mesh with a name and optional session ID
  • DiscoverGET /mesh/agents lists all active agents
  • MessagePOST /mesh/agents/{name}/inbox sends a message (with optional heimdall wake)
  • ConsumeGET /mesh/agents/{name}/inbox returns the oldest unread message
  • Pruning — Stale agents auto-transition: active → idle → dead → removed

All /mesh/* endpoints are localhost-only (middleware rejects non-loopback requests), so exposure via Cloudflare Tunnel or similar is safe.

Web UI

A live-updating control panel showing agent status, recent messages, and a send-message form. SSE events trigger HTMX partial reloads, Alpine.js handles client-side interactivity. Web terminal gives browser access to agent pty sessions.

Agent Integration

No plugins or hooks needed. Drasill injects mesh awareness into each agent's system prompt at launch and delivers messages via heimdall stdin injection when agents go idle. Agents communicate with peers using curl to the mesh API.


Prerequisites

Tool Required Purpose
uv Yes Python package management and virtualenv
heimdall (hm) Yes Rust pty supervisor — agents run inside heimdall sessions
Claude Code Yes The AI coding agent that Drasill coordinates
git Yes Used for session naming (repo + branch) and general dev
curl Recommended Agents use curl to communicate with the mesh API
Tailscale Optional Access Drasill from other devices on your tailnet
# Verify prerequisites
uv --version && hm --version && claude --version && git --version && curl --version

Quick Start

# Install dependencies
uv sync

# Start the server
uv run uvicorn drasill.app:create_app --factory --reload --port 8400

# Open the dashboard
open http://localhost:8400

Deploy with systemd

./deploy/install.sh

Join the mesh from Claude Code

Agents are mesh-aware at launch — no setup needed. Send a message from any terminal:

curl -s -X POST "http://localhost:8400/mesh/agents/alpha/inbox" \
  -H 'Content-Type: application/json' \
  -d '{"from_agent": "human", "body": "Run the tests and report results"}'

Configuration

config.toml at the project root (or set DRASILL_CONFIG env var):

[server]
host = "0.0.0.0"
port = 8400

[db]
path = "~/.local/share/drasill/dash.db"

# Per-dashboard overrides
[dashboards.agent_mesh]
enabled = true
schedule = "5s"

Development

uv sync                              # install deps
uv run pytest                        # run tests (95% coverage gate)
uv run ruff check py_src py_tests    # lint
uv run ruff format py_src py_tests   # format
uv run nox -s all_checks             # lint + format + typecheck + test

150 tests, 96% coverage, zero lint warnings.


Stack

Layer Tech
Language Python 3.13+
Framework FastAPI + uvicorn
Database SQLite via aiosqlite
Realtime SSE event bus + asyncio background tasks
Frontend Jinja2 + HTMX + Alpine.js + Tailwind CDN
Validation Pydantic v2
Linting Ruff (ALL rules)
Type checking ty (strict)
Testing pytest + pytest-asyncio, 95% coverage gate
Build hatchling, managed by uv

Project Structure

py_src/drasill/
├── app.py                 # FastAPI app factory + lifespan
├── config.py              # TOML → Pydantic config loader
├── db.py                  # SQLite schema + init
├── claude.py              # Async claude CLI wrapper
├── doctor.py              # Dependency health checks
├── supervisor_client.py   # Async heimdall socket client
├── mesh/
│   ├── router.py          # /mesh/* API endpoints
│   ├── models.py          # Pydantic request/response models
│   ├── events.py          # SSE event bus (asyncio.Queue fanout)
│   ├── middleware.py       # Localhost-only security middleware
│   ├── uploads.py         # File attachment storage
│   └── pruning.py         # Agent lifecycle management
├── terminal/
│   └── router.py          # WebSocket heimdall proxy + session creation
├── templates/             # Jinja2 + HTMX templates
└── static/                # PWA assets + CSS

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drasill-1.0.0.tar.gz (301.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

drasill-1.0.0-py3-none-any.whl (223.3 kB view details)

Uploaded Python 3

File details

Details for the file drasill-1.0.0.tar.gz.

File metadata

  • Download URL: drasill-1.0.0.tar.gz
  • Upload date:
  • Size: 301.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for drasill-1.0.0.tar.gz
Algorithm Hash digest
SHA256 80eed5590a7587308a7c21f13a515e237765e80e7c7e0bfe8d755acbea0121e7
MD5 86628f6045a4e9be01143874b0543f75
BLAKE2b-256 38dfb8337e67027a50d069f0a8a2a4ae2c68ff4bcbbb2cb182f5d0602797a1d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for drasill-1.0.0.tar.gz:

Publisher: release.yml on nazq/Drasill

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file drasill-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: drasill-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 223.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for drasill-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8aa9c4b61dbec14d436468cbe20bb5e5fbbf4a8d03fe5c73a8c20e8162049b20
MD5 120fcbcfc119cb383d590cf9d555f530
BLAKE2b-256 d9d6031a09b1476416853c198ef1bcea5486c396d65436f7616053fb5f031faf

See more details on using hashes here.

Provenance

The following attestation bundles were made for drasill-1.0.0-py3-none-any.whl:

Publisher: release.yml on nazq/Drasill

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page