A single-tenant personal AI assistant deployed as a Databricks App. Slack is your interface — talk to it in a DM with yourself, give it access to your Databricks data tools via UC connections, and customize its personality by editing the source code. One deployment per user. Fork it and make it yours.
You (@yourself in a Slack DM-with-yourself)
│
▼
Databricks App (FastAPI + Claude Agent SDK)
│ Polls conversations.history on your self-DM channel
│ Your PAT forwarded via X-Forwarded-Access-Token
│
├── UC Connection → Slack (post responses back)
├── UC Connection → any other external MCP tool
├── Managed MCP → Genie, Vector Search, SQL, UC Functions
├── Custom MCP → arbitrary HTTP MCP servers
└── claw-memory MCP → MEMORY.md on UC Volume
│
▼
Response posted back to your Slack thread
Slack is purely the transport layer — Claude never calls Slack as a tool. The app polls your self-DM for new messages, runs the agent, and posts responses back using your Slack UC connection directly. No Events API, no Socket Mode, no public URL needed.
Default: thread-in-DM-with-yourself.
The app calls Slack's auth.test to resolve your user ID, then opens a DM channel with yourself. It watches that channel for messages where you @mention yourself.
- Open a DM with yourself in Slack
- Send
@YourName do something— where@YourNameis your own Slack display name - Claw replies in that thread
- Continue the conversation naturally — no need to @mention again within the same thread
- Messages to yourself without the @mention are ignored
React to any message in Slack with the :onit: emoji (configurable via CLAW_TRIGGER_REACTION). Claw copies the message text into a new thread in your self-DM and starts working on it. The reaction is removed automatically after processing. You can restrict which channels this works in with CLAW_REACTION_CHANNELS.
Send \close, close, bye, goodbye, or done in a thread to end the session. Claw disconnects and frees resources. Sessions also auto-close after 7 days of inactivity (configurable via ACTIVE_THREAD_WINDOW_DAYS).
Two layers:
- Within-thread: Full conversation continuity via Claude Agent SDK session IDs keyed on Slack
thread_ts. Stored in Lakebase. The agent resumes exact conversation state when you send follow-up messages. - Cross-thread:
MEMORY.mdon a UC Volume via a stdio MCP server (claw-memory). The agent reads and writes facts it wants to remember across sessions — names, preferences, ongoing projects, decisions.
The app runs as a Databricks App with its own service principal (auto-injected by the platform). You provide a Personal Access Token (PAT) as a Databricks Secret — this PAT is forwarded via X-Forwarded-Access-Token on UC connection proxy calls so that external services (Slack, other MCP tools) resolve to your identity, not the app's SP.
- SP token → Databricks SDK calls (Lakebase, UC Volume, AI Gateway)
- Your PAT → forwarded to UC connection proxies for user-scoped external access (Slack, MCP tools)
The app never holds a Slack bot token directly — the UC connection stores Slack credentials and the proxy handles upstream auth.
Claw connects Claude to external tools through three categories of MCP servers, all configured via environment variables in app.yaml:
- External (
UC_MCP_CONNECTIONS): UC connection names proxied through{host}/api/2.0/mcp/external/{name}. Use for any service with a UC connection (Slack, GitHub, etc.) - Managed (
UC_MANAGED_MCPS): Databricks-native MCP servers —genie:{space_id},vector-search:{catalog}.{schema}.{index},sql,uc-functions:{catalog}.{schema} - Custom (
UC_CUSTOM_MCPS): Arbitrary HTTP MCP endpoints —name=urlpairs
See app.example.yml for full configuration reference.
Edit the source. No admin panel needed — it's your deployment.
CLAUDE.md ← personality, tone, formatting rules, instructions
.claude/skills/<name>/ ← add skills (invocable via slash commands like /skill-name)
app.yaml ← runtime config (MCP connections, model, polling interval)
databricks.yml ← DAB bundle variables (catalog, secret scope, name prefix)
- Databricks workspace with an AI Gateway endpoint configured
- A Slack UC connection set up in Unity Catalog (stores your Slack app credentials)
- Databricks Personal Access Token (PAT) for the deploying user
databricksCLI installed and authenticateduvinstalled
Open Claude Code in the repo root and run:
/initial-setup
The setup skill walks you through every phase interactively:
- Prerequisites check — verifies CLI tools, auth, workspace connectivity
- Personalization — auto-detects your username, sets a
name_prefixto avoid resource collisions in shared workspaces - App configuration — fills in
app.yamlwith your workspace ID, catalog, UC connection names, validates the AI Gateway URL against your workspace - Slack UC connection — verifies the connection exists and tests it against Slack's
auth.test - Secrets — ensures the secret scope and PAT secret exist (never asks you to paste tokens in chat)
- Deploy — runs
make full-deploy(build → validate → deploy → migrate → start → app-deploy) - Smoke test — confirms the app is running, poller started, and Slack replies work
If you prefer to set things up yourself:
- Copy
app.example.ymltoapp.yamland fill in your workspace ID, catalog name, and UC connection names - Add your PAT as a secret:
databricks secrets put-secret claw claw-user-pat --string-value <your-pat>
- Deploy:
bash scripts/deploy.sh full
bash scripts/deploy.sh app-deployPush source code changes without redeploying infrastructure.
This repo is designed to be forked and customized into your own personal assistant. Fork it, rename it, change the personality in CLAUDE.md, add your own skills, wire up the MCP servers you care about.
A sync-upstream skill is included so you can pull in upstream changes:
/sync-upstream
databricks-claw/
├── claw/
│ ├── main.py # FastAPI app entry point
│ ├── models.py # SQLModel tables (Session, Message)
│ └── core/
│ ├── agent.py # Claude Agent SDK client + streaming
│ ├── auth.py # SP/PAT header generation
│ ├── config.py # AppConfig (env vars → typed config)
│ ├── db.py # Lakebase engine + token refresh
│ ├── mcp_mapper.py # UC connections → SDK MCP configs
│ ├── memory.py # MEMORY.md read/write on UC Volume
│ ├── memory_mcp.py # Stdio MCP server for persistent memory
│ ├── sessions.py # thread_ts → sdk_session_id CRUD
│ ├── slack_client.py # Slack API via UC connection proxy
│ └── slack_poller.py # Background polling + dispatch
├── .claude/skills/ # Skills loaded into every agent session
├── alembic/ # Database migrations (Lakebase)
│ ├── env.py
│ └── versions/
├── resources/
│ ├── app.yml # Databricks App resource definition
│ ├── lakebase.yml # Lakebase CU_1 instance
│ └── volume.yml # UC Volume for memory files
├── scripts/
│ ├── deploy.sh # Full e2e deploy
│ └── migrate.py # Grant SP perms + run Alembic
├── tests/ # Unit tests (pytest)
├── CLAUDE.md # Agent personality + instructions
├── alembic.ini
├── databricks.yml # DAB bundle config
├── app.yaml # App runtime config (from app.example.yml)
└── pyproject.toml