-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathapp.yaml
More file actions
280 lines (275 loc) Β· 14.6 KB
/
Copy pathapp.yaml
File metadata and controls
280 lines (275 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
command:
- gunicorn
- app:app
env:
- name: HOME
value: /app/python/source_code
- name: ANTHROPIC_MODEL
value: system.ai.claude-sonnet-5
# Pi routes to the same /anthropic gateway route as Claude Code; PI_MODEL is
# the serving-endpoint name it addresses (validated against in-geo models).
- name: PI_MODEL
value: system.ai.claude-sonnet-5
- name: GEMINI_MODEL
value: system.ai.gemini-3-flash
# The setup script discovers system.ai models served via the Responses API
# and replaces this request with the newest compatible model when needed.
# Codex speaks wire_api="responses"; chat-completions-only models are
# filtered out by gateway model discovery.
- name: CODEX_MODEL
value: system.ai.gpt-5
- name: HERMES_MODEL
value: databricks-claude-opus-4-8
- name: HERMES_FALLBACK_MODEL
value: databricks-claude-opus-4-8
# Keep the public default set small and explicit.
- name: ENABLE_CLAUDE
value: "true"
- name: ENABLE_FABLE_MODELS
value: "false"
- name: ENABLE_HERMES
value: "false"
- name: ENABLE_PI
value: "true"
# Codex enabled by default. CODEX_MODEL must name a model served by the
# Responses API; set ENABLE_CODEX=false to skip its install.
- name: ENABLE_CODEX
value: "true"
- name: ENABLE_OPENCODE
value: "true"
# Gemini enabled by default. GEMINI_MODEL must name a model served by the
# Google-native API; set ENABLE_GEMINI=false to skip its install.
- name: ENABLE_GEMINI
value: "true"
- name: CLAUDE_CODE_DISABLE_AUTO_MEMORY
value: 0
# Firewalled network: install Claude Code from the npm registry instead of the
# claude.ai installer host. Same CLI (@anthropic-ai/claude-code); use when npm
# is allowlisted but claude.ai / its install CDN is blocked. Default (unset)
# keeps the curl claude.ai path.
- name: CLAUDE_INSTALL_METHOD
value: npm
# AI Gateway host. LEFT UNSET DELIBERATELY β do not commit a workspace URL here.
#
# Unset is the correct default: utils.get_gateway_host() tier 2 derives the
# gateway from DATABRICKS_WORKSPACE_ID (or from an Azure DATABRICKS_HOST) and
# probes it for reachability, so a fresh deploy resolves its OWN workspace's
# gateway with no edit. A committed URL is TRUSTED with no probe (tier 1), and
# a token minted at one workspace is invalid at another's gateway β "400
# Invalid Token" on every model call β so a stale value is worse than none.
#
# Note the three states are distinct (see the tier-1 comment in utils.py):
# unset -> auto-derive + probe (this file's default)
# set URL -> trust it, no probe
# set "" -> explicitly DISABLE the gateway; fall back to serving-endpoints
# So to pin a gateway, uncomment and set a real URL; do not set it empty.
# - name: DATABRICKS_GATEWAY_HOST
# value: https://<your-workspace>.<region>.databricks.com/ai-gateway
#
# Claude Code OTEL export to Unity Catalog. Both vars are needed: the flag
# below plus CLAUDE_CODE_OTEL_CATALOG_SCHEMA pointing at a <catalog>.<schema>
# this app's SP can write to (needs USE_SCHEMA + MODIFY + SELECT +
# CREATE_TABLE). claude_otel.py no-ops when the schema is absent, so the flag
# alone does nothing. Off by default β the target schema is deployment-specific.
- name: CLAUDE_CODE_OTEL_ENABLED
value: "false"
# - name: CLAUDE_CODE_OTEL_CATALOG_SCHEMA
# value: <catalog>.<schema>
# βββ MLflow tracing (workshop Part 3: observability / policy / cost) βββββββ
# Master switch. When true, agent sessions are traced into the experiment
# /Users/{APP_OWNER}/{DATABRICKS_APP_NAME} for later analytics (harness
# comparison, token/cost, trace review β see ppcs-challenge Round 3).
# COVERAGE (verified against the setup scripts, NOT the marketing copy):
# β’ Claude Code β traced via Stop hook (setup_mlflow.py) AND OTELβUC above
# β’ Codex β traced via @mlflow/codex notify hook (setup_codex.py)
# β’ Gemini / Hermes / Pi / OpenCode / Omnigent host β NOT MLflow-traced
# (no first-party MLflow hook exists for these CLIs yet). Their
# endpoint-level usage/cost is still captured by AI Gateway usage
# tracking on the model endpoints (enable per docs/observability).
- name: MLFLOW_TRACING_ENABLED
value: "false"
# βββ spec-B/D: route traces to the self-hosted MLflow OSS app (Lakebase) βββββ
# For network-restricted deployments where the direct `databricks` tracking
# path is blocked (no zerobus/managed storage). When true, Claude Code (spec-B)
# and the content-filter proxy for OpenCode/Hermes/Pi (spec-D) send traces to
# MLFLOW_OSS_URL instead of `databricks`, authed with the app SP's M2M OAuth
# token. Requires the CoDA app SP to have CAN_USE on the OSS app
# (grant_mlflow_host.sh). Off by default β set true only where needed.
#
# BRAND-NEW-ENV ORDERING: on a fresh workspace the OSS app doesn't exist yet and
# this app's SP has no CAN_USE grant, so trace writes would fail. Sequence:
# (1) deploy CoDA with tracking OFF -> (2) deploy the coda-mlflow-oss app
# -> (3) ./grant_mlflow_host.sh --coda-app <coda> --mlflow-app coda-mlflow-oss
# -> (4) uncomment MLFLOW_OSS_URL with that app's URL, flip the flag, redeploy.
#
# MLFLOW_OSS_URL is left unset: it names a specific app in a specific
# workspace, and proxy_tracing._enabled() already requires BOTH the flag and a
# non-empty URL, so an absent URL is a safe no-op.
- name: MLFLOW_OSS_TRACKING_ENABLED
value: "false"
# - name: MLFLOW_OSS_URL
# value: https://coda-mlflow-oss-<workspace-id>.<region>.databricksapps.com
# Capture full prompt/response bodies in proxy trace spans (not just metadata
# shapes). Default is false (privacy-preserving: n_messages/stop_reason only).
# Enabled here so the Traces UI shows the actual model conversation. NOTE: this
# writes potentially sensitive prompt/response content into the OSS trace store.
- name: PROXY_TRACE_CONTENT
value: "false"
# Browser-terminal ceiling. These are a FALLBACK: real traffic runs as
# Omnigent runners (see OMNIGENT_HOST_MAX_RUNNERS below), and the terminal is
# mainly used to debug an Omnigent problem β so keep a small reserve here and
# give the shared 12 GB / 4 vCPU budget to Omnigent. 2 browser + 10 host
# runners = 12 concurrent agents worst case, which stays inside 12 GB at a
# moderate ~500 MB/agent (measured: an idle pi agent is ~200 MB). Each session
# spawns a real coding-agent child (Node/Python). Raise from the resource
# pressure monitor's per-session RSS, not by guessing.
- name: MAX_CONCURRENT_SESSIONS
value: "2"
# WORKSHOP / shared-app mode (TEMPORARY): disable the single-user owner
# binding so every attendee can use the terminal as the single injected PAT
# identity. Isolation then rests entirely on the UC grants of that identity β
# prefer a dedicated low-privilege SP token, not a personal PAT, and revoke
# it when the workshop ends. Only opens the terminal + WebSocket; configure-pat
# and omnigent-host/share stay owner-only. Remove this line to restore
# single-user security. See _owner_check_disabled() in app.py.
# Shared workshop mode is intentionally not enabled in the safe default.
# Enable CODA_DISABLE_OWNER_CHECK only in a dedicated, approved workshop overlay.
# βββ Omnigent host integration ββββββββββββββββββββββββββββββββββββββββββββ
# Register this app as a persistent Omnigent host on boot:
# initialize_app() -> start_host() dials the server as the app SP, so the
# deployed app self-registers as an always-on host on every restart/redeploy.
#
# The host is ON when the two valueFrom resources below are attached to the
# app (via `make attach-omnigent-resources` or the UI); it's OFF otherwise β
# an unresolved valueFrom yields an empty string and omnigents_host_enabled()
# returns False. So the on/off switch is "are the resources attached", not
# "did you edit this committed file" β which keeps app.yaml generic and
# git-deploy friendly, and satisfies docs/agent-instructions.md Β§5 (these must
# not carry one workspace's values on main).
# See attach_omnigent_resources.sh.
#
# OMNIGENTS_SERVER_URL β the Omnigent server app URL for THIS workspace.
# valueFrom: omnigent-server-url β a Secret resource holding the URL.
- name: OMNIGENTS_SERVER_URL
valueFrom: omnigent-server-url
# OMNIGENTS_WHEEL_SPEC β the UC Volume holding omnigent-*.whl +
# omnigent_client-*.whl + omnigent_ui_sdk-*.whl (flat, top level).
# valueFrom: omnigent-wheels β a UC Volume resource (resolved to
# /Volumes/<catalog>/<schema>/<volume> at runtime). Needs the app SP's
# READ_VOLUME grant (grant_omnigent_host.sh).
- name: OMNIGENTS_WHEEL_SPEC
valueFrom: omnigent-wheels
# Force-reinstall the host CLI on boot so a new wheel in the UC Volume is
# actually installed (uv tool install otherwise no-ops when the tool exists).
# Set only while rolling out a runner build; remove once the wheel is stable.
- name: OMNIGENTS_FORCE_REINSTALL
value: "1"
# Cap concurrent Omnigent runners this host will spawn. Omnigent sessions
# arrive over the WSS tunnel and spawn a full agent process each, entirely
# OUTSIDE MAX_CONCURRENT_SESSIONS (which only gates the browser terminals) β
# so without this the two paths can together overcommit this box's 12 GB and
# OOM the single gunicorn worker. This is where the real traffic lives, so it
# gets the bulk of the budget: 10 host runners + 2 browser sessions = 12
# concurrent agents worst case (~6.5 GB at a moderate 500 MB/agent; CPU is
# 3:1 on 4 cores, tolerable for bursty agents that idle between turns). Read
# by the forked host CLI (OMNIGENT_HOST_MAX_RUNNERS -> _handle_launch
# backpressure, returns host_at_capacity past the cap); reaches the host
# subprocess via config_profile_env, which strips only Databricks auth vars.
# Unset/0 = unlimited. Raise from the resource-pressure monitor's data.
- name: OMNIGENT_HOST_MAX_RUNNERS
value: "10"
#
# Claude Code / pi fetch their gateway bearer via an apiKeyHelper that mints
# a fresh app-SP OAuth token per-TTL (spec C), instead of the PAT rotator
# pushing a static token into settings.json. Requires the [omnigents-host]
# OAuth profile, which OMNIGENTS_SERVER_URL above causes to be written; the
# helper falls back to the PAT if it's ever absent.
- name: ENABLE_SP_APIKEYHELPER
value: "true"
# Optional GitHub CLI auth for gh commands in the terminal. Leave unset for
# public-read-only deployments. For a deployment that must use gh API/repo
# commands, attach a short-lived/fine-grained token as a Databricks secret
# resource and uncomment this valueFrom. setup_gh_repos.sh consumes GH_TOKEN
# and runs `gh auth setup-git`; never commit a token here.
# - name: GH_TOKEN
# valueFrom: github-token
# Workshop challenge repo (A-R7) β OPT-IN, both vars unset by default.
# PRIVATE repo cloned from its main branch at container startup into
# ~/projects/<name>; the attendee terminal opens directly inside it. The read
# token is a repo-scoped READ-ONLY GitHub token stored in a Databricks secret
# and attached to the app as a secret resource named "challenge-repo-token".
# The token is used for the clone only and is stripped from attendee sessions.
#
# Uncomment both for a workshop deploy. Leaving them out is a clean no-op:
# app.py only registers the "challenge" setup step when CHALLENGE_REPO_URL is
# set, and install_challenge_repo.sh exits 0 when it's unset. Leaving
# CHALLENGE_REPO_READ_TOKEN's valueFrom in place without the secret attached is
# what produces the "error resolving resource challenge-repo-token" boot
# warning, so both stay commented together.
# - name: CHALLENGE_REPO_URL
# value: https://github.com/<org>/<challenge-repo>
# - name: CHALLENGE_REPO_READ_TOKEN
# valueFrom: challenge-repo-token
# βββ Enterprise security knobs ββββββββββββββββββββββββββββββββββββββββββββ
# Stable Flask session-cookie key. Without this, the key is regenerated on
# every worker restart and existing session cookies get invalidated. Wire to
# a Databricks secret in production (see app.yaml.template for syntax).
# - name: FLASK_SECRET_KEY
# valueFrom: coda-prod/flask-secret-key
#
# Set to "true" to disable CoDA's outbound telemetry to Databricks (event-name
# pings via the SDK User-Agent β see telemetry.py). Regulated deployments
# (banks, retail PII, etc.) typically need this off so the third-party-risk
# register has no undisclosed data flow.
# - name: CODA_TELEMETRY_DISABLED
# value: "true"
# βββ Enterprise mode (proxy / registry redirects) ββββββββββββββββββββββββ
# Uncomment and set the env vars below to run CoDA in locked-down enterprise
# networks. All are optional β set only what your environment requires.
# See docs/enterprise.md for the full contract, JFrog mirror conventions,
# and troubleshooting.
#
# Master switch β when true, logs a startup banner and warns on missing
# recommended mirrors. Behavioural overrides are still driven by the
# individual vars below.
# - name: ENTERPRISE_MODE
# value: "true"
#
# Corporate egress proxy + TLS root CA.
# - name: HTTPS_PROXY
# value: http://proxy.corp.example.com:3128
# - name: NO_PROXY
# value: localhost,127.0.0.1,.corp.example.com
# - name: REQUESTS_CA_BUNDLE
# value: /etc/ssl/certs/corp-root.pem
# - name: NODE_EXTRA_CA_CERTS
# value: /etc/ssl/certs/corp-root.pem
#
# Internal PyPI proxy (e.g. JFrog pypi-virtual).
# - name: UV_DEFAULT_INDEX
# value: https://jfrog.example.com/api/pypi/pypi-virtual/simple/
#
# Internal npm registry. NPM_TOKEN should be a Databricks secret reference.
# - name: NPM_REGISTRY
# value: https://jfrog.example.com/api/npm/npm-virtual/
# - name: NPM_TOKEN
# valueFrom: <secret>
#
# GitHub release mirror β must serve the same path tail as github.com.
# - name: GITHUB_RELEASE_MIRROR
# value: https://jfrog.example.com/artifactory/github-mirror
# - name: GITHUB_API_BASE
# value: https://ghe.example.com/api/v3
#
# Claude installer + Hermes package spec β override when the upstream URLs
# are firewalled.
# - name: CLAUDE_INSTALLER_URL
# value: https://mirror.example.com/claude-install.sh
# - name: HERMES_PIP_URL
# value: hermes-agent==1.2.3
#
# Drop public MCP servers (DeepWiki, Exa) entirely by setting these to "".
# - name: DEEPWIKI_MCP_URL
# value: ""
# - name: EXA_MCP_URL
# value: ""