AI-first automation platform — describe workflows in plain English, build them instantly.
Quick Start · Architecture · Features · Configuration · Deployment
Iris is a self-hosted automation platform that lets you build and manage event-driven workflows ("relays") by describing them in plain English — via a web dashboard, or directly on Telegram using text or voice notes.
You say: "Create a relay that checks Bitcoin price every hour and sends me a Telegram message if it drops below $60k."
Iris builds the relay, schedules it, and runs it. No code required.
- AI relay builder — Describe automation workflows in plain English (powered by Gemini)
- Visual DAG builder — Drag-and-drop node-based relay editor in the browser
- Telegram bot — Create, list, trigger, enable/disable relays by chat or voice note
- Voice notes → relays — Send a voice note on Telegram, ElevenLabs transcribes it, Gemini builds the relay
- Webhook triggers — Each relay gets a unique webhook URL for external integrations
- Cron triggers — Schedule relays with natural-language cron expressions
- Secrets manager — Encrypted secret storage for API keys used in relay actions
- Execution history — Full audit trail of every relay run with step-level logs
- Self-hosted — Runs on a single $24/month VPS
┌─────────────────────────────────────────────────────┐
│ iris-web (Next.js) │
│ Dashboard · Visual Builder · Connections │
└───────────────────────┬─────────────────────────────┘
│ REST API
┌───────────────────────▼─────────────────────────────┐
│ iris-core (Go) │
│ Auth · Relays · Secrets · AI · Settings · NATS │
└──────────┬────────────────────────┬─────────────────┘
│ NATS JetStream │ NATS
┌──────────▼──────────┐ ┌─────────▼─────────────────┐
│ iris-worker (Go) │ │ iris-hooks (Go) │
│ Executes relay │ │ Receives webhook POSTs │
│ actions (HTTP, │ │ → publishes to NATS │
│ NATS, cron, etc.) │ └───────────────────────────┘
└─────────────────────┘
┌─────────────────────────────────────────────────────┐
│ iris-telegram (Go) │
│ Telegram bot · STT · AI relay creation via chat │
└─────────────────────────────────────────────────────┘
┌──────────────────────┐ ┌──────────────────────────┐
│ PostgreSQL │ │ NATS JetStream │
│ (all state) │ │ (event bus) │
└──────────────────────┘ └──────────────────────────┘
| Service | Language | Port | Purpose |
|---|---|---|---|
iris-core |
Go | 3000 | Main REST API — auth, relays, AI, settings |
iris-hooks |
Go | 8080 | Public webhook ingestion endpoint |
iris-worker |
Go | — | Background relay executor + cron scheduler |
iris-telegram |
Go | — | Telegram bot (polling, no webhook needed) |
iris-web |
Next.js | 3001 | Frontend dashboard |
- Go 1.22+
- Node.js 20+
- Docker + Docker Compose
- A Google AI Studio API key (free tier works)
git clone https://github.com/youruser/Iris.git
cd IrisCopy the example env and fill in the required values:
cp .env.example .envOpen .env and set at minimum:
# Required
DATABASE_URL=postgres://user:password@localhost:5432/iris?sslmode=disable
NATS_URL=nats://localhost:4222
JWT_SECRET=change-me-to-a-long-random-string-256bit
ENCRYPTION_KEY=64-char-hex-string-for-secret-encryption
# AI (required for relay generation)
LLM_PROVIDER=gemini
LLM_API_KEY=your-google-ai-api-key
LLM_MODEL=gemini-2.0-flash
# Optional — enable voice notes on Telegram
ELEVENLABS_API_KEY=your-elevenlabs-key
# Optional — set Telegram bot token here OR via the Connections page in the UI
# TELEGRAM_BOT_TOKEN=
TELEGRAM_BOT_USERNAME=YourBotUsername
# URLs
IRIS_CORE_URL=http://localhost:3000
IRIS_HOOKS_URL=http://localhost:8080
FRONTEND_URL=http://localhost:3001# Start Postgres + NATS
make infra-up
# Wait a few seconds, then run migrations
make db-migrate-upIf
migrateCLI is not installed:go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest
# Starts core + hooks + worker + telegram bot (waits for core before starting bot)
make dev-allEach service logs to stdout with structured JSON:
{"time":"...","level":"INFO","msg":"http server listening","service":"iris-core","addr":":3000"}
{"time":"...","level":"INFO","msg":"iris-worker ready","service":"iris-worker","workers":10}
{"time":"...","level":"INFO","msg":"telegram bot authorized","service":"iris-telegram","username":"YourBotUsername"}cd web/iris-web
npm install
npm run devOpen http://localhost:3001.
- Go to http://localhost:3001
- Click Sign Up → create an account
- You're in the dashboard
- Get a bot token from @BotFather on Telegram →
/newbot - In the dashboard: Connections → paste your token → Save
- The bot fetches the token from the database automatically — no restart needed if already running
- Open your bot on Telegram →
/login <your-iris-jwt-token>- Copy your JWT from the Connections page
- Start sending voice notes or text to create relays!
make infra-up # Start Postgres + NATS via Docker
make infra-down # Stop Docker infra
make db-migrate-up # Run all pending database migrations
make db-migrate-down # Roll back last migration
make db-reset # Drop and re-run all migrations (destructive!)
make dev-core # Start iris-core only
make dev-hooks # Start iris-hooks only
make dev-worker # Start iris-worker only
make dev-telegram # Start iris-telegram only
make dev-backend # Start core + hooks + worker (no telegram)
make dev-all # Start all 4 services (telegram waits for core)
make build # Build all binaries to bin/
make lint # Run golangci-lint| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
✅ | — | PostgreSQL connection string |
NATS_URL |
✅ | — | NATS server URL |
JWT_SECRET |
✅ | — | Secret for signing JWTs |
ENCRYPTION_KEY |
✅ | — | 64-char hex key for encrypting secrets |
CORE_PORT |
— | 3000 |
HTTP port |
FRONTEND_URL |
— | http://localhost:3001 |
Allowed CORS origin |
LLM_PROVIDER |
— | openai |
gemini or openai |
LLM_API_KEY |
— | — | API key for your LLM provider |
LLM_MODEL |
— | gpt-4o-mini |
Model name |
SERVICE_SECRET |
— | — | Shared secret for internal service calls |
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
✅ | — | PostgreSQL connection string |
NATS_URL |
✅ | — | NATS server URL |
HOOKS_PORT |
— | 8080 |
HTTP port |
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
✅ | — | PostgreSQL connection string |
NATS_URL |
✅ | — | NATS server URL |
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
✅ | — | PostgreSQL connection string |
IRIS_CORE_URL |
— | http://localhost:3000 |
iris-core base URL |
IRIS_HOOKS_URL |
— | http://localhost:8080 |
iris-hooks base URL (shown in webhook relay messages) |
TELEGRAM_BOT_TOKEN |
— | — | Bot token from @BotFather. If empty, fetched from DB (set via Connections page) |
TELEGRAM_BOT_USERNAME |
— | — | Bot username without @ (used for deep links) |
ELEVENLABS_API_KEY |
— | — | Enables voice note → text transcription |
SERVICE_SECRET |
— | — | Must match iris-core's SERVICE_SECRET |
SESSION_TTL |
— | 24h |
Telegram session inactivity timeout |
| Command | Description |
|---|---|
/start |
Welcome message |
/login <jwt> |
Link your Iris account (paste JWT from dashboard) |
/logout |
Unlink your account |
/new |
Start creating a relay with AI |
/list |
List all your relays |
/toggle <name or ID> |
Flip a relay's active/inactive state |
/enable <name or ID> |
Enable a relay |
/disable <name or ID> |
Disable a relay |
/trigger <name or ID> |
Manually trigger a relay |
/status <name> |
Show recent executions for a relay |
/delete <name> |
Delete a relay |
/templates |
Quick-start template gallery |
/cancel |
Cancel current operation |
/help |
Show all commands |
Voice notes: Just send a voice note while logged in — the bot transcribes it with ElevenLabs and creates a relay. No /new needed.
Each relay is a DAG of actions. Currently supported action types:
| Action | What it does |
|---|---|
http_request |
Make an HTTP GET/POST/PUT/DELETE request |
send_email |
Send an email via SMTP |
telegram_message |
Send a Telegram message to the linked user |
nats_publish |
Publish a message to a NATS subject |
transform |
Transform data with a template |
condition |
Branch the DAG based on a condition |
| Trigger | Description |
|---|---|
webhook |
Triggered by a POST to <hooks-url>/hooks/<relay-id> |
cron |
Scheduled (e.g. every hour, every morning at 9am) |
manual |
Only triggered via /trigger command or dashboard |
Migrations live in services/core/db/migrations/. Each migration is a pair of .up.sql / .down.sql files.
# Create a new migration
make db-migrate-create NAME=add_something
# Run all pending
make db-migrate-up
# Roll back one
make db-migrate-downEverything runs on a single $24/month DigitalOcean Droplet (2 vCPU / 4 GB RAM).
Stack:
- Go binaries managed by systemd (auto-restart on crash)
- Next.js frontend managed by PM2
- Postgres + NATS via Docker Compose
- Nginx as reverse proxy for 3 subdomains
- Let's Encrypt for free SSL (auto-renews)
For full step-by-step instructions see docs/deployment.md.
Quick overview:
yourdomain.com → Next.js frontend
api.yourdomain.com → iris-core (REST API)
hooks.yourdomain.com → iris-hooks (webhook ingestion)
Set TELEGRAM_BOT_TOKEN via the Connections page in the dashboard — no secrets in .env on the server.
Iris/
├── services/
│ ├── core/ # Main API (Go)
│ │ ├── cmd/api/ # Entry point
│ │ ├── db/migrations/ # SQL migrations
│ │ └── internal/
│ │ ├── api/ # HTTP handlers, router, middleware
│ │ ├── ai/ # LLM client + prompts
│ │ ├── models/ # Request/response types
│ │ └── store/ # PostgreSQL data access
│ ├── hooks/ # Webhook ingestion service (Go)
│ ├── worker/ # Relay executor + cron scheduler (Go)
│ └── iris-telegram/ # Telegram bot (Go)
│ ├── cmd/bot/ # Entry point
│ └── internal/
│ ├── bot/ # Command handlers, session state
│ ├── iris/ # iris-core API client
│ ├── stt/ # ElevenLabs STT client
│ └── store/ # Telegram DB (links, sessions)
├── web/
│ └── iris-web/ # Next.js 16 frontend
│ └── app/dashboard/ # Dashboard pages
├── packages/
│ └── logger/ # Shared structured logger
├── docker-compose.yml # Postgres + NATS
├── Makefile # Dev commands
└── .env # Local environment (never commit)
- Fork the repo
- Create a branch:
git checkout -b feature/my-feature - Make your changes
- Run
make lintandmake build - Open a pull request
MIT
