Gateway runtime
The Axum HTTP server. Hosts the REST API, WebSocket and SSE transports, the
embedded dashboard, webhook ingress, and an in-process MCP server. Default
bind is http://127.0.0.1:42617.
Conceptual overview of the runtime, gateway, channels, operator, memory, and security layers and how they fit together.
Revka is a Rust-first, audit-first agent runtime that ships as a single binary
(revka). That binary embeds a REST + WebSocket gateway, a React dashboard, a
cron scheduler, a channel supervisor, and the CLI — and it coordinates two Python
MCP sidecars (Kumiho memory and the Operator) plus optional cloud agents. This
page explains the layers, what runs where, and how a message becomes an agent
turn.
Read this once before you wire up channels, providers, or workflows — it gives you the mental model the rest of the docs assume. If you just want to get running, start with Installation and the Quickstart, then come back here.
Revka is layered. Each layer has a narrow job and a clear boundary with the layers around it.
Gateway runtime
The Axum HTTP server. Hosts the REST API, WebSocket and SSE transports, the
embedded dashboard, webhook ingress, and an in-process MCP server. Default
bind is http://127.0.0.1:42617.
Channel supervisor
Connects the agent to messaging platforms (Telegram, Discord, Slack, Matrix, and more). Runs inside the daemon alongside the gateway, heartbeat, and cron.
Operator + Kumiho sidecars
Two Python MCP servers. The Operator orchestrates sub-agents, teams, and workflows; Kumiho is the persistent graph-memory backend.
Security policy
A defence-in-depth model — autonomy levels, command allowlists, path sandboxing, OTP gating, emergency stop, and a tamper-evident audit log — evaluated before any tool runs.
Everything starts from the single binary. You build or download revka, run a
command (revka gateway, revka daemon, or revka agent), and the binary
brings up the layers that command needs.
These three commands all start the runtime, but they bring up different combinations of components. Pick the one that matches what you are doing.
| Command | What it runs | Use it when |
|---|---|---|
revka gateway | The HTTP gateway only: REST API, dashboard, WebSocket, SSE. No channels. | You want the dashboard and API but no messaging integrations. |
revka daemon | The gateway plus all configured channels, the heartbeat, and the cron scheduler. | You are running Revka as a full, always-on agent. |
revka service | Installs and manages the daemon as an OS service (launchd, systemd, or OpenRC). | You want Revka to survive reboots and run unattended. |
# Gateway only — dashboard + API at http://127.0.0.1:42617revka gateway
# Full runtime — gateway + channels + heartbeat + cronrevka daemon
# Run as a managed background servicerevka service install && revka service startrevka service statusrevka service logs --followThe gateway binds to 127.0.0.1:42617 by default. Override with --host and
--port. On first start with pairing enabled, the gateway prints a one-time
pairing code; a client exchanges it for a bearer token via POST /pair. See
Pairing & authentication for the full
flow.
A few endpoints are always available without a bearer token, by design:
GET /health — public liveness for load balancers (no secrets leaked).GET /metrics — Prometheus text format, only when [observability] backend = "prometheus".POST /webhook — generic agent ingress (optionally secured with X-Webhook-Secret).POST /admin/shutdown, GET|POST /admin/paircode — localhost-only admin endpoints (remote callers get 403).A runtime adapter is the layer that decides how an agent actually executes on the host. The same agent definition can run in different modes depending on your deployment and resource constraints — foreground process, gateway-only, managed service, or container. The mode you choose maps directly onto the gateway / daemon / service commands above.
| Mode | How to run it |
|---|---|
| Foreground runtime | revka daemon |
| Gateway only | revka gateway |
| Managed service | revka service install && revka service start |
| Docker / Compose | docker compose up -d |
For the full treatment of runtime modes, adapter selection, and resource limits, see Runtime modes, adapters & resource limits and Docker, Compose & one-click PaaS.
Revka keeps the orchestration brain and the memory backend out of the Rust binary and runs them as two Python MCP sidecars. The Rust daemon launches and supervises both over stdio, and exposes their tools to agents through the Model Context Protocol.
The Operator is a Python 3.11+ MCP server, spawned fresh per agent chat session by the daemon. It gives the agent tools for spawning and coordinating sub-agents, running declarative YAML workflows, managing teams, recording outcomes, and talking to other agents over the A2A protocol. Operator code can change without restarting the daemon.
The Operator pairs with a Node.js Session Manager sidecar that manages agent SDK sessions (Claude SDK and Codex) and relays live agent events to the gateway’s WebSocket channel — this is what drives the dashboard’s live workflow view. Without the Session Manager, orchestration still works but the live execution overlay receives no events.
[operator]mcp_path = "~/.revka/operator_mcp/run_operator_mcp.py"See Operator MCP, Spawning & coordinating agents, and the Workflows overview.
Revka does not persist memory locally. At the Rust level the memory binding
is always a no-op (NoneMemory); all persistence is delegated to the Kumiho MCP
sidecar, a client stub that talks to the Kumiho graph-memory control plane.
Setting backend = "kumiho" or backend = "none" both resolve to that no-op
binding — any other backend name (sqlite, qdrant, …) is rejected at startup.
[memory]backend = "kumiho" # or "none"; both run NoneMemory locally
[kumiho]enabled = truemcp_path = "~/.revka/kumiho/run_kumiho_mcp.py"api_url = "https://api.kumiho.cloud"space_prefix = "Revka"memory_project = "CognitiveMemory"Agents use a two-reflex pattern: call kumiho_memory_engage before
responding to load relevant context, and kumiho_memory_reflect after
responding to store structured captures (decisions, facts, preferences, and so
on) with provenance edges. Memories are stored as items in hierarchical spaces,
each with immutable revisions.
Learn more in the Memory overview, Kumiho setup, and Graph model: spaces, items & provenance.
The channel supervisor runs inside revka daemon. It connects the agent to
messaging platforms and routes inbound messages into the agent loop and agent
replies back out. Channels fall into two delivery classes:
/webhook, …) require
a public HTTPS endpoint so the platform can POST to your gateway.revka channel list # show configured channels and statusrevka channel start # start the channel supervisorrevka channel doctor # diagnose channel configurationAllowlist semantics are consistent across channels: an empty allowlist denies
everyone, "*" allows everyone, and an explicit list allows only the named
users. Inbound messages pass through prompt-injection scanning before they reach
the LLM, and outbound messages pass through credential-leak detection before
delivery.
See the Channels overview and Connect a messaging channel.
When a message arrives — from a channel, the dashboard chat, the /webhook
endpoint, a cron job, or revka agent — Revka runs it through a tool-using
agent loop:
Ingress. The message enters via a channel, WebSocket (/ws/chat), SSE, a
webhook, or the CLI. Inbound text is scanned for prompt injection.
Engage memory. The agent calls kumiho_memory_engage to pull relevant
prior context from the Kumiho graph and inject it into the prompt.
Reason and call tools. The LLM reasons and issues tool calls. Every tool call is checked against the security policy before it executes.
Iterate. Tool results feed back into the loop until the task is done or a
limit (max_tool_iterations, default 60) is reached. Tools can run in
parallel when [agent] parallel_tools = true.
Reflect. The agent calls kumiho_memory_reflect to persist decisions and
facts as captures with provenance edges.
Respond. The reply streams back to the originating surface. Outbound text is scanned for credential leaks; the turn is recorded to the audit log.
Key knobs live in [agent] in ~/.revka/config.toml:
| Key | Default | Meaning |
|---|---|---|
max_tool_iterations | 60 | Max tool-call rounds per turn |
max_history_messages | 1000 | Conversation history retained |
max_context_tokens | 1050000 | Context window budget |
parallel_tools | true | Allow concurrent tool calls |
For a deeper walkthrough, see The agent loop, Autonomy levels & approvals, and Sessions & conversation state.
Security is enforced in independent layers, each evaluated before a tool is allowed to act. No single bypass defeats the model.
Autonomy level
read_only, supervised (default), or full. Controls whether the agent
can act at all, and whether risky commands need approval.
Command allowlist
A quote-aware shell parser splits compound commands and validates each segment, blocking chaining, subshells, redirections, and risk-classified commands.
Path sandboxing
File operations are pinned to the workspace and allowed_roots, with
traversal, symlink-escape, and forbidden-path checks.
OTP & emergency stop
TOTP gates sensitive actions; revka estop freezes tools, kills network, or
blocks domains instantly, with OTP-gated resume.
Beyond these, Revka encrypts secrets at rest (ChaCha20-Poly1305), hashes pairing tokens (SHA-256), supports optional OS-level sandbox backends (Firejail, Bubblewrap, Landlock, sandbox-exec, Docker), and applies per-domain trust scoring that automatically downgrades autonomy when an agent keeps making mistakes in a domain.
Every security-relevant event is appended to a tamper-evident audit log — a SHA-256 Merkle hash chain, optionally HMAC-signed. You can query and verify it:
# Query recent audit eventscurl "http://127.0.0.1:42617/api/audit?limit=50&event_type=command_execution" \ -H "Authorization: Bearer rk_<token>"
# Verify chain integrity (detects tampering)curl "http://127.0.0.1:42617/api/audit/verify" \ -H "Authorization: Bearer rk_<token>"[autonomy]level = "supervised" # read_only | supervised | fullblock_high_risk_commands = truerequire_approval_for_medium_risk = trueworkspace_only = true
[audit]enabled = true # tamper-evident Merkle hash chainDig into the details in the Security model, Policy, commands & sandboxing, OTP gating & emergency stop, and the Audit log.