Vision

Where Owlat is heading — from email platform to unified communication intelligence powered by AI agents.

Where Owlat is going

Owlat started as an email platform. But the problem we set out to solve — helping companies communicate effectively — is much broader than email. Companies drown in fragmented communication across dozens of tools, with no intelligence layer connecting them. We are building the system that treats all organizational communication as a single, AI-powered pipeline.

What exists today

Most of this is already built. Beyond email campaigns, transactional email, automations, and audience management, Owlat ships inbound email and channel processing, the multi-step agent pipeline with graduated autonomy, the verification queue with a live feedback loop, the knowledge graph with automatic extraction and true vector retrieval, a semantic file system with a live processing pipeline (including PDF text extraction), internal team chat, unified multi-channel messaging, ask-anything queries, a visualization agent that reads real account data, code-work tasks created from inbound feature requests, and a desktop app — all on top of a custom email renderer, a real-time Convex backend, and a custom MTA. The sections below describe the full picture and call out the smaller set of pieces still being wired.

The problem with company communication today

Fragmentation. Companies use separate tools for email marketing, customer support, internal chat, ticketing, and CRM. Each tool has its own data silo. When a customer emails about a booking, the support agent alt-tabs to three different systems to find the context they need to reply.

Manual routing. Humans spend their days classifying, routing, and drafting responses. Most of this work is mechanical: look up data, apply a template, send. The creative, judgment-heavy work — deciding on exceptions, handling escalations, building relationships — is buried under routine.

No institutional memory. The veteran support rep who knows "when customer X says Y, they actually mean Z" — that knowledge lives in one person's head. When they leave, it disappears. There is no system that learns from every interaction and makes that knowledge available to the entire organization.

Communication is not just outbound. Companies treat human-to-human conversation and automated messaging as separate concerns — one lives in Slack and email threads, the other in marketing tools. But all of it is organizational communication. It all generates knowledge, builds relationships, and drives decisions. Any system that only handles one side is incomplete.

The Communication Hub

Owlat is the single place where all organizational communication flows through — inbound and outbound, customer-facing and internal, human-to-human and AI-assisted.

Email and internal chat are fully wired today. SMS, WhatsApp, and generic third-party channels exist in the same unified pipeline, sharing one threading, identity, and status model. Conversational email now lives in the same unifiedMessages store as the other channels: inbound emails and confirmed agent replies are mirrored into unifiedMessages (idempotently, keyed by external message id), so the per-contact timeline interleaves email conversations with SMS/WhatsApp/generic/chat. Campaign, transactional, and automation sends are deliberately not mirrored — they're not conversation turns, and they already surface in the Activity tab via contactActivities. Inbound delivery and per-channel health monitoring are live, and inbound channel messages now flow through the same agent pipeline as email — the channel webhook projects the message onto an inbound row and starts the agent walker. Outbound sending for SMS and WhatsApp also has a built dispatch path (channels/outbound.ts dispatchOutbound decrypts the channel's credentials and calls the SMS/WhatsApp/generic adapters), but it is inert: nothing in the routing pipeline calls it yet, and it stays a no-op until an operator configures provider credentials. Voice is still being wired. The architecture is channel-agnostic: every message becomes a structured event in the same pipeline, regardless of where it originates or where it needs to go.

Email
SMS
Chat
Webhooks
Owlat
Content Filter
PassQuarantine
1
Prompt injectionDirect injection, delimiter attacks, role impersonation
2
Instruction smugglingHidden HTML, invisible text, image alt text
3
Content policySpam keywords, phishing URLs, prohibited content
4
Metadata strippingHTML → structured text, header filtering
Flagged messages quarantined — admin can release, confirm, or block sender
clean messages only
Knowledge Graph
FactsDecisionsEvents
Semantic searchGraph traversalSynthesized briefings
context & updates
Agent Pipeline
1
ContextRetrieve
2
ClassifyIntent
3
PlanAction
4
DraftGenerate
Every message processed by an AI agent
draft + confidence score
Verification Queue
AutoReviewEscalate
Org members see a prioritized list of verifications and approvals
Approve
Edit
Reject
Outbound DeliveryRoute to correct channel
Knowledge updated
Strict tenant isolation — every operation scoped to a single organization

Channel Adapters are pluggable connectors that normalize different communication channels into a unified message format. Adding a new channel — say, WhatsApp or a custom webhook — means writing an adapter, not redesigning the pipeline.

Human-to-human communication comes first

The pipeline does not replace direct conversation. When one person messages another — whether a colleague on the team or a customer over email — the message flows through and is delivered directly. No gates, no approval queues, no friction.

AI watches and enriches. It surfaces relevant context from the Knowledge Graph ("this customer had a billing dispute last month"), suggests follow-ups ("you promised to send the report by Friday"), and flags commitments that might otherwise be forgotten. For external adapters like email or SMS, the original message threading is fully preserved. The recipient sees a normal conversation in their inbox. They never need to know Owlat exists.

The agent pipeline is augmentation, not a gate. Humans talk to humans. AI makes those conversations more informed.

Owlat as its own channel

Owlat is also its own communication channel — a desktop app where organization members handle their communication in one place. The desktop app is built: a Tauri 2 + Rust shell that bundles the Owlat web UI, connects to one or more remote instances (multi-workspace), authenticates per workspace through the system browser with credentials in the OS keychain, and adds native notifications, a dock/taskbar unread badge, and owlat:// deep links.

Internal chat. Colleagues talk directly, in threaded rooms and direct messages with mentions. This is shipped today.

External communication. Conversations with contacts surface in the shared inbox, and the cross-channel unified timeline is shipped — a per-contact view (UnifiedTimelineTab) that interleaves conversational email (inbound messages and agent replies) with the SMS/WhatsApp/generic/chat channels from the same unifiedMessages store into one chronological thread. (Campaign/transactional/automation email is not in this store; it shows in the Activity tab.)

Quick queries. Organization members can ask the system free-form questions and get back a synthesized answer. The backend (quickQuery.ask, an authedAction gated on the ai.knowledge flag and the knowledge:read permission) fans out over both retrieval seams — hybrid vector + full-text search over Knowledge Graph entries (knowledge/retrieval.semanticSearch) and the semantic file store (semanticFileProcessing.semanticSearch, vector_files) — then asks the LLM to synthesize a grounded answer that cites each retrieved source by number. The returned sources span both kinds (knowledge entries and files); every retrieved title and body is scrubbed for prompt-injection and clamped before it reaches the model. The ask-anything box (QuickQueryPanel) lives on the knowledge dashboard today.

Owlat is a first-class adapter in the same architecture. It does not get special treatment — it follows the same pipeline, the same security model, the same audit trail as every other channel. This means anything built for one channel works for all of them.

The Agent Pipeline

Every inbound message flows through a multi-step processing chain. This is the technical heart of the system, and it runs today: each step is a module under apps/api/convex/agent/steps/, dispatched in order by the agent walker.

Before the chain even starts, an optional coalescing gate (agent/coalescing.ts) collapses rapid-fire bursts on the same thread — a CC chain with three replies in 30 seconds — into a single pipeline run on the latest message, archiving the superseded ones (their content still reaches the agent through thread history). It's opt-in via agentConfig.coalesceWindowMs; the default of zero means every message is processed immediately.

Step 1: Security scan. Before anything else, the message runs through the content security scanner — a deterministic pattern scan for prompt-injection, instruction-smuggling, and spam heuristics, now backed by a guard-tier LLM classifier (getLLMProvider('guard')) that catches novel or obfuscated phrasings. The LLM call fails open so a flaky model never blocks the pipeline. Anything flagged is quarantined rather than handed to the agent.

Step 2: Context retrieval. The agent assembles a briefing for everything relevant to this message: the contact profile, recent activity, and thread history, plus two semantic-retrieval passes — vector search over the Knowledge Graph (knowledge.retrieval.semanticSearch) for relevant typed facts and decisions, and vector search over the file store (semanticFileProcessing.semanticSearch) for the actual source documents. Both feed the [KNOWLEDGE] and [RELEVANT FILES] sections of a token-budgeted briefing — recent context verbatim, older context compacted — and the review queue records which compaction tier was used.

Step 3: Classification. The agent determines intent and urgency using a fast, cost-efficient model. Is this a billing question? A feature request? A complaint? An internal task?

Step 4: Draft generation. The agent produces a response grounded in the organization's configured tone and signature. This is not generic LLM output — it reflects how your organization communicates.

Step 5: Routing. The draft is scored for confidence, then routed in three safety-first tiers (agent/steps/route/index.ts): (1) if any circuit breaker is open, the message goes to human review no matter what; (2) when graduated autonomy is enabled, the per-category autonomy rule decides — a category with no rule is never auto-approved, and approvals charge that category's daily cap; (3) otherwise the legacy global setting applies — auto-reply on/off, one confidence threshold, one daily cap. Anything that doesn't clear its tier lands in the Verification Queue.

Graduated autonomy is live

Routing now consults the per-category autonomyRules (via autonomy.checkPermissionInternal) when the autonomy flag is on, and the feedback loop is closed: approve / edit / reject in the review queue calls autonomy.recordFeedback, which feeds the weekly adjustThresholds cron that tunes each category's threshold from human corrections. The single global threshold remains as a fallback when graduated autonomy is switched off. What's still on the way is parallel multi-intent branching — one message that needs several agents working at once.

Incoming message"Can I move my booking from Thursday to Saturday?"
Context RetrievalQuery the Knowledge Graph
Customer history
Account data
Past interactions
Org policies
Retrieves booking #4821, customer profile, Thursday availability data
ClassificationDetermine intent & urgency
Booking changeBillingComplaintFeature request
Intent: booking change · Urgency: normal · Sentiment: neutral
Action PlanningDecide what to do
1Fetch Saturday availabilityapi
2Draft confirmation emaildraft
3Update booking recorddata
Plan: check availability → draft reschedule confirmation → queue for review
Draft GenerationProduce grounded response
Re: Booking reschedule request
Hi Sarah, your booking has been moved to Saturday at 10am...
Uses org tone, includes booking details, Saturday confirmed available
RoutingDeliver or queue for review
Verification QueueHuman reviews draft
Auto-deliverHigh confidence, policy allows
Confidence: 92% · Routed to support queue · Assigned to agent on shift

The Verification Queue

For organization members, work becomes a list of verifications and approvals. This is not a limitation — it is the correct default. AI should draft, humans should decide. The agent queue is live in the dashboard inbox today.

Every agent action produces a reviewable artifact: a draft email, a proposed ticket, a data update. Members see a prioritized queue — not a firehose of notifications, but a focused list of items that need their attention.

  • One-click approve when the draft is ready to go
  • Edit and approve when it needs adjustments — manually or via chat with the agent
  • Reject when the agent got it wrong, with feedback that improves future drafts
  • Confidence scoring determines routing: high-confidence items can be auto-approved based on organizational policy
  • Full audit trail for every action, whether human-initiated or agent-initiated
3Pending
24Auto-approved today
8sAvg response
94%
Email Reply
12s ago
Re: Booking reschedule requestfrom Sarah Chen
Auto-approved
67%
Email Reply
2m ago
Re: Billing dispute — double chargefrom Marcus Rivera
82%
Ticket
5m ago
Feature request: bulk export contactsfrom Internal — Product
41%
Code Change
8m ago
PR #847: Add CSV export endpointfrom Coding Agent
High confidence— can auto-approve per org policy
Medium— human review recommended
Low— requires human decision
Full audit trail — every action logged with provenance: what knowledge was retrieved, what reasoning applied, who approved

Over time, organizations can expand the auto-approval boundary as they build confidence in the system. The goal is not to remove humans from the loop — it is to put them in the loop only where they add value.

The Knowledge Graph

Every organization accumulates knowledge: who their customers are, what has been decided, what happened last week, how things are done. Today, that knowledge is scattered across inboxes, documents, chat threads, and people's heads. The Knowledge Graph changes that. It is built — entries, typed relations, browse, search, true vector retrieval, automatic extraction from conversations and files, and confidence decay all ship today, with a dashboard UI.

Sarah ChenKnowledge subgraph
Fact
Pro PlanCustomer since 2024
Decision
Billing exceptionCredited $50 on Feb 12
Event
Upgrade to ProJanuary 2025
Preference
Prefers emailOver phone or chat
Event
3 support ticketsLast 30 days — API rate limits
Goal
Reduce response timeTarget: under 2 hours
Fact
Decision
Event
Preference
Goal
Hybrid RetrievalThree strategies merged via rank fusion
Semantic SearchVector similarity — finds conceptually related knowledge
"billing frustration"
Full-text SearchExact keyword matching for specific records
"invoice #12345"
Graph TraversalFollow relationships across the graph
"all interactions with Acme Corp"
Synthesized briefingWhat the agent actually receives — not a raw dump

Customer X has been on the Pro plan since 2024, upgraded in January. Billing exception granted in February ($50 credit). Prefers email. 3 recent tickets about API rate limits.

Typed knowledge, not raw data. The graph stores categorized knowledge — Facts, Decisions, Events, Preferences, Goals, plus relationships and action items — each with a confidence score and optional expiry. Entries are linked to each other through typed relations (supports, contradicts, supersedes, relates to, causes, blocks), and to contacts and conversation threads. Retrieval is now genuinely semantic: knowledge.retrieval.semanticSearch embeds the query and runs the vector_knowledge index, so agents pull the relevant entries when handling a message — facts about the customer's plan and past billing decisions, not every message that happens to contain the word "billing."

Self-building from conversations. Extraction is now wired into the live pipeline. When a message finishes classification, knowledge.extraction.extractFromMessage mines it for typed entries — for inbound email and for inbound channel messages (SMS/WhatsApp/generic) that flow through the agent. It's idempotent (re-runs don't duplicate entries) and best-effort (a failed extraction never fails the message). Files feed the graph too: once a file is processed, extractFromFile distills its text into entries.

Knowledge maintenance. The graph is a living system, not a write-only log. Entries carry confidence, a last-validated timestamp, and an optional expiry, so stale knowledge can decay and be revalidated over time.

Still on the way

The graph's deeper reasoning is the part still being built. Extraction stores entries but does not yet do near-duplicate vector merging or automatically create the typed relations between them (saveEntry dedupes only exact source+title matches). Maintenance is still decay-and-expiry only — there's no contradiction resolution or validation-boost pass yet. There are no memory-as-tools the agent can call to write back to the graph mid-draft. And internal member-to-member chat is not mined for knowledge — only inbound pipeline messages are. Browse, search, typed entries, relations, vector retrieval, automatic extraction, and decay are fully functional.

Data isolation is non-negotiable

Each organization's knowledge graph is completely isolated. Agent context windows never mix data from different organizations. This extends the same multi-tenancy model Owlat uses today — every record scoped by organization — to the knowledge layer. Strict tenant boundaries are enforced at the storage, retrieval, and inference layers.

Internal communication and task agents

The same pipeline that handles "customer emails about a booking" also handles internal work. The architecture is identical — the agents are different.

Code-work tasks. Owlat tracks code-work tasks as first-class artifacts with their own lifecycle — queued, claimed, branched, testing, completed with a pull request, failed. They're now created automatically: a message the agent classifies as a feature_request schedules codeWorkTasks.createFromInbound (gated on the inbox.codeTasks flag, idempotent on the message), so a customer request flows to engineering without a manual step.

Code review in the same queue. A customer feature request flows to engineering automatically — the agent classifies it and creates the code-work task. The other end of the loop is wired too: a GitHub merge webhook (webhooks/githubHttp.ts, HMAC-verified, POST /webhooks/github) advances the matching task to merged via markMergedByPrUrl when its PR lands. The eventual goal is review in a developer's queue, same pattern as a support draft.

Still on the way

The two ends of the loop — inbound-to-task and merge-to-done — are wired; the middle isn't fully autonomous yet. Actually running the coding agent that turns a task into a pull request still needs the code-worker sidecar and OpenCode running alongside the backend. Until that's deployed, tasks are created and merges are recorded automatically, but the code itself is produced by hand or by an operator-driven worker.

Agents pause, ask, and resume

Agents do not guess when they encounter ambiguity. If a coding agent hits an unclear requirement, or a support agent encounters a policy edge case, or a data agent needs approval for a sensitive operation — the agent pauses. It formulates a structured question with full context and places it in the relevant person's queue.

The question is not a bare notification. It includes what the agent was doing, what it already knows, what the options are, and what it recommends. The human answers — sometimes with a single click, sometimes with a detailed response. The agent then resumes from exactly where it stopped, incorporating the answer.

Multiple agents can have pending questions for the same person. The system prioritizes them by urgency and impact, just like any other queue item. Over time, the system learns from recurring questions and proposes organizational policies to eliminate them — turning ad-hoc decisions into codified rules.

The Visualize Agent

A specialized agent that takes a natural-language prompt and builds an interactive visual component — charts, dashboards, data tables, progress trackers. Not static images or screenshots, but self-contained HTML/CSS/JS that renders in a sandboxed iframe, with hover effects, tooltips, and animations. This agent is built today, and generated visualizations can be pinned to the dashboard.

Ask "Show me our email delivery rates for the last 30 days" and the Visualize Agent picks an appropriate chart type and produces an interactive component.

Reads real data for known datasets

The Visualize Agent now reads your real account data for a fixed allowlist of four datasets — email delivery (30d), agent health, contact growth, and campaign performance — each backed by a hand-written, read-only fetcher (visualizationAgent.ts). When a prompt maps to one of those, the chart uses your actual numbers; for anything else it falls back to clearly-labeled illustrative sample data ("Illustrative example — not your account data"). There is no free-form query channel — only the fixed allowlist. The Visualizations page now has a dataset picker to opt a chart into one of these live datasets, and a per-chart refresh action that re-runs the fetch on demand.

Internal knowledge queries. Team members ask the system questions: "What was our refund policy decision last quarter?" or "How did we handle the last outage?" quickQuery.ask retrieves across both the Knowledge Graph and the file store and asks the LLM to synthesize a grounded answer that cites each source it used — shipped today via the ask-anything box (see Quick queries above).

The key insight: for all organization members, regardless of role, work converges to a single interface — a queue of verifications, approvals, and answers to provide.

The File System

Every organization has files — contracts, invoices, presentations, design assets, documentation. Today, they live in Google Drive, Dropbox, SharePoint, email attachments, and Slack threads. Finding the right file means remembering where it was saved, or who sent it, or what it was called. Owlat's file system works differently — and it is built: upload, browse, search, tagging, version history, and a live AI processing pipeline (text extraction, summaries, embeddings, auto-tags, semantic search) all ship today.

Storage and retrieval. Files are stored with their provenance — who uploaded them, whether they came from an upload, an email attachment, or an agent — and linked to the contacts and conversation threads they relate to. You browse and search files in the dashboard rather than navigating folder hierarchies.

Version history with provenance. The system tracks not just what changed in a file, but who shared it and where it came from, with each version pointing back to its predecessor. When three versions of a contract float around, you can trace the revision chain.

Tags and semantic organization. Files carry manual tags plus AI-generated auto-tags and embeddings, so they can be organized by meaning rather than by filename. Auto-tags are also inherited from the conversation a file was shared in — drop a file into a "Q3 financials" thread with Acme Corp and it picks up q3-financials / acme-corp automatically — and each new version carries a coarse changeSummary describing how it differs from its predecessor.

Processing pipeline. When a file is uploaded, semanticFiles.create schedules semanticFileProcessing.processFile, which extracts text, generates a title/summary/tags via the LLM, computes an embedding, and feeds the content into the Knowledge Graph. A backfillUnprocessed cron (every 15 minutes) re-schedules any recently-created file that slipped through without an embedding. PDF text extraction is real (via the unpdf parser, falling back to a placeholder on error).

Still on the way

Two narrower gaps remain. Non-PDF binaries — Word, Excel, images — still return a placeholder rather than extracted text or OCR. And there is no auto-ingest of inbound email attachments or agent-generated files into the file pipeline yet — only user uploads are indexed. Tag reconciliation and merge-suggestions are also not built.

Contextual retrieval for agents. Files are part of the agent's context-retrieval step today: the step runs semanticFileProcessing.semanticSearch (a true vector_files index search) alongside the knowledge query, so when an agent handles a customer inquiry about their contract it can surface the actual document, not just a knowledge graph node about it. The file system and the Knowledge Graph are complementary by design: the graph stores structured facts, the file system stores the source material.

Files are not a separate product

The file system is a layer in the same architecture. Files are scoped to the organization, searchable through the same retrieval pipeline, governed by the same permissions model, and logged in the same audit trail. There is no separate "file management" interface — files surface where they are needed, in conversations, in agent context, in search results.

The CRM Hub

Owlat already manages audiences and contacts for email campaigns. The next step is making it the definitive source of truth for every relationship the organization has — not just email subscribers.

Every contact type in one system. Customers, potential customers, investors, partners, vendors, press contacts, advisors. The CRM does not care about the label. Every person or company the organization interacts with is a contact, with a unified profile that spans all channels and all history.

Communication-native. Traditional CRMs require a separate "update the CRM" step — log the call, add the note, change the deal stage. In Owlat, the CRM builds itself from actual communication. When you email an investor, the interaction is logged automatically. When a customer complains in chat, the sentiment is captured. When a deal progresses through a conversation thread, the pipeline updates. The CRM is not a database you maintain — it is a view of your communication history.

Relationship intelligence. The Knowledge Graph powers relationship insights that go beyond "last contacted" timestamps. The system tracks sentiment trends, outstanding commitments ("you promised a proposal by next Tuesday"), recurring topics, response patterns, and relationship health scores. When you are about to meet with a contact, the system briefs you — not with a flat activity log, but with a synthesized summary of the relationship.

Contact unification across channels. The same person might email from their work address, text from their personal phone, and message from a chat handle. Contact identity resolution is built: each contact can carry multiple typed identities (email, phone, WhatsApp, social handles), and lookups across channels go through those identities. Exact-identifier duplicates are now auto-merged: an autoMergeDuplicates cron (every 6 hours) merges contacts that share an exact strong identifier — the same email or phone — and folds all identities, relationships, threads, and messages into the survivor. Ambiguous matches still surface as merge suggestions for a member to confirm, since a near-match shouldn't be merged without human judgment.

The part still on the way is automatic relationship extraction: contactRelationships stores operator-entered links between contacts, but nothing yet mines conversations to derive them automatically.

Security model

AI-powered communication systems introduce real risks. We take them seriously. The security model is built around four layers.

Tenant isolation. Every query, every agent context window, every knowledge graph traversal is scoped to a single organization. There is no shared state between tenants. This extends Owlat's existing organizationId-scoped data model to every new subsystem. An agent processing messages for Organization A has zero visibility into Organization B's data.

Agent sandboxing. Agents that connect to external systems — booking APIs, code repositories, CRMs — operate within credential-scoped sandboxes. An agent processing a support ticket for Customer A cannot access Customer B's data, even if both customers belong to the same organization. Credentials are managed securely, never exposed in agent context, and scoped to the minimum necessary permissions. Channel-config secrets are encrypted at rest: updateChannelConfig schedules encryptAndPersistConfig, which wraps the config in an AES-256-GCM envelope (lib/credentialCrypto) before it touches the row, and the dispatch path decrypts only when it needs to send.

Audit and explainability. Every agent action is logged with full provenance: what knowledge was retrieved, what classification was made, what draft was produced, and who approved it. If an agent makes a mistake, you can trace exactly why — and that trace feeds back into improving future behavior.

Graduated autonomy. Organizations control how much autonomy agents have, per category. You can enable auto-approval for specific categories — simple acknowledgments, routine status updates, standard booking confirmations — each with its own confidence threshold and daily cap, and a category with no rule is never auto-approved. The routing step consults these rules live, and the feedback loop is closed: every approve / edit / reject in the review queue tightens or relaxes the relevant threshold through the weekly tuning cron. Three circuit breakers guard the pipeline — llm_failure, confidence_degradation, and rejection_spike — each evaluated every rollup with open → half_open → closed hysteresis; while any breaker is open, nothing auto-sends. The system earns trust incrementally. It does not assume it.

Tenant Isolation
Agent Sandbox
Audit Trail
Agent
Every agent operates within nested security boundaries. No layer can be bypassed.
Tenant IsolationEvery operation scoped by organizationId
Org A
Org B
Org C
Agent SandboxingCredential-scoped, minimum permissions
Booking API
CRM read
Admin API
Audit & ExplainabilityFull provenance on every action
Knowledge retrieved
Reasoning trace
Approval chain
Graduated AutonomyOrganizations control the trust boundary
Auto-approve simple
Review complex
Escalate sensitive
Example: Agent processes support email for Customer A
Tenant gate — agent context loaded for Org X only
Sandbox — booking API credentials scoped to Customer A
Customer B's booking data — access denied
Draft produced — full trace logged to audit
Routed to verification queue — human reviews before send

The Data Model

Everything described above — channels, conversations, agents, files, knowledge, contacts — connects through a single data model. This is not a collection of separate features bolted together. It is one graph of entities and relationships, scoped to the organization, where every surface (the desktop app, the verification queue, the CRM, the file system) is a different view of the same data.

Data ModelEntity relationships
TenantRoot scope
Core
OrganizationTenant root — all data scoped here
Actors & ChannelsParticipants
People
MemberOrg employees with roles & permissions
Contacts
ContactCustomers, investors, partners, vendors
Communication
ChannelEmail, SMS, Chat, Owlat, Webhooks
Intelligence
AgentAI workers — draft, classify, visualize
ThreadsUniversal hub
Communication
ConversationThreaded message stream across channels
ArtifactsWhat conversations produce
Communication
MessageHuman or agent authored content
Content
FileEmbedded, tagged, version-tracked
Intelligence
Knowledge NodeFacts, decisions, events, preferences
Core & People
Contacts
Communication
Content
Intelligence
Key design principles
Single tenant rootEvery entity scoped to Organization — no cross-tenant leakage
Conversation as hubMembers, Contacts, and Channels all meet in Conversations — the universal thread
Knowledge accrues passivelyMessages, Files, and Contacts automatically feed the Knowledge Graph — no manual entry
Agents are first-class actorsAgents participate in Conversations, produce Messages, query Knowledge, and ask Members for decisions

The model has four layers. The tenant root (Organization) scopes everything — no entity exists outside an organization. Actors and channels (Members, Contacts, Channels, Agents) are the participants. Conversations are the universal hub where all participants meet, regardless of channel. Artifacts (Messages, Files, Knowledge Nodes) are what conversations produce. Every layer connects downward, and intelligence flows back up — agents read knowledge to enrich conversations, files feed into the knowledge graph, and the knowledge graph informs every future interaction.

The roadmap

RoadmapWhat ships and when
Now
Email & Agent PlatformBuilding now
Email campaignsTransactionalAutomationsAudiencesInbound + agent pipelineVerification queueKnowledge graphFile systemTeam chatMulti-channel storeVisualize agentDesktop app
Shipped: sending, audiences, inbound processing, and the agent framework
Building in the open

We document architectural decisions for each phase as ADRs in our Developer docs, just as we have for the custom email renderer, Convex backend, custom MTA, process architecture, and model routing.

Why we are building this

Every company eventually builds an ad-hoc version of this: a support inbox connected to a CRM connected to a ticketing system connected to Slack, held together with Zapier and hope. That patchwork works until it does not. The knowledge is scattered. The routing is manual. The response time is slow. And when someone leaves, their knowledge leaves with them.

The file system, the CRM, the desktop app, the visualization engine — these are not separate products. They are surfaces on the same data model, connected by the same agent pipeline, governed by the same security model.

We think the right answer is a system that treats communication as a first-class data type, routes it intelligently, and lets humans focus on the decisions that actually require human judgment — not the mechanical work of looking up data and filling in templates.

Owlat began as the email layer. Most of the communication layer is now built — the inbound pipeline, the agent pipeline with graduated autonomy and a live feedback loop, the verification queue, the knowledge graph (automatic extraction + true vector retrieval), the file system (live processing pipeline + PDF extraction + agent retrieval), internal chat, multi-channel messaging that feeds the same agent pipeline, ask-anything queries, the desktop app, and a visualization agent reading real account data all ship today. The remaining wiring is narrower and called out section by section: outbound SMS/WhatsApp go-live (the dispatch path exists but needs provider credentials and a routing caller), running the coding agent for end-to-end code-work, deeper knowledge reasoning (in-extraction relation creation, contradiction resolution), automatic CRM relationship extraction, and a handful of UI follow-ups. The architecture we have built — a real-time backend, a custom MTA, a block-based content system, and multi-tenant isolation — is the foundation for everything described here.

We are not building another inbox. We are building the communication intelligence layer that every organization needs but nobody has built yet.