Architecture

Six layers. Adapter-first. No AI magic.

The AI is not the hard part — the adapter layer is. Get vendor-agnosticism right and onboarding a new GDS or accounting system becomes a driver, not a redesign.

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.

Ready to retire the 15-tool workflow?

Voyagent is in early access. We onboard a small number of agencies each month with white-glove setup of drivers, data, and approval workflows.