Layer 0 — Platform Services
Multi-tenancy, RBAC, audit log, approval workflow engine, credential vault, observability, billing.
Every other layer assumes this exists. Roles (agent / senior_agent / accountant / admin / auditor) are scoped per domain and per action. Every side-effect tool call is recorded immutably for CA/auditor review.
Layer 1 — Canonical Domain Model
One internal vocabulary. Enquiry, Passenger, Itinerary, Fare, PNR, Booking, VisaFile, Voucher, Invoice, JournalEntry, BSPReport, Reconciliation.
Vendor fields never leak upward. Adding a new GDS means writing a driver that maps its API to the canonical Fare / PNR / Booking — no agent change required. The model is versioned strictly.
Layer 2 — Driver / Adapter Layer
FareSearch, PNR, Hotel, Transport, VisaPortal, Accounting, Payment, BSP, Card, Bank, Messaging, Document, Statutory.
One driver per external system. Each publishes a capability manifest declaring exactly what it supports. The orchestrator selects drivers at runtime based on tenant configuration and capability availability — so if a tenant's accounting system can't auto-post, Voyagent gracefully falls back to a Tally-importable XML.
Layer 3 — Tool Runtime
Canonical tools with side_effect, reversible, and approval_required flags.
Irreversible side-effects — issue_ticket, post_journal_entry, submit_visa, disburse_payment — always require explicit human confirmation. Reversible actions (hold PNR, draft quote) run freely.
Layer 4 — Agents
Orchestrator, three domain agents (ticketing_visa, hotels_holidays, accounting), cross-cutting agents (document_verifier, reconciler, reporter).
The Anthropic Python SDK with prompt caching enabled from day one, wrapped in our own in-process orchestrator running inside services/agent_runtime and streamed to clients over FastAPI SSE. No Temporal in v0 — ADR D11 supersedes the workflow-engine portion of D9.
Layer 5 — Clients
Web (Next.js), Desktop (Tauri 2), Mobile (Expo / React Native).
Desktop is the power-user client — it hosts integrations that need local OS access (GDS terminals, Tally ODBC/XML, smart-card readers, local printers). Web is the thin SPA. Mobile handles reports, approvals, and a remote-control relay paired to a desktop session over WebSocket.
Deployment — single Ubuntu host, native processes
systemd-supervised processes on one Ubuntu 22.04 box. No Docker in the request path. No Temporal. No Kubernetes.
- Three systemd units: voyagent-api (uvicorn on :8010), voyagent-web (next start on :3011), voyagent-marketing (next start on :3012).
- Native Postgres 16 on 127.0.0.1:5432 and native Redis 7 on 127.0.0.1:6379 — one shared host instance, not a container.
- Single host nginx with certbot for TLS. The earlier two-nginx layout has been retired.
- Cookie-based auth on web (voyagent_at, httpOnly); SecureStore on mobile and desktop. Multi-tenant isolation rides a JWT-derived tenant_id on every query.
- Pydantic v2 to OpenAPI to TypeScript codegen is on the roadmap, not shipped.
Read the full architecture doc
The detailed version — driver contracts, canonical-model design rationale, invariants — lives in the repo alongside the code.