What we've shipped, in reverse chronological order.
No roadmap promises, no marketing copy — just the concrete increments that have landed on main. Dates use ISO format.
·Wave 2: dark mode, i18n, runtime + release infra, ~200 new tests
Six parallel agent packs: dark mode + command palette + i18n, product feature polish, per-tenant runtime settings, desktop + mobile release CI, axe-core sweeps, and off-site backup + staging tooling.
- Dark mode across the app (Tailwind
darkMode: "class", cookie + localStorage +prefers-color-scheme), toast notifications, proper 404 and 500 pages, dynamic favicons. - Hand-rolled
en/hiinternationalisation with a language switcher on the settings page, plus a Cmd+K command palette with fuzzy matching over the in-app actions. - Chat session delete and rename, audit log CSV export (admin-only streaming, 100k row cap), six new enquiry filter parameters, and a schema migration that actually populates
payloadandresolved_by_user_idon approvals. - Per-tenant agent runtime settings: model override, system prompt suffix, rate limits per minute / hour, daily token budget, default currency. Cost tracker writes every turn to
session_costsand enforces the daily budget. GET/PATCH /api/tenant-settingsadmin-only, plus a trial-balance report and tool result cache (read-only allowlist, tenant-scoped, 5-minute default TTL)..github/workflows/desktop-release.yml(Tauri build matrix for macOS, Linux, Windows with PR dry-run) andmobile-release.yml(EAS build + OTA update).- Passport OCR scaffold in the mobile app with a real ICAO 9303 MRZ parser (and a stubbed capture path until a provider is picked). First vitest suite wired into
apps/mobile. - Accessibility sweep with
@axe-core/playwrightacross 19 pages (surfaced 8 pre-existing colour-contrast violations as a UX backlog), an opt-in real-Postgres integration fixture, Locust load scenarios, and a getting-started walkthrough plus per-driver setup pages. - Off-site Postgres backups via an rclone wrapper (AWS S3, Backblaze B2, Cloudflare R2, Wasabi, MinIO, DigitalOcean Spaces), a staging environment bootstrap script with systemd unit templates, and a secret rotation CLI for the JWT / DB / Redis / metrics / KMS secrets.
- Dark mode across the app (Tailwind
·Wave 1: team onboarding, auth hardening, observability, agent-to-ledger, ~100 new tests
Five parallel packs that unblock real team usage and close the loop between the agent runtime and the ledger.
- Tenant invites with roles, accept-invite flow, and an
/app/settingspage for admins to manage members. PATCH /api/auth/profile, a password reset flow (Redis token, log-to-stdout email stub), and three new public pages:/app/forgot-password,/app/reset-password, and/app/accept-invite.- Password strength validator with a 58-entry blocklist, TOTP 2FA with
pyotpand a/auth/sign-in-totpsecond-factor endpoint, plus an API key table with scopedvy_-prefixed keys. - GitHub Actions CI (pytest + vitest + Playwright + marketing build), automated Postgres backups via a systemd timer with a 30-day retention, and a runbook documenting 17 deploy gotchas from previous sessions.
- Sentry integration across the API, web app, and marketing site with PII-scrubbing
before_sendhooks and a tenant-tagging middleware, plus a Prometheus/internal/metricsendpoint gated to localhost or a shared token. - Mobile sidebar drawer (hidden below 768px with a hamburger overlay), enquiries filter bar now responsive, four
loading.tsxskeletons for the main list pages. - Audit log viewer with admin-only RBAC, an approvals-to-audit hook so granted and rejected decisions land in the trail, and a passenger resolver that mints UUIDv7 identifiers correctly.
draft_invoicetool for the accounting agent (approval-gated, auto-numbering per tenant,Decimal-only math), the/reports/trial-balanceendpoint, and a demo tenant seeder that populates five enquiries, three invoices, three bills, five ledger accounts, three balanced journal entries, and five audit events — idempotent via a marker row.
- Tenant invites with roles, accept-invite flow, and an
·Demo account and chat path fixes
A public demo login and three fixes to the chat path that were biting browser-side SDK consumers.
- Demo account
[email protected]exposed on the sign-in page with a “Use demo credentials” pre-fill link. - Fixed SDK consumers (web, mobile, desktop) to pass an
/api-prefixed base URL so the browser-side SDK reaches FastAPI through nginx. - Fixed
createSessionto post an empty body (the API derives tenant and actor from the bearer JWT).
- Demo account
·Approvals inbox and enquiry lifecycle
A finance-side approvals inbox and a first-class enquiry object with a full lifecycle.
- New
/api/approvalsand/app/approvals— list pending tool-call approvals, approve or reject from a finance inbox, 15-minute TTL, cross-tenant 404. - New
enquiriestable and full CRUD:/api/enquiriesand UI at/app/enquiries(list, filter, search, create, detail, edit, promote-to-chat). - Status lifecycle
new → quoted → bookedwithcancelledas a terminal state. - Migration
0006_enquiries.
- New
·Real-data reports
Receivables and payables reports now query real ledger tables instead of fixture data.
invoices,bills,ledger_accounts,journal_entriestables added (migration0005_invoices_ledger).build_journal_entryhelper enforces debit == credit in code, not via DB triggers./reports/receivablesand/reports/payablesnow query real data with 0-30 / 31-60 / 61-90 / 90+ aging buckets.
·Eight bug fixes from the error-path test pass
A focused sweep of error-path regressions found during an explicit failure-mode test run.
- Tool output schema validation with retry-once on schema mismatch.
- Anthropic
RateLimitError/APIConnectionErrorretry with exponential backoff (Retry-Afterhonored). - Sign-in gates on
email_verifiedwith distinguishable 401 codes (email_not_verifiedvsinvalid_credentials). - Amadeus JSON decode errors mapped to typed driver errors (no raw exceptions through the boundary).
- BSP India HAF parser airline allow-list (164 IATA carriers) plus a regex pre-check.
- VFS MFA / 2FA / OTP signals routed to
PermanentError(was being miscategorized as auth failure). pending_approvals.expires_atandstatus="expired"enum value with lazy sweep.resolve_approval(actor_tenant_id)cross-tenant guard.
·Hotels domain
A hotels_holidays agent, a canonical hotel data model, and a real-HTTP TBO driver for search and re-pricing.
- New
hotels_holidaysagent with approval-gated booking. - New canonical hotel models:
HotelRoom,HotelRate,HotelProperty,HotelSearchResult, and aBoardBasisenum. - New TBO driver — search and price re-check wired with real HTTP; booking is stubbed pending sandbox credentials.
- Migration
0003_passengersplusStoragePassengerResolverend-to-end. - Postgres session stores wired by default when
VOYAGENT_DB_URLis set.
- New
·In-house auth replaces Clerk everywhere
Auth is now owned end-to-end in the platform — password hashing, JWTs, refresh-token rotation, and a Redis-backed denylist.
- Argon2id password hashing.
- HS256 JWT access tokens (1h) plus opaque refresh tokens (30d, single-use rotation).
- httpOnly cookies on web (
voyagent_at), SecureStore on mobile and desktop. - Redis-backed JWT
jtidenylist for revocation. - Email verification flow stubbed (
/send-verification-email,/verify-email); real delivery is pending a provider decision. - Migrations
0002_inhouse_auth.
·Native deployment
Docker Compose retired in favor of systemd-supervised native processes on a single host.
- Migrated off Docker Compose to systemd-supervised processes.
- Three units:
voyagent-api(uvicorn :8010),voyagent-web(next start :3011), andvoyagent-marketing(next start :3012). - Native Postgres 16 (shared host instance) and native Redis 7.
- Single-host nginx plus certbot for TLS.
- Removed Clerk, Temporal, and Docker from docs and configs.
·Foundations
The baseline platform the entries above build on — canonical model, driver contracts, agent loop, and multi-tenant isolation.
- In-process agent loop with prompt caching (Anthropic SDK).
- Three domain agents:
ticketing_visa,accounting, andhotels_holidays. - Canonical Pydantic v2 data model: flights, hotels, visa, finance, lifecycle.
- Five driver skeletons: Amadeus, TBO, Tally, BSP India, and VFS — all conforming to typed driver contracts.
- Real-time chat with SSE streaming and approval-gated tool calls.
- Multi-tenant isolation enforced at every storage query.
- Tests: roughly 750 Python (pytest) and 47 TypeScript (vitest).
For a deeper roadmap see IMPLEMENTATION-PLAN.md. For architecture decisions see docs/DECISIONS.md.
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.