From ravi-dev
Documentacao completa da arquitetura do Ravi. Use quando precisar: - Entender como o sistema funciona end-to-end - Modificar componentes existentes - Adicionar novos subsistemas - Debugar fluxos de mensagem - Onboarding no codebase
How this skill is triggered — by the user, by Claude, or both
Slash command
/ravi-dev:architectureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Ravi é um sistema multi-agent construído sobre o Claude Agent SDK que orquestra conversas em múltiplas plataformas via omni (WhatsApp, Discord, Telegram).
Ravi é um sistema multi-agent construído sobre o Claude Agent SDK que orquestra conversas em múltiplas plataformas via omni (WhatsApp, Discord, Telegram).
Repositório: /Users/luis/dev/filipelabs/ravi.bot
Runtime: Bun | DB: SQLite | PubSub: NATS JetStream | AI: Claude SDK
[WhatsApp/Discord/Telegram]
-> omni API (child process)
-> NATS JetStream (stream MESSAGE)
-> OmniConsumer (subscriber JetStream)
-> nats.emit("ravi.{sessionKey}.prompt")
-> RaviBot (Claude SDK query)
-> nats.emit("ravi.{sessionKey}.response")
-> Gateway
-> OmniSender (HTTP POST /api/v2/messages/send)
-> omni API
-> [WhatsApp/Discord/Telegram]
Orquestra startup de todos os subsistemas:
~/.ravi/.envlocal/server.ts)local/omni.ts)Shutdown tem timeout global de 15s (force-exit se travar).
Spawna nats-server com JetStream habilitado (-js). Armazena em ~/.ravi/jetstream/.
Inclui recovery automático: se startup falhar (WAL corrompido), limpa storage e reinicia.
Spawna omni API como child process (bun). Gerencia:
~/.ravi/omni-api-key)Subscriber de dois streams JetStream do omni:
MESSAGE (filter: message.received.>) → prompts de agenteINSTANCE (filter: instance.>) → QR codes, conexãoComportamento:
start() aguarda consumers ficarem prontos (timeout 60s, continua em background)msg.ack() apenas após handler suceder; msg.nak() em erro (retry automático)ravi.config.changedHTTP client para omni REST API (@omni/sdk). Métodos:
send(instanceId, to, text) — textosendTyping(instanceId, to, active) — indicador de digitaçãosendReaction(instanceId, to, messageId, emoji) — reaçãosendMedia(instanceId, to, path, type, filename, caption) — mídiaRetry com backoff exponencial (3x, 1s/2s/3s). Só retenta TypeErrors (rede) e 5xx.
Subscriptions internas do ravi (não gerencia canais):
ravi.*.response → OmniSender.send()ravi.outbound.deliver → OmniSender.send()ravi.*.claude → typing heartbeat → OmniSender.sendTyping()ravi.outbound.reaction → OmniSender.sendReaction()ravi.config.changed → sync REBACProcessa prompts usando Claude Agent SDK.
Fluxo:
ravi.*.promptAbort control:
Resolução de rota (prioridade):
thread:ID — mais específica (thread dentro de grupo)group:ID ou padrão de telefoneinstance.agent (tabela instances)Policy resolution (por mensagem):
route.policy → instance.dmPolicy/groupPolicy → legacy account.* settings → "open"
Session keys:
agent:{agentId}:{scope}:{peerId}
agent:main:main # Todas DMs (scope=main)
agent:main:dm:5511999 # Por contato
agent:main:whatsapp:group:123456 # Grupo
agent:main:whatsapp:main:group:123456:thread:abc # Thread
agent:main:outbound:queueId:phone # Outbound
Instâncias (tabela instances):
Entidade central que une canal + agent + policies. Substitui namespace account.* de settings.
interface InstanceConfig {
name: string; // nome da conta omni (ex: "main", "vendas")
instanceId?: string; // UUID do omni
channel: string; // "whatsapp" | "matrix" | ...
agent?: string; // agent padrão desta instância
dmPolicy: "open" | "pairing" | "closed";
groupPolicy: "open" | "allowlist" | "closed";
dmScope?: DmScope;
}
Arquivos:
router/resolver.ts - Resolve rota → session key (matchRoute, findRoute)router/session-key.ts - Constrói/parseia session keysrouter/sessions.ts - CRUD de sessões (SQLite)router/config.ts - Carrega RouterConfig (agents + routes + instances)router/router-db.ts - Camada de banco (CRUD agents, routes, instances, settings)outbound/)Campanhas de mensagens proativas com processamento round-robin.
Fluxo:
nextRunAtQualificação: cold → warm → interested → qualified/rejected
triggers/)Automação event-driven disparada por eventos do sistema.
Fluxo:
cron/)Jobs agendados com suporte a múltiplos formatos.
Schedules: cron expression | interval ("30m") | daily ("09:00") | at (one-time)
Fluxo: Timer → job due → emite prompt → calcula próximo run
heartbeat/)Check-ins periódicos de agents dentro de horários ativos.
Fluxo:
HEARTBEAT_OK = silencioso, qualquer outro texto = envia pro canalcli/commands/sessions.ts)Mensagens entre sessões (inter-session communication).
Comandos: sessions send | sessions inform | sessions execute | sessions ask | sessions answer
Duas fontes:
~/.cache/ravi/plugins/~/ravi/plugins/Build time: gen-plugins.ts escaneia src/plugins/internal/ e gera internal-registry.ts
Runtime: discoverPlugins() extrai internos + escaneia user dir → passa para SDK
Intercepta chamadas Bash e valida permissões via REBAC.
Checa agentCan(id, "execute", "executable", exec) pra cada executável parsed.
Extrai memórias antes do SDK compactar contexto.
Lê COMPACT_INSTRUCTIONS.md do agent, roda modelo barato em background, atualiza MEMORY.md.
@Group({ name: "agents" })
class AgentCommands {
@Command({ name: "list" })
list() { ... }
@Command({ name: "create" })
create(@Arg("id") id: string) { ... }
}
runWithContext({ sessionKey, agentId, source }, async () => {
const ctx = getContext();
});
~/.ravi/ravi.db - SQLite: agents, routes, sessions, contacts, settings
~/.ravi/.env - API keys e env vars
~/.ravi/omni-api-key - API key para omni (auto-gerada)
~/.ravi/jetstream/ - JetStream storage (nats-server)
~/.ravi/logs/ - Logs do daemon
~/ravi/{agent-id}/ - Diretórios dos agents (CLAUDE.md, MEMORY.md)
~/.cache/ravi/plugins/ - Plugins internos extraídos
~/.claude/sessions/ - SDK session files (JSONL)
OMNI_DIR=/path/to/omni-v2 # obrigatório para canal WhatsApp/Discord/Telegram
OMNI_API_PORT=8882 # default
DATABASE_URL=postgresql://... # banco do omni
NATS_PORT=4222 # default
_emitId + _instanceId previne duplicatas@@SILENT@@ suprime emissão pro canalnpx claudepluginhub filipexyz/ravi --plugin ravi-devAutomate Botstar operations via Rube MCP and Composio's Botstar toolkit. Always discover tools first with RUBE_SEARCH_TOOLS.
Guides setting up external messaging channels (WhatsApp, Telegram, Discord, iMessage) for Claude Code agents via plugins. Useful for enabling communication outside the CLI.