https://github.com/automagik-dev/omni
Universal event-driven omnichannel platform for AI agents to communicate across any messaging platform
https://github.com/automagik-dev/omni
ai-agents bun discord event-driven messaging nats omnichannel typescript whatsapp
Last synced: about 1 month ago
JSON representation
Universal event-driven omnichannel platform for AI agents to communicate across any messaging platform
- Host: GitHub
- URL: https://github.com/automagik-dev/omni
- Owner: automagik-dev
- Created: 2026-01-29T23:09:28.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-04-01T06:20:48.000Z (3 months ago)
- Last Synced: 2026-04-03T05:36:39.882Z (3 months ago)
- Topics: ai-agents, bun, discord, event-driven, messaging, nats, omnichannel, typescript, whatsapp
- Language: TypeScript
- Homepage: https://github.com/automagik-dev/omni
- Size: 51.4 MB
- Stars: 14
- Watchers: 0
- Forks: 1
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
Universal event-driven omnichannel messaging platform
One API to send and receive messages across WhatsApp, Discord, Telegram, and more.
CLI-first. Event-driven. Built for AI agents.
Install •
Quick Start •
AI Agents •
CLI •
API •
SDKs •
Development
---
Think of Omni as a deep-sea octopus. Each **channel** is a tentacle — WhatsApp, Discord, Telegram — reaching into a different messaging ecosystem. **Events** are nerve impulses flowing through NATS JetStream. The **core** is the brain — identity resolution, event routing, and a unified API that lets you treat all channels as one.
## Why Omni?
| | |
|---|---|
| 🔌 **One API, every channel** | Send a WhatsApp message, a Discord embed, and a Telegram photo with the same endpoint |
| ⚡ **Event-driven** | Every action produces an event. Subscribe, replay, automate |
| 🧬 **Identity graph** | Same person on WhatsApp and Discord? Omni knows |
| 🤖 **AI-native** | Agent providers, automations, built to be controlled by LLMs |
| 🔧 **Plugin architecture** | Build new channels with the Channel SDK |
| 📦 **Multi-SDK** | Auto-generated TypeScript, Python, and Go SDKs |
## Channels
| Channel | Status | Highlights |
|---------|--------|------------|
| **WhatsApp** (Baileys) | ✅ Stable | QR/phone pairing, media, reactions, groups, contacts, presence |
| **Discord** | ✅ Stable | Bots, embeds, polls, buttons, threads, slash commands |
| **Telegram** | ✅ New | Bot API, inline keyboards, groups, channels, threads, polls |
| WhatsApp Cloud API | 🔮 Planned | — |
| Slack | 🔮 Planned | — |
## Install
### Quickest (npm)
```bash
bun add -g @automagik/omni
omni install # interactive wizard: sets up server + PM2
```
> **Migrating from `@omni/cli`?** Run `bun remove -g @omni/cli` first.
### Via install script (npm-first, git fallback)
```bash
curl -fsSL https://raw.githubusercontent.com/automagik-dev/omni/main/install-client.sh | bash
```
### Full server from source
```bash
curl -fsSL https://raw.githubusercontent.com/automagik-dev/omni/main/install.sh | bash
```
Three modes: **CLI only** · **Full server** · **CLI + connect to remote**
Non-interactive & manual install
```bash
# CLI only (tries npm first, falls back to git clone)
curl -fsSL https://raw.githubusercontent.com/automagik-dev/omni/main/install.sh | bash -s -- --cli
# CLI + connect to remote
curl -fsSL https://raw.githubusercontent.com/automagik-dev/omni/main/install.sh | bash -s -- --cli https://your-omni-server.com
# Full server
curl -fsSL https://raw.githubusercontent.com/automagik-dev/omni/main/install.sh | bash -s -- --server
```
**Manual:**
```bash
git clone https://github.com/automagik-dev/omni.git && cd omni
make setup # Install deps, create .env, start services
```
API runs at `http://localhost:8882` · Swagger docs at `/api/v2/docs` · API key printed in startup banner.
## Quick Start
```bash
# Authenticate
omni auth login --api-key
# WhatsApp — scan QR
omni instances create --name "my-whatsapp" --channel whatsapp-baileys
omni instances qr --watch
# Discord — connect bot
omni instances create --name "my-discord" --channel discord
omni instances connect --token "BOT_TOKEN"
# Telegram — connect bot
omni instances create --name "my-telegram" --channel telegram
omni instances connect --token "BOT_TOKEN"
# Send messages
omni send --to "+5511999999999" --text "Hello from the deep 🐙"
# Browse conversations
omni chats list --unread --sort unread
```
## AI Agents
Connect any LLM provider and your instances become intelligent agents — responding to messages, reacting to events, across every channel.
```
Message received → NATS event → Agent Dispatcher → Provider (OpenAI/Agno/Webhook) → Humanized reply
```
```bash
# Connect a provider
omni providers create --name "my-llm" --schema openai --base-url "https://api.openai.com/v1" --api-key "sk-..."
# Bind to instance — it's now an agent
omni instances update --agent-provider
```
| Trigger | When | Use Case |
|---------|------|----------|
| **DM** | Direct message | Always reply |
| **Mention** | @bot in group | Respond to mentions |
| **Reply** | Reply to bot's message | Continue thread |
| **Reaction** | Emoji on message | 👍 approve, 🔥 prioritize |
**Built-in:** message debouncing · per-user rate limits · access control · smart response chunking · typing presence · cross-channel identity · self-chat detection
Automations & event-driven workflows
```bash
# Auto-reply
omni automations create --name "welcome" \
--trigger "message.received" \
--action send_message --action-config '{"text":"Got it! 🐙"}'
# Webhook on connection
omni automations create --name "notify" \
--trigger "instance.connected" \
--action webhook --action-config '{"url":"https://your-app.com/hook"}'
# Route VIPs to a special agent
omni automations create --name "vip" \
--trigger "message.received" \
--condition '{"field":"payload.from","op":"in","value":["+551199..."]}' \
--action call_agent --agent-id "vip-handler" --provider-id
```
## Architecture
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ WhatsApp │ │ Discord │ │ Telegram │ Tentacles
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
└────────────────┼────────────────┘
┌─────────▼─────────┐
│ NATS JetStream │ Nerve System
└─────────┬─────────┘
┌─────────▼─────────┐
│ Omni Core │ Brain
└─────────┬─────────┘
┌──────────────┼──────────────┐
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ REST API │ │ CLI │ │ Dashboard │ Interfaces
└───────────┘ └───────────┘ └───────────┘
```
Project structure
```
packages/
├── core/ # Events, identity, schemas
├── db/ # Drizzle ORM + PostgreSQL
├── api/ # Hono + tRPC + OpenAPI
├── channel-sdk/ # Plugin SDK
├── channel-whatsapp/ # Baileys
├── channel-discord/ # discord.js
├── channel-telegram/ # grammy
├── cli/ # `omni` command
├── media-processing/ # Media sync
├── sdk/ # TypeScript SDK
├── sdk-go/ # Go SDK
└── sdk-python/ # Python SDK
apps/
└── ui/ # React + Vite + Tailwind
```
## CLI Reference
Core commands — send, chats, messages, instances, channels, persons
#### `send` — Send messages
```bash
omni send --to "+5511999999999" --text "Hello!"
omni send --to "+5511999999999" --media ./photo.jpg --caption "Check this out"
omni send --to "+5511999999999" --reaction "👍" --message
omni send --to "+5511999999999" --sticker ./sticker.webp
omni send --to "+5511999999999" --contact --name "John" --phone "+1234567890"
omni send --to "+5511999999999" --location --lat -23.55 --lng -46.63 --address "São Paulo"
omni send --to "discord-channel-id" --poll "Favorite color?" --options "Red,Blue,Green"
omni send --to "discord-channel-id" --embed --title "Alert" --description "Server rebooting" --color "#ff0000"
omni send --to "+5511999999999" --presence typing
```
#### `chats` — Manage conversations
```bash
omni chats list --unread --sort unread
omni chats messages --limit 20 --rich
omni chats archive
omni chats participants --add "+5511999999999"
```
Subcommands: `list` · `get` · `create` · `update` · `delete` · `archive` · `unarchive` · `messages` · `participants` · `read`
#### `messages` — Search and manage
```bash
omni messages search "meeting tomorrow" --instance --limit 10
omni messages read --chat --instance
```
#### `instances` — Channel connections
```bash
omni instances list
omni instances create --name "work-whatsapp" --channel whatsapp-baileys
omni instances qr --watch
omni instances connect --token "BOT_TOKEN" # Discord / Telegram
omni instances sync --type all --depth 30
omni instances contacts --limit 50
omni instances groups
```
Subcommands: `list` · `get` · `create` · `delete` · `status` · `qr` · `pair` · `connect` · `disconnect` · `restart` · `logout` · `sync` · `syncs` · `update` · `contacts` · `groups` · `profile`
#### `persons` — Contact directory
```bash
omni persons search "John"
omni persons get
omni persons presence
```
Management — keys, providers, automations, access, webhooks
#### `keys` — API key management
```bash
omni keys create --name "agent-key" --scopes "messages:*,instances:read"
omni keys list --status active
omni keys revoke --reason "Compromised"
```
#### `providers` — AI/LLM providers
```bash
omni providers create --name "openai" --schema openai --api-key "sk-..."
omni providers list
omni providers test
```
Schemas: `agnoos` · `a2a` · `openai` · `anthropic` · `webhook` · `custom`
#### `automations` — Event-driven workflows
```bash
omni automations create --name "Auto-reply" --trigger "message.received" \
--action send_message --action-config '{"text":"Got it!"}'
omni automations list --enabled
omni automations test
```
Actions: `webhook` · `send_message` · `emit_event` · `log` · `call_agent`
#### `access` — Access control
```bash
omni access create --type deny --instance --phone "+1234567890" --action block
omni access list --instance
omni access check --instance --user "+1234567890"
```
Modes: `disabled` · `blocklist` · `allowlist`
#### `webhooks` — External event sources
```bash
omni webhooks create --name "github-events"
omni webhooks trigger --type "custom.event" --payload '{"key":"value"}'
```
System — update, status, auth, config, events, batch, logs
```bash
omni update -y # Update CLI; restart only services that were already online
omni update -y --no-restart # Update CLI only; skip restarts and API-port health check
omni status # Verify runtime health after update
omni auth login --api-key # Authenticate
omni config set defaultInstance # CLI settings
omni events list --type "message.*" --since 2h # Event history
omni events replay --start --since 2024-01-01 # Replay events
omni batch create --instance --type targeted_chat_sync --chat
omni resync --instance # History backfill
omni logs list --level error --limit 50 # Server logs
omni dead-letters list --limit 20 # Failed events
```
`omni update` can exit non-zero after install only when restart runs (services were already online): in that path it checks API health on the configured API port and fails on restart or health-check errors.
`omni doctor` is not available yet and is tracked as a follow-up.
## REST API
| | |
|---|---|
| **Base URL** | `http://localhost:8882/api/v2` |
| **Docs** | [`/api/v2/docs`](http://localhost:8882/api/v2/docs) (Swagger UI) |
| **OpenAPI** | `/api/v2/openapi.json` |
| **Auth** | `x-api-key` header |
**20 endpoints:** `/auth` · `/instances` · `/messages` · `/chats` · `/events` · `/persons` · `/access` · `/settings` · `/providers` · `/automations` · `/webhooks` · `/keys` · `/logs` · `/batch-jobs` · `/dead-letters` · `/media` · `/metrics` · `/event-ops` · `/payloads`
## SDKs
**TypeScript**
```typescript
import { createOmniClient } from '@omni/sdk';
const omni = createOmniClient({
baseUrl: 'http://localhost:8882',
apiKey: 'your-api-key',
});
await omni.messages.send({
instanceId: '...',
to: '+5511999999999',
text: 'Hello from SDK!',
});
```
**Python**
```python
from omni import OmniClient
client = OmniClient(
base_url="http://localhost:8882",
api_key="your-api-key"
)
instances = client.instances.list()
```
**Go**
```go
client := omni.NewClient(
"http://localhost:8882",
"your-api-key",
)
instances, _ := client.Instances.List(ctx)
```
Regenerate after API changes: `make sdk-generate`
## Web Dashboard
```bash
make dev-ui # Dev → http://localhost:5173
make build-ui # Prod → served by API on :8882
```
**Pages:** Dashboard · Instances · Chats · Chat View · Contacts · Persons · Providers · Automations · Access Rules · Batch Jobs · Dead Letters · Events · Logs · Settings
🔐 API Keys & Security
API key is generated on first boot (shown once in startup banner).
```bash
# Scoped keys
omni keys create --name "admin" --scopes "*"
omni keys create --name "reader" --scopes "messages:read,chats:read"
omni keys create --name "wa-only" --scopes "messages:*" --instances "uuid1,uuid2"
```
**Scopes:** `namespace:action` pattern — `messages:*`, `instances:read`, `*` for full access
**Namespaces:** `messages` · `chats` · `instances` · `persons` · `events` · `access` · `settings` · `providers` · `automations` · `webhooks` · `keys` · `logs` · `batch`
⚙️ Configuration & environment
| Variable | Default | Description |
|----------|---------|-------------|
| `API_PORT` | `8882` | API server port |
| `DATABASE_URL` | `postgresql://...localhost:8432/omni` | PostgreSQL |
| `NATS_URL` | `nats://localhost:4222` | NATS connection |
| `OMNI_API_KEY` | *(auto)* | Override primary key |
Set `*_MANAGED=false` for external services. Full list in `.env.example`.
| Service | PM2 Name | Port |
|---------|----------|------|
| PostgreSQL | `omni-pgserve` | 8432 |
| NATS | `omni-nats` | 4222 |
| API | `omni-api` | 8882 |
## Development
```bash
make dev # Start all services + API
make check # typecheck + lint + test
make dev-ui # UI dev server
make db-push # Push schema changes
make db-studio # Drizzle Studio
```
All make targets
```bash
make setup # Full setup (deps + env + services)
make dev-api # API only
make dev-services # PostgreSQL + NATS via PM2
make typecheck # TypeScript only
make lint # Biome linter
make lint-fix # Auto-fix
make test # All tests
make test-api # API tests
make test-file F= # Specific test
make build # Build all
make build-ui # Build UI
make status # Service status
make logs-api # API logs
make restart-api # Restart API
make db-reset # Reset DB (DESTRUCTIVE)
make sdk-generate # Regenerate SDKs
make cli ARGS="" # Run CLI from source
make cli-link # Install CLI globally
```
Building a channel plugin
```typescript
import { BaseChannelPlugin } from '@omni/channel-sdk';
export class MyPlugin extends BaseChannelPlugin {
readonly id = 'my-channel';
readonly name = 'My Channel';
readonly version = '1.0.0';
readonly capabilities = { /* ... */ };
async connect(instanceId: string, config: InstanceConfig) { /* ... */ }
async disconnect(instanceId: string) { /* ... */ }
async sendMessage(instanceId: string, message: OutgoingMessage) { /* ... */ }
}
```
## Tech Stack
| | |
|---|---|
| Runtime | [Bun](https://bun.sh) |
| HTTP | [Hono](https://hono.dev) |
| API | [tRPC](https://trpc.io) + OpenAPI |
| DB | PostgreSQL + [Drizzle](https://orm.drizzle.team) |
| Events | [NATS JetStream](https://nats.io) |
| Validation | [Zod](https://zod.dev) |
| Frontend | React + [Vite](https://vitejs.dev) + Tailwind |
| Monorepo | [Turborepo](https://turbo.build) |
| Linter | [Biome](https://biomejs.dev) |
---
MIT — do whatever you want, just don't blame the octopus. 🐙
This README is maintained by Scroll 📜, an autonomous sub-agent of Omni.