AI Settings (BYOAI)
Per-environment bring-your-own AI provider configuration for report narratives.
AI Settings (BYOAI)
Sequel does not host a default LLM for report narratives. Each tenant configures their own provider and API key per environment. Narrative generation runs in the sequel-app BFF using credentials fetched from this service; payment-reconciler never writes narrative prose.
Concepts
- Enabled — master switch for AI report summaries in that environment
- Provider —
openai,anthropic, orazure_openai - Model — must be from Sequel’s recommended allowlist (
GET .../ai-settings/models) - API key — write-only; stored encrypted with
TENANT_AI_ENCRYPTION_KEY; responses exposehasApiKeyonly - Verification —
POST .../ai-settings/testprobes the provider and setsverified/failed
Verification probe
POST /tenants/:id/ai-settings/test performs a live, minimal request against the configured provider. Protocol versions used by the probe are pinned in code today:
| Provider | Probe request | Protocol / API version |
|---|---|---|
openai | GET https://api.openai.com/v1/models | OpenAI REST v1 (no dated api-version) |
anthropic | POST https://api.anthropic.com/v1/messages (max_tokens: 1) | Header anthropic-version: 2023-06-01 |
azure_openai | POST {baseUrl}/openai/deployments/{model}/chat/completions (max_tokens: 1) | Query api-version=2024-10-21 |
Notes:
- These pins apply to verification only. Report narration in sequel-app should use the same versions (or document any override) so Verify success matches Summarize behavior.
- Azure’s dated
api-versionmay be retired or reject newer deployment shapes over time; a failed Verify with a valid key often means this pin needs updating. azure_openairequiresbaseUrl(resource endpoint). The path uses the configured model value as the Azure deployment name.
Credentials (BFF only)
GET /tenants/:id/ai-settings/credentials returns the decrypted API key for server-side use (sequel-app BFF). Do not call this from browsers.
Access controls:
- JWT only — API keys are rejected (even with
read/write) - Callers — either:
- Admin JWT — Keycloak roles
tenant-admin/admin(own tenant) orsuper-admin, or - BFF service JWT — Keycloak confidential client (client credentials) with realm/client role
ai-credentials. No User/TenantUser row required; tenant/environment come fromX-Tenant-Id/X-Environment
- Admin JWT — Keycloak roles
- Acting user (service only) — BFF must send:
X-Acting-User-Id— end user who triggered SummarizeX-Acting-User-Email— end user email for audit
Missing/blank →403
- Verified only —
verification.statusmust beverified; otherwise400 - Audited as
TenantAiSettingsCredentials(never logs the raw key). Audit includesprincipalType(admin_user|bff_service), optionalclientId, and acting-user fields - Path tenant binding — path
:idmust equal the tenant resolved byTenantEnvironmentGuard(X-Tenant-Id/ JWT context). Mismatched URL vs context →403
PATCH rules (secrets)
- Changing
providerwithout a newapiKeyclears the stored key (do not reuse another vendor’s secret under a new provider). - Enabling AI after a provider change requires a fresh
apiKey. - Any provider / model / baseUrl / apiKey change resets verification to
unverified.
Environment
Requires TENANT_AI_ENCRYPTION_KEY (min 32 chars). Fail-closed if missing when storing or reading keys.
Related
- Reports — deterministic report APIs that expose
meta.aireadiness - Email Transport — similar BYO secret + test pattern