Oxagen Docs

Brand kits

How Oxagen workspaces define palette, typography, spacing, logos, and voice — and how every agent-authored document, spreadsheet, slide deck, and PDF picks up the active kit automatically.

A brand kit captures the visual identity of a workspace — colour palette, typography scale, spacing tokens, logo, favicon, watermark, voice document, footer. Every artifact tool in the Artifacts family reads the workspace's active kit before materialising the output, so a deck the agent produces comes out looking like your company's brand.

The BrandKit row

Every kit lives in org.brand_kits and carries:

ColumnTypeMeaning
namestringDisplay label.
is_defaultbooleanAt most one active row per workspace is true; enforced by a partial unique index so archiving a kit frees the slot.
is_lockedbooleanUI-only edit lock — the dashboard requires an explicit unlock gesture before persisting edits. The database does not interpret it.
palette_jsonJSONBFree-form palette tokens. Conventional keys: primary, secondary, background, foreground, accent, muted, error.
typography_jsonJSONBFree-form typography tokens. Conventional keys: family, scale, weights, display_family, mono_family.
spacing_jsonJSONBFree-form spacing tokens. Conventional keys: gap, radius, shadow.
logo_document_idFKThe primary logo document in app.documents.
favicon_document_idFKThe favicon document.
voice_doc_markdowntextBrand voice document body. The agent reads it before composing copy.
footer_markdowntextFooter snippet rendered on artifact exports.

The *_json columns are intentionally free-form JSONB — the product iterates the conventional key set without a DDL cycle. Renderers tolerate missing keys and fall back to vendor defaults.

Typed assets

Beyond the two FK-bound slots on the kit row, org.brand_kit_assets holds an arbitrary number of secondary documents per kit. The column kind is a typed enum constrained by a CHECK:

kindUsed for
logoSecondary or alternate-orientation logos.
watermarkWatermark image laid behind slide / doc content.
faviconAdditional favicon sizes.
fontCustom font file the renderer registers before generation.
swatchStandalone palette swatch images for design QA.
imageAny other branded image the kit needs (header banner, sticker, etc.).

Each asset row points at an app.documents row — the binary lives in the documents store, the asset row is just typed metadata.

How kits flow into generation

Every artifact capability resolves the active kit at call time:

  1. Lookup. branding.get_active_kit(ctx) reads the workspace row where is_default = true AND is_deleted = false. Zero rows is fine — generation falls back to the vendor's defaults.
  2. Map to vendor primitives. Each provider has a kit-mapper that translates JSONB tokens into Google Slides theme colours, Google Docs named styles, Google Sheets cell formats, etc.
  3. Insert. The provider applies the mapped styles before writing the spec's content.

The mapping is deterministic — the same kit produces the same vendor styling on every call. Re-running the same docs.create_from_spec against the same kit with an Idempotency-Key returns the cached (doc_url, external_id).

Capability surface

CapabilityCreditsWhat it does
branding.list_kits0List every kit in the workspace with is_default and is_locked flags.
branding.get_active_kit0Return the active default kit including palette / typography / spacing tokens and asset references.
branding.set_active_kit1Mark a kit as the active default. Requires owner role. The previous default is demoted in the same transaction.

Kit creation and editing happen in the dashboard at Settings → Branding — the agent can read kits and switch the active one, but it does not author new ones. This is a deliberate separation: brand assets are an org-level decision; the agent should never silently invent a new palette.

Voice doc

voice_doc_markdown is loaded into the agent's system prompt when generating copy for the workspace — landing pages, sales briefs, customer-facing reports. The agent reads it as a tone guide rather than as data to extract, so it never quotes the voice doc verbatim in an artifact unless you explicitly ask.

Storage

Brand kits live alongside the artifacts they style:

  • org.brand_kits — kit row.
  • org.brand_kit_assets — typed asset rows.
  • app.documents — every binary the kit references (logo, favicon, watermark, fonts, swatches).

Workspace-scoped RLS applies to both org.brand_kits and org.brand_kit_assets, so a workspace can never read another workspace's kit even if it knew the id.

Audit

Each create / update / set-active writes an audit.event row with action='brand_kit.created' | 'brand_kit.updated' | 'brand_kit.activated', the before / after JSON in the row body, and the chain hash linking it to the previous mutation. See Events, triggers, and audits.


Artifacts overview · Document generation · Spreadsheets · Slides · Artifact storage

On this page