Architecture Overview
High-level architecture of AgentOwl — package layout, runtime model, data stores, API surface, and ingress paths.
AgentOwl is built as a CLI-first, worker-backed inbound communications platform.
At a high level:
- Operators use the CLI to manage desired state
- The Worker exposes the API and persists configuration
- Providers send inbound traffic directly to Worker ingress endpoints
- Ingress handlers normalize events and enqueue them
- Queue consumers resolve routing and dispatch to tenant endpoints
Current package layout
packages/shared
Shared types and protocol contracts used by both the CLI and the Worker:
- Canonical resource types such as
Tenant,Binding,Endpoint,Route, andPolicy - Event envelope definitions
- ID generation and error helpers
- Internal protocols for ingress, queue, dispatch, and reconciliation
packages/worker
Cloudflare Worker application that currently combines several responsibilities behind one service boundary:
- Control-plane API under
/v1/* - Ingress endpoints under
/ingress/* - Queue consumer for deferred processing
- Runtime config publication to KV
- Early reconciler/provider integration code
packages/cli
Operator-facing CLI that talks to the Worker API. It covers:
- Tenant lifecycle
- Endpoint, binding, route, and policy management
- Event inspection and replay
- Log tailing
- Config validation and diff
- Version and compatibility checks
Runtime model
The current runtime model follows the main design even though some roles are still co-located in one Worker deployment.
CLI -> Worker API -> D1 / KV
Provider webhooks -> Worker ingress -> Queue -> Queue consumer -> Tenant endpointMain data stores and bindings
- D1: durable storage for tenants, bindings, endpoints, routes, policies, events, and config snapshots
- KV: published runtime configuration used by ingress resolution
- Queues: decouple provider-facing ingress from downstream dispatch
- sendmailrs filesystem spool: temporary on-disk spool on the OVH VPS used by the SMTP server before dispatch; no database or Redis on the VPS
API surface
The Worker entrypoint currently registers routes for:
- Tenants
- Endpoints
- Bindings
- Routes
- Policies
- Events and replay
- Version and compatibility
- Provider sync and drift checks
- Config validate, diff, and publication
- Logs tail
- SMS and voice ingress
- Cloudflare email ingress through the Worker email handler
- SMTP email ingress via
/ingress/smtp(receives normalized events from sendmailrs)
Ingress paths
AgentOwl accepts inbound traffic through three ingress paths:
- Cloudflare Email Routing — Cloudflare forwards inbound email to the Worker's
email()handler. - Telnyx SMS / Voice — Telnyx webhooks POST to
/ingress/smsand/ingress/voice. - Self-hosted SMTP (sendmailrs) — A Rust binary on an OVH VPS receives mail on port 25 and POSTs normalized events to
/ingress/smtp.
All three paths normalize into a canonical event envelope, persist to D1, and enqueue for downstream dispatch.
Self-hosted SMTP ingress (sendmailrs)
sendmailrs is a Rust binary deployed on an OVH VPS running Ubuntu 24.04. It receives email directly on port 25 via MX DNS records pointing to the VPS.
The processing pipeline has nine modules:
- Network / TLS — accepts connections and optionally upgrades to STARTTLS.
- SMTP session — implements the SMTP state machine (EHLO, MAIL FROM, RCPT TO, DATA).
- Recipient validation — checks the recipient against known tenants and agents.
- Spool — writes the raw message to a filesystem spool directory.
- MIME parse — decodes MIME structure, extracts body parts and attachments.
- Sender auth — validates SPF, DKIM, and DMARC alignment.
- Normalize — maps the parsed message into a
NormalizedEmailEvent. - Dispatch — POSTs the JSON event to the Worker's
/ingress/smtpendpoint. - Observability — structured logging and metrics for each pipeline stage.
On the Worker side, /ingress/smtp persists the event to the D1 events table and enqueues it for downstream dispatch, identical to the other ingress paths.
Tenant subdomain routing: the recipient address encodes tenant and agent identity. For example, hello@beta.agentowl.dev routes to tenant beta, agent hello.
Hosted inbox pages: each tenant gets a rolling 24-hour inbox view at {tenant}.agentowl.dev/inbound/email with auto-refresh, served by the Worker's pages handler.
VPS resource model: sendmailrs intentionally avoids external dependencies on the VPS. The spool is filesystem-based, rate limits are held in memory, and tenant configuration is cached from the Worker API. There is no Redis or database on the VPS.
Design priorities visible in the codebase
- Multi-tenant scoping across persisted resources
- Queue-first ingress for operational resilience
- Canonical event envelopes for replay and downstream dispatch
- Optimistic concurrency via
resource_versionandetag - Provider abstraction without fully hiding provider-specific concerns
Current limitations
The repository already includes pieces of the longer-term design, but some are partial:
- Provider reconciliation is present but still early and not fully productionized
- Some operational flows are stubs or simplified implementations
- Deployment is still a single Worker boundary rather than independently deployable roles
- Examples and external integration guides are still thin