Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
293 lines (246 loc) · 14.6 KB
/
Copy path.env.example
File metadata and controls
293 lines (246 loc) · 14.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# =================================================================
# Kairo — single root .env.local for the entire monorepo
#
# cp .env.example .env.local (fill in real values, never commit)
#
# How each app reads this file:
# apps/dashboard — Vite envDir set to "../../" so it reads from here
# apps/landing — Next.js traverses up to the monorepo root
#
# Validated by packages/env/index.ts (shared) and each app's env.ts.
# Never access process.env or import.meta.env directly — use env.ts.
# =================================================================
# === SHARED (packages/env) =======================================
# Validated for: api, landing (server-side)
# Supabase project URL — server-side usage
SUPABASE_URL=https://your-project.supabase.co
# === MODEL ROUTING (server only; KAI-63) ===========================
# Remote models use the team's own provider key (BYOK) configured in Gateway.
# Gateway retries a failed BYOK request with its system credentials and offers
# no switch to disable that; Kairo logs a warning for each response served that
# way. Configure only models the BYOK key supports.
# All remote inference uses this credential. Never use a VITE_* key.
# AI_GATEWAY_API_KEY=
# Gateway identifiers use provider/model, as listed in its live catalog.
# AI_GATEWAY_MODEL= # default generative model
# AI_GATEWAY_TEXT_MODEL= # optional text-only default
# AI_GATEWAY_DECISION_MODEL=typesafe-ai/jev # replace with any native decision model
# Serving providers default to the model owner. Override by model ID or owner:
# AI_GATEWAY_PROVIDER_ROUTES={"moonshotai":["moonshotai"],"typesafe-ai":["typesafe-ai"]}
# Provider restriction does NOT disable Gateway's BYOK-to-system credential fallback.
# Transport defaults: gateway | ollama. Legacy anthropic/jev aliases use Gateway.
INTELLIGENCE_PROVIDER=gateway
# Native typed questions and probabilities: decision. Structured generation: language.
CLASSIFICATION_MODE=decision
TEXT_PROVIDER=gateway
EMBEDDING_PROVIDER=ollama
# Domain capabilities; evaluated at operation boundaries. Existing indices are preserved.
# FEATURE_FLAG_ENABLE_EMBEDDINGS=true
# FEATURE_FLAG_ENABLE_EMBEDDING_GENERATION=true
# FEATURE_FLAG_ENABLE_EMBEDDING_INDEXING=true
# FEATURE_FLAG_ENABLE_EMBEDDING_RETRIEVAL=true
# Per-role overrides take precedence and select Gateway.
# AI_GATEWAY_CLASSIFICATION_MODEL= # must match CLASSIFICATION_MODE
# AI_GATEWAY_KNOWLEDGE_DECISION_MODEL= # native decision capability
# AI_GATEWAY_EVIDENCE_ANALYSIS_MODEL= # language capability; analyzes evidence before decisions
# AI_GATEWAY_KNOWLEDGE_DRAFT_MODEL= # language capability
# AI_GATEWAY_VALIDATION_MODEL= # native decision capability; verifies source support and business context
# FEATURE_FLAG_ENABLE_EMAIL_KNOWLEDGE=false # propose business facts and articles from incoming mail
# AI_GATEWAY_REPLY_MODEL= # language capability
# AI_GATEWAY_ASSISTANT_MODEL= # language capability + tools
# AI_GATEWAY_EMBEDDING_MODEL= # embedding capability; must produce EMBEDDING_DIMENSIONS
# Ollama is the only local exception: loopback/private LAN, no redirects.
# OLLAMA_BASE_URL=http://localhost:11434
# OLLAMA_MODEL=granite4.1:3b
# OLLAMA_EMBEDDING_MODEL=nomic-embed-text-v2-moe
# Dimensions of the embedding model, for every provider. Must equal the database
# vector columns (768); the API refuses to start otherwise. Changing the model
# means migrating the columns and re-embedding, not only this value.
# EMBEDDING_DIMENSIONS=768
# Knowledge retrieval and affected-ticket selection: minimum cosine similarity
# (0.70-0.90) and most tickets evaluated per approved knowledge version.
# EMBEDDING_SIMILARITY_THRESHOLD=0.80
# KNOWLEDGE_CANDIDATE_LIMIT=25
# Optional independent language classifier: gateway:provider/model or ollama:model.
# INTELLIGENCE_ENSEMBLE=
# FEATURE_FLAG_ENABLE_JEV_SHADOW_CLASSIFICATION=true
# FEATURE_FLAG_ENABLE_JEV_CANARY=true
# FEATURE_FLAG_JEV_CANARY_MAILBOXES=
# Native classifications remain proposals until calibration is validated.
# FEATURE_FLAG_ENABLE_AUTO_APPROVAL_RECOMPUTE=true
# FEATURE_FLAG_ENABLE_KNOWLEDGE_CANDIDATES=true
# Both flags are needed to use the ticket assistant.
# FEATURE_FLAG_ENABLE_TICKET_ASSISTANT=true
# VITE_FF_ENABLE_ASSISTANT_TAB=true
# ================================================================
# GOOGLE OAUTH client secret — server-only, NEVER expose to the client
GOOGLE_CLIENT_SECRET=your-google-client-secret
# Tier 1 onboarding fast-path (apps/api/src/functions/pipeline/tier1-fast-path.ts)
# How many of the most recent inbox messages to scan on first Gmail connect.
FAST_PATH_SCAN_SIZE=30
# Minimum relevant classifications before the wizard "Continue" button enables.
# Does NOT cap how many emails Tier 1 classifies — that's FAST_PATH_SCAN_SIZE.
FAST_PATH_CONTINUE_THRESHOLD=3
# Concurrent *runs* of the whole Tier 1 function (e.g. two accounts onboarding
# at the same time) — not concurrent LLM calls within one run.
FAST_PATH_CONCURRENCY=3
# Concurrent classifyEmailWithMeta calls WITHIN a single tier1/tier2/tier3 run.
# Local Ollama has a real ceiling here (OLLAMA_NUM_PARALLEL, usually 1-4 —
# exceeding it queues/timeouts requests); Remote models' per-minute rate limits
# comfortably absorb much higher values. Keep low for local dev, raise per
# environment once measured, not guessed.
FAST_PATH_LLM_CONCURRENCY=2
# Consecutive classification failures before a run's circuit breaker opens and
# stops attempting new messages for the rest of that run (in-flight ones still
# finish) — the backend is down/saturated, don't burn the rest of the batch on it.
FAST_PATH_CIRCUIT_BREAKER_THRESHOLD=3
# Total classification attempts a message can accumulate (across all 5 pipeline
# call sites + the retry sweep cron) before classification_status becomes
# 'failed_permanent'. Not the same as withRetry's own 4 internal attempts.
CLASSIFICATION_MAX_ATTEMPTS=5
# === OBSERVABILITY (KAI-126) ======================================
# Validated for: api (packages/intelligence reads these directly)
# See docs/observability.md to stand up the local stack and get real keys.
# Langfuse (self-hosted, docker-compose.observability.yml) — LLM tracing.
# Unset → tracing is a no-op, classification/embeddings work unaffected.
LANGFUSE_BASE_URL=http://localhost:3003
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...
# ClickStack (HyperDX all-in-one, docker-compose.observability.yml) —
# app observability. Unset → OTel SDK stays disabled.
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_SERVICE_NAME=kairo-api
# --- docker-compose.observability.yml only (NOT read by packages/env) ---
# Required to start the Langfuse containers. Generate with `openssl rand -hex 32`.
# LANGFUSE_SALT=
# LANGFUSE_ENCRYPTION_KEY=
# LANGFUSE_NEXTAUTH_SECRET=
# Optional overrides (compose has safe local-dev defaults otherwise):
# LANGFUSE_POSTGRES_PASSWORD=
# LANGFUSE_CLICKHOUSE_PASSWORD=
# LANGFUSE_MINIO_SECRET=
# LANGFUSE_REDIS_PASSWORD=
# Headless init (KAI-189) — auto-provisions the org/project/user/API-key pair
# on first boot, no manual signup needed. Set these to the SAME values as
# LANGFUSE_PUBLIC_KEY/LANGFUSE_SECRET_KEY above (you choose them, they don't
# need to come from Langfuse — any pk-lf-.../sk-lf-... string works).
# LANGFUSE_INIT_PROJECT_PUBLIC_KEY=
# LANGFUSE_INIT_PROJECT_SECRET_KEY=
# LANGFUSE_INIT_USER_EMAIL=local@kairo.dev
# LANGFUSE_INIT_USER_PASSWORD=
# ClickStack ingestion key (docker-compose.observability.yml only — NOT the
# same as the Personal API access key scripts/observability/hyperdx-dashboard.ts
# needs, which HyperDX doesn't support headless-provisioning; get that one
# from the UI after first signup — Team Settings -> API & Agents).
# HYPERDX_API_KEY=
# === FEATURE FLAGS (packages/feature-flags) =======================
#
# Server-side, boolean (runtime-overrideable):
# FEATURE_FLAG_<UPPER_SNAKE_NAME>=true|false
# Defaults: false unless overridden here.
#
# Server-side, numeric (runtime-overrideable):
# FEATURE_FLAG_<UPPER_SNAKE_NAME>=<positive integer>
# Defaults: see packages/feature-flags/src/flags.ts. Invalid/unset → default.
#
# Client-side (build-time, Vite/framework-compiled):
# VITE_FF_<UPPER_SNAKE_NAME>=true|false
# Defaults: false unless overridden here.
# Used by SPA clients that can't access process.env at runtime.
#
# Client-side, numeric (build-time, Vite/framework-compiled):
# VITE_FF_<UPPER_SNAKE_NAME>=<positive integer>
# Defaults: see apps/dashboard/src/lib/feature-flags.ts. Invalid/unset → default.
# Baked in at build time — a new value only takes effect on the next deploy.
# KAI-201: show real-time detection UI in the onboarding wizard (step 2)
# When OFF (default): wizard skips detect step → goes straight to company-name form
# When ON: shows live classification metrics polled from /bff/classification/progress
# FEATURE_FLAG_ENABLE_DETECTION_UI=true
# KAI-246: send acknowledgement.html on new ticket creation via outbox
# When OFF (default): customer doesn't get auto-confirmation with ticket number (KAI-T-n)
# When ON: sends "Kairo Support" template immediately on was_created=true, skips out-of-hours reply
# FEATURE_FLAG_ENABLE_TICKET_ACKNOWLEDGEMENT=true
# KAI-248: how often (in minutes) the Gmail history.list poll cron fans out
# one event per active Gmail integration. Default: 5. The cron schedule is
# registered at app startup, so a new value takes effect on the next deploy/restart.
# FEATURE_FLAG_GMAIL_POLL_CRON_INTERVAL_MINUTES=5
# Vercel build variable, not read by the app: set it on the kairo-api project, or its Hono build fails type-checking.
VERCEL_EXPERIMENTAL_BACKENDS=1
# === LANDING (apps/landing) ======================================
# Validated by apps/landing/env.ts via @t3-oss/env-nextjs
# Supabase public vars (safe to expose to the browser)
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY=your-publishable-key
# Google OAuth client ID (safe to expose to the browser)
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
# Base URL of the landing/auth app (used for OAuth redirects)
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Where to send users after login — /dashboard in prod, Vite URL in dev
NEXT_PUBLIC_DASHBOARD_URL=http://localhost:5173/dashboard/
# KAI-126/KAI-189: ClickStack (OpenTelemetry) browser tracing. Unset -> disabled.
NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
# === KELAN (apps/kelan) ============================================
# Validated by apps/kelan/env.ts via @t3-oss/env-nextjs
# Supabase public vars (safe to expose to the browser)
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
# Optional — base URL of the kelan app itself
# NEXT_PUBLIC_KELAN_URL=http://localhost:3002
# KAI-126/KAI-189: ClickStack (OpenTelemetry) browser tracing. Unset -> disabled.
NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
# === DASHBOARD (apps/dashboard) ===================================
# Validated by apps/dashboard/src/env.ts via @t3-oss/env-core
# Supabase public vars (Vite exposes VITE_* to the browser)
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
# Landing URL for cross-app redirects — empty in prod (same origin)
VITE_LANDING_URL=http://localhost:3000
# Origins serving /api/* and /bff/* — empty = same origin as the app (web build).
# A host that is not the landing origin (desktop shell, standalone hosting) sets both.
VITE_API_BASE_URL=
VITE_BFF_BASE_URL=
# KAI-126: ClickStack (OpenTelemetry) browser tracing (docker-compose.observability.yml).
# Unset -> disabled, no fetch instrumentation registered.
VITE_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
VITE_OTEL_SERVICE_NAME=kairo-dashboard
# Client-side feature flags (build-time, VITE_FF_*)
# These are compiled at build time by Vite and cannot be changed at runtime.
# Default: false (disabled) — uncomment to enable.
# ╔════════════════════════════════════════════════════════════════════════════╗
# ║ Dashboard → Right Panel — Triage Ticket Tabs ║
# ╚════════════════════════════════════════════════════════════════════════════╝
#
# Each tab can be independently enabled/disabled. When disabled, the tab does
# not appear in the UI and is not loaded. Default is OFF (false).
# Tab 0: AI Assistant — Copilot chat for ticket resolution (KAI-249)
# VITE_FF_ENABLE_ASSISTANT_TAB=true
# Tab 1: Client Profile — Customer details, contact info, KPIs
# VITE_FF_ENABLE_CLIENT_TAB=true
# Tab 4: Escalation Flow — Escalation reasons, severity, recommendation (KAI-249)
# VITE_FF_ENABLE_ESCALATE_TAB=true
# Ticket grouping (KAI-24) — triage left panel: multi-select checkboxes,
# "Agrupar seleccionados" action bar, AI similarity suggestion callout and
# the grouped-tickets badge on cards. OFF unless exactly "true"; safe unset.
# VITE_FF_ENABLE_TICKET_GROUPING=true
# "Assign to me" button (ticket header) — OFF unless exactly "true"; safe unset.
# VITE_FF_ENABLE_ASSIGN_TO_ME=true
# KAI-177: how often (in seconds) the sidebar polls /api/v1/sidebar/counts for
# the nav badge counts (Triage/Resuelto/etc.). Default: 20. Invalid/unset → default.
# VITE_FF_SIDEBAR_COUNTS_POLL_INTERVAL_SECONDS=20
# Internal notes and @mentions (KAI-232) — gates the ENTIRE internal-notes
# surface: note mode in the reply bar, amber note cards in the thread, the
# right-panel "Notes" tab, the @mention dropdown, and the "@menciones" tab in
# the notification bell. OFF unless exactly "true"; safe unset. The backend
# stays live either way — this only hides the UI.
# VITE_FF_ENABLE_INTERNAL_NOTES=true
# KAI-232: how often (in seconds) the notification bell polls
# /api/v1/notifications. Default: 30. Invalid/unset → default.
# VITE_FF_NOTIFICATIONS_POLL_INTERVAL_SECONDS=30
# === MOBILE (apps/mobile) ==========================================
# No @t3-oss/env setup yet (app is a placeholder) — read via process.env
# directly, using Expo's own EXPO_PUBLIC_* convention for build-time-inlined
# client vars, not this repo's usual env.ts pattern.
# KAI-126: mobile OTel tracing (manual spans only, no auto-instrumentation —
# see packages/observability/src/mobile.ts). Unset -> disabled.
EXPO_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318