A multi-tenant worker operating system for small and medium businesses. Businesses can activate AI workers for real operational jobs — inbox management, content creation, booking operations, CRM follow-up, and admin support.
Built as a modular Docker Compose stack: Dashboard (product surface), Paperclip (orchestration), worker-gateway (execution boundary), Agent Zero (worker runtime), LiteLLM (model gateway), plus Postgres and a provisioned Redis instance reserved for future coordination/caching. Target deployment: Hetzner via Coolify.
This repository includes the standard baseline expected from an open source project:
CONTRIBUTING.mdfor local setup, validation, and PR expectationsCODE_OF_CONDUCT.mdfor community behavior standardsSECURITY.mdfor private vulnerability reportingSUPPORT.mdfor help and issue-routing guidanceGOVERNANCE.mdfor the current maintainer-led decision modelTHIRD_PARTY_NOTICES.mdfor upstream attribution and external provider terms- GitHub issue forms, a pull request template,
CODEOWNERS, CI, and Dependabot
This is the quick-start view of the running stack. The fuller layered diagram lives in docs/architecture/system-architecture.md.
flowchart TB
USER["Business Users / Operators"]
DASH["Dashboard - Next.js :3000"]
PAPER["Paperclip - Control Plane :3100"]
GATE["Worker Gateway - FastAPI :8080"]
A0["Agent Zero - Runtime :50080"]
LLM["LiteLLM - Model Gateway :4000"]
PG["Postgres :5432"]
REDIS["Redis - Reserved / Future Use :6379"]
USER --> DASH
DASH --> PAPER
DASH --> GATE
DASH --> PG
PAPER --> GATE
PAPER --> PG
GATE --> A0
GATE --> PG
A0 --> LLM
LLM --> PG
All services communicate over the workerstack Docker bridge network. Container names follow the psilo-* convention.
- Docker and Docker Compose (v2) — install
- At least one LLM provider API key (OpenAI, Anthropic, Google, or Groq) for LiteLLM to route model requests
- ~4 GB free RAM for all seven containers
# 1. Generate .env with random secrets
make setup
# 2. Add at least one provider key
# Edit .env and fill in OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.
# 3. Build and start all services
make build
# 4. Verify everything is healthy
make status
# 5. Run smoke tests
make test| Service | URL | Notes |
|---|---|---|
| Dashboard | http://localhost:3000 | Customer-facing product surface |
| Paperclip | http://localhost:3100 | Control plane UI |
| LiteLLM | http://localhost:4000 | Model gateway (auth required) |
| Agent Zero | http://localhost:50080 | Worker runtime UI |
| Worker Gateway | http://localhost:8080 | Bridge API |
| Worker Gateway Health | http://localhost:8080/healthz | Health + downstream status |
Postgres (:5432) and Redis (:6379) are internal-only — not exposed to the host.
make setup Generate .env from .env.example with random secrets
make validate Validate docker-compose.yml
make build Build and start the stack (detached)
make up Start the stack (detached, no rebuild)
make down Stop the stack
make clean Stop the stack and remove volumes
make logs Tail logs for all services
make status Show service status
make test Run smoke tests against running stack
Per-service shortcuts: make logs-worker-gateway, make restart-paperclip, make shell-agentzero, etc.
Run make setup to auto-generate secrets. The setup script fills:
| Variable | Generated | Notes |
|---|---|---|
POSTGRES_PASSWORD |
Yes | 32-char random |
LITELLM_MASTER_KEY |
Yes | sk- prefix + 48-char random |
PAPERCLIP_AGENT_JWT_SECRET |
Yes | 64-char hex |
AGENTZERO_AUTH_PASSWORD |
Yes | 32-char random |
You must still set manually:
| Variable | Where |
|---|---|
OPENAI_API_KEY / ANTHROPIC_API_KEY / etc. |
At least one provider key in .env |
AGENTZERO_API_TOKEN |
From Agent Zero UI after first boot (see below) |
See .env.example for the full list.
After the stack is running:
- Open http://localhost:50080
- Log in with the credentials from
.env(AGENTZERO_AUTH_LOGIN/AGENTZERO_AUTH_PASSWORD) - Go to Settings > External Services
- Copy the API token
- Paste it into
.envasAGENTZERO_API_TOKEN=<token> - Restart the gateway:
make restart-worker-gateway
In the Agent Zero UI, set the chat model to use LiteLLM as an OpenAI-compatible gateway:
- Provider: OpenAI Compatible
- Base URL:
http://litellm:4000 - API Key: your
LITELLM_MASTER_KEYvalue - Model: one of the models in
services/litellm/config.yaml(e.g.gpt-4.1-mini)
- Open http://localhost:3100
- On the first boot, run
make logs-paperclipand open the one-time Paperclip bootstrap URL printed in the startup logs after Paperclip finishes startup - Create an agent with adapter type HTTP
- Set the webhook URL to:
http://worker-gateway:8080/paperclip/wake - Send a test task — check worker-gateway logs with
make logs-worker-gateway
- Paperclip POSTs a wake event to
worker-gatewayat/paperclip/wake - The gateway executes the wake through the runtime adapter
- The runtime adapter sends the task to Agent Zero via
POST /api_message - Agent Zero routes model traffic through LiteLLM
- The gateway returns a 2xx response to Paperclip; the current HTTP adapter flow does not require a callback endpoint
If Agent Zero is unreachable or the API token is missing, the gateway returns an error result through the same wake request flow.
habilis/
├── apps/
│ ├── dashboard/ Next.js customer product surface
│ └── worker-gateway/ FastAPI bridge service
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
├── packages/
│ ├── shared-types/ Cross-service type definitions
│ ├── worker-definitions/ Worker configs and schemas
│ ├── connector-sdk/ Connector SDK
│ ├── ui/ Shared UI components
│ └── config/ Shared configuration
├── services/
│ ├── paperclip/ Control plane (Dockerfile)
│ ├── litellm/ Model gateway (config.yaml)
│ └── agentzero/ Worker runtime (placeholder)
├── infra/
│ ├── postgres/init/ DB init scripts
│ ├── docker/ Docker configs
│ ├── coolify/ Deployment configs
│ ├── scripts/ setup.sh, smoke-test.sh
│ └── env/ Environment templates
├── docs/
│ └── mission.md Mission and architecture vision
├── docker-compose.yml Full stack definition
├── .env.example Environment variable template
├── Makefile Dev workflow shortcuts
└── CLAUDE.md AI assistant guidance
Use the Docker Compose build pack in Coolify and point it to this repo.
Public-facing services (attach domains):
app.yourdomain.com→ Dashboard, port 3000paperclip.yourdomain.com→ Paperclip, port 3100llm.yourdomain.com→ LiteLLM, port 4000
Internal-only (no public domain):
- Postgres, Redis, Agent Zero, Worker Gateway
Required env vars in Coolify: same as .env.example — set all secrets in Coolify's environment variable UI rather than committing a .env file.
Recommendations:
- Pin
LITELLM_IMAGE_TAGto a specific stable version after testing - For internet-facing deploys, set
PAPERCLIP_DEPLOYMENT_MODE=authenticatedandPAPERCLIP_PUBLIC_URL=https://paperclip.yourdomain.com - On the first authenticated boot, use the bootstrap URL printed after Paperclip startup; if needed later, run
paperclipai auth bootstrap-ceo --base-url https://paperclip.yourdomain.com
Contributions are welcome. Start with CONTRIBUTING.md,
then open an issue or pull request with clear scope and testing notes.
Apache-2.0. See LICENSE.