v0.0.1 · phase 0 shipped 2026-05-20

The agentic CRM for creative agencies that needed one.

Foyer owns the client lifecycle from inbound conversation to delivered work. Polymorphic artifacts. Brand-as-context auto-injected into every creative call. A hosted MCP server so Claude Code, Cursor, and Codex can teammate with your workspace.

32 tables 11 build phases 10 ADRs locked 6 read tools live 5 channels in v1 ▸ verified end-to-end
01

Architecture

workspace ⇄ stage · one source of truth
Workspace

Agency cockpit

  • inbound_messages
  • artifacts_index
  • agent_runs
  • brand_kit_versions
  • audit_log
foyer projection
not copy
Stage

Client surface

  • pinned artifacts
  • themed in client brand
  • comment + light-edit
  • signed_url grants
  • talktrack walkthroughs
// ADR-003 — polymorphic API surface over typed tables type Artifact = { id: uuid, kind: "brief" | "naming_candidate" | "decision_record" | …, client_container_id: uuid, status: "draft" | "in_review" | "decided" | …, client_visible: bool, stage_pinned: bool, fields: kind_specific_payload, ... }
02

Build phases

~38 wks · two engineers · sequential where deps force it
−1
Decisions + naming
2 wks
done
00
Foundation
5 wks
done
01
Telegram ingestion
4 wks
build
1.5
Permission-aware Q&A
5 wks
sketch
02
Slack + Marketplace
5 wks
sketch
03
BrandKit Builder
5 wks
sketch
4a
WhatsApp window
5 wks
sketch
4b
SMS (10DLC)
3 wks
sketch
05
Creative agents
5 wks
sketch
06
External MCP
4 wks
sketch
0X
Signal
legal
gated
03

Architecture decisions

10 ADRs · all phase −1 locked
ADR-001

SaaS-only for v1

Self-host is a Phase 7+ paid-enterprise feature, not a v1 fork. One infra, one security surface, one trust story.

distribution
ADR-002

Postgres + pgvector, hot/cold split

Time-partitioned message tables. Typed cold tables per kind. `artifacts_index` view is the polymorphic surface.

storage
ADR-003

Polymorphic API over typed storage

One Artifact shape on the wire. Typed tables behind it. Adding a kind = new table + view extension.

api
ADR-004

Server-side agent runtime

Skills run on Foyer's runtime, not the caller. Every invocation lands in `agent_runs` with full token + cost + cache telemetry.

runtime
ADR-005

BrandKit as cached prefix

Anthropic prompt cache keyed on `brand_kit_version`. Triage agents skip injection; creative agents always get it.

context
ADR-006

Defer Signal to Phase X

Linked-device trust gap is legal + marketing, not engineering. Three gates before any Signal code lands.

channels
ADR-007

Per-seat + container-tier pricing

Client seats always free. AI overage at a publicly published per-run rate. No credits. No opaque throttles.

pricing
ADR-008

WorkOS + magic link + OAuth provider

Three constituencies, three auth paths, one observable surface. SAML for enterprise from day one.

auth
ADR-009

365-day audit, 7-year enterprise

Every write is an immutable row. Monthly partitions. Tiered to S3 after 1 year for enterprise retention.

audit
ADR-010

Dynamic skill registry

Skills discovered from a managed index at runtime startup. Anthology evolves without redeploy. Index membership is the gate.

extensibility
04

MCP tools — Phase 0

read-only · phase 6 unlocks writes behind OAuth scopes
list_clientsList ClientContainers the caller can read.live
get_clientOne ClientContainer with projects and brand-kit summary.live
get_brand_kitCurrent BrandKit version with logos, palette, voice, archetype, vocab.live
list_artifactsPolymorphic list across all Artifact kinds via the index view.live
get_artifactFetch one Artifact by (kind, id). Returns the full typed row.live
list_inbound_recentRecent inbound messages across all bound channels for a client.live

Run it locally in five commands.

Phase 0 ships as a pnpm monorepo. Docker compose boots Postgres + Redis. Drizzle handles migrations. The MCP server is one process and you can wire it into Claude Code today.

Quickstart
$ docker
compose up -d
$ pnpm
install
$ pnpm
db:migrate
$ pnpm
server:dev → :4000
$ pnpm
mcp:dev → stdio