Skip to main content
Everything in Vexa composes from a handful of primitives. A unit of work — a dispatch — is one agent, in one container, over a person’s workspace, authorized by an identity token, fired by the scheduler. The data those agents grow on comes from meetings and docs. Don’t have a key yet? Hosted: sign in at vexa.ai/signin with a Google account and copy your key from your account page — free credit, no card required. Self-hosted: make all prints a key when the stack comes up.

Workspace

A git folder, stored in an (encrypted) bucket, with an id and an access mode (ro/rw). A dispatch mounts a list — typically system (ro) + company (ro) + user (rw). It holds knowledge, plans, and the agent’s session — all just files, with no dictated structure. git is the durable state and the undo. The knowledge itself lives in the kg/ subtree as an Open Knowledge Format (OKF) v0.1 bundle — one markdown file per entity at kg/entities/<type>/<slug>.md, YAML frontmatter on top, index.md listings for navigation. Knowledge-as-code: portable, diffable, and readable by any OKF consumer, not just Vexa. See Browse the workspace.

Meeting

One record from plan to transcript. A meeting is born in a user-owned intent status — planned ahead by hand or imported from a calendar (idle/scheduled) — is claimed in place by the bot lifecycle when the bot joins (requested → … → completed), and ends with its speaker-attributed transcript on the same record. Because it is one record, everything attached to the plan survives the meeting: the title, and the workspace binding — bind a meeting to a shared workspace and every member sees it (the plan, the live feed, the transcript). scheduled means the bot joins on its own at start time (the auto-join sweep; per-meeting opt-out). See Meetings.

Agent

A generic CLI coding agent selected by a runner (Claude Code is one; others and BYO-inference plug in the same way). It works the mounted workspace with a scoped toolbelt and commits. It is untrusted — outside the trust boundary — so it carries a signed token but enforces nothing. Its outbound capabilities (email, calendar, web) are integrations: cred-gated tools reached over MCP, never built into the backend. See Agents.

Container

The isolated, ephemeral unit an agent runs in, spawned by the runtime. Sub-second to start, reaped on idle, no egress except through brokered tools — thousands run in parallel with no lateral movement. Its live output streams to the client over a per-dispatch channel.

Identity

The chain of custody. The launcher proves itself (a user session, or a signed delegation grant for a schedule/integration); the identity service mints a short-lived signed dispatch token (subject = on whose behalf · launcher = who triggered · scope); the runtime attests the workload (SPIFFE/SPIRE); and every boundary verifies the token — never the agent. Tool calls exchange it for an audience-scoped credential (Keycloak / RFC 8693) at an MCP gateway, so the agent never holds a raw key.

Scheduler

Redis. The one mechanism that dispatches agents, on a trigger — a schedule entry (cron), an integration event (e.g. new email), or now (chat). It holds the user-manageable schedule; a meeting ending is just another event that dispatches an agent.
Two more primitives live one level down, in the code itself — they are how everything above is built:

Module

The unit of construction. A module owns exactly one concern and is the single source of truth for that concern — that’s the rule, everywhere. Capture bricks compose into the meeting bot, modules compose into services (each service a modular monolith), services compose into deployments. Because its concern is exact and singular, a module is tested — and debugged — fully in isolation against fixtures. Every module ships three things: the running code, the adversarial code (tests that harness it), and the data (goldens that validate it). Fixtures are collected from real meetings — real audio, speaker activations, environment metadata — so the harness replays reality. The full tree: Modules & Seams.

Contract

The only way modules join. A contract is defined once, rarely changed, and sealed — a sha256 per contract in contracts.seal.json, enforced in CI, so a seal can break loudly but a contract can never drift silently. Chains of modules joined by contracts test in integration with the same fixtures — a bug is reproduced at exactly the scale it lives at. All ports are deterministic for deterministic input, which keeps the verify loop simple enough for an AI agent to own. The registry (owner → consumers, all 16 seals): Modules & Seams.