Domain model
The Autonomous Inbox data model has nine first-class resources plus a few internal tables (revoked tokens, revoked client certs). Everything is multi-tenant by Workspace — every row hangs off exactly one workspace, and every API request is automatically scoped to the workspace derived from the JWT sub claim.
Relationship diagram
Workspace
│
┌───────────┬─────────┼─────────┬───────────┐
▼ ▼ ▼ ▼ ▼
Inbox Email Agent Webhook SystemEvent
│ │ │ │
│ │ │ └── WebhookDelivery
│ │ │
│ └── AgentRun ──┘
│
└── (optional bound Agent)
Resources at a glance
| Resource | Purpose | Lifecycle |
|---|---|---|
| Workspace | Multi-tenant root, mirrors a Kobana account | Created via kobana-app provisioning hook |
| Inbox | A routable email address + processing policy | Created via API; deactivated rather than deleted |
| A received message + processing state | Created by SES ingestion or POST /emails | |
| Agent | An LLM configuration (model, system prompt, skills) | Created via API |
| AgentRun | A single execution of an agent against an email | Created by the worker; read-only via API |
| Webhook | A subscription to one or more SystemEvent slugs | Created via API |
| WebhookDelivery | An attempt to POST a webhook payload | Created by the dispatcher; read-only via API |
| SystemEvent | An immutable record of a domain event | Emitted by handlers/workers; read-only via API |
Shared fields
Every resource exposes:
| Field | Type | Notes |
|---|---|---|
id | UUID v4 | Internal identifier. |
created_at | ISO 8601 | Set at creation. |
updated_at | ISO 8601 | Updated by Prisma on every change. |
deleted_at | ISO 8601 | null | Soft-delete marker. |
Some resources additionally expose:
| Field | Type | Notes |
|---|---|---|
external_id | UUID v4 | Stable identifier from the originating system (Workspace, Inbox, Agent). |
metadata | JSON | System-set metadata. |
custom_metadata | JSON | Free-form, never inspected by the system. |
Soft delete
Resources that support deletion are soft-deleted: deleted_at is set, but the row stays in Postgres. Queries filter by WHERE deleted_at IS NULL through a Prisma middleware. Re-creating a row that conflicts with a soft-deleted one (e.g. same email on Inbox) returns 409 conflict — restore the original via internal tooling rather than recreating.
Idempotency and uniqueness
| Resource | Unique constraint |
|---|---|
| Workspace | external_id |
| Inbox | email (global, not per-workspace) |
message_id (the SES messageId) | |
| Agent | external_id |
| Webhook | — (label is not unique) |
Email.message_id uniqueness is what makes the SES ingestion handler idempotent: SNS may retry the same notification, but the second insert hits the unique constraint and the handler returns 200 immediately.