Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
479 lines (393 loc) · 27.1 KB
/
Copy path.env.example
File metadata and controls
479 lines (393 loc) · 27.1 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
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
# ─────────────────────────────────────────────────────────────────────────────
# Nasiko — server environment reference
#
# cp server/.env.example server/.env # then edit
# just run # sources server/.env
#
# This is the COMPLETE list of environment variables the OSS server reads.
# The root `.env.example` is the shorter docker-compose quick start; this file
# is the annotated reference for every knob, and the one `just run` sources.
#
# NEVER commit server/.env (it is gitignored).
# ─────────────────────────────────────────────────────────────────────────────
#
# HOW TO READ THIS FILE
# • REQUIRED → the server exits at startup if missing or invalid.
# • Everything else is commented out and shows its built-in default, so an
# uncommented line is always a deliberate override.
# • Values shown as `(unset)` have no default — the feature is off until set.
#
# Boot requires DATABASE_URL, REDIS_URL, SECRETS_ENCRYPTION_KEY, JWT_SECRET
# and S3_SECRET_KEY (sections 1 and 4). Bootstrap login additionally needs
# ADMIN_USERNAME and ADMIN_PASSWORD. The supplied values are for local demos;
# replace the encryption/signing keys and admin password before first boot.
# Features have additional requirements: local coding-agent routing needs
# AGENT_JWT_SECRET (section 6), and telemetry needs section 12 configured.
# Docker Compose supplies the infrastructure/telemetry URLs automatically.
# ═══════════════════════════════════════════════════════════════════════════
# 1) REQUIRED
# ═══════════════════════════════════════════════════════════════════════════
# --- Connection URLs ---------------------------------------------------------
# REQUIRED. Under docker compose these are overridden with service names.
DATABASE_URL=postgres://nasiko:nasiko@localhost:5432/nasiko_dev
REDIS_URL=redis://localhost:6379
# --- Security keys -----------------------------------------------------------
# REQUIRED. AES-256-GCM key encrypting agent secrets at rest. Must be exactly
# 32 bytes, base64-encoded — the server validates this at startup and refuses
# to boot on a malformed key. Generate one with: openssl rand -base64 32
SECRETS_ENCRYPTION_KEY=kmd9Ic4cgD9YYE/owDL3QSzpKI/BZ3pmVZQ67X+eABc=
# REQUIRED. Signs user session JWTs. openssl rand -base64 48
JWT_SECRET=dev-secret-change-me
# --- Bootstrap admin ---------------------------------------------------------
# Needed for first-login bootstrap, not a startup validation requirement.
# Both must be set for the server to create the admin account.
ADMIN_PASSWORD=changeme
ADMIN_USERNAME=admin
# ═══════════════════════════════════════════════════════════════════════════
# 2) SERVER & NETWORK
# ═══════════════════════════════════════════════════════════════════════════
# CP_BIND=0.0.0.0:8080
# CP_DOMAIN= # (unset) public hostname, for URL derivation
# APP_BASE_URL= # ("") where OAuth flows redirect back to
# CORS_ALLOWED_ORIGINS= # ("") comma-separated; empty = same-origin only
RUST_LOG=info # tracing filter
# ═══════════════════════════════════════════════════════════════════════════
# 3) AGENT RUNTIME
# ═══════════════════════════════════════════════════════════════════════════
# How deployed agents are run:
# local → processes on the host (source/dev, no Docker needed)
# docker → containers via the Docker socket
# simulated → deploys nothing; every agent resolves to SIM_AGENT_URL. Lets you
# run the control plane with no container runtime at all.
AGENT_RUNTIME=local
# Endpoint every agent resolves to under AGENT_RUNTIME=simulated.
# SIM_AGENT_URL=http://localhost:8000
# Docker network the server joins to reach agent containers by name. Leave
# unset when the server runs on the host; set it when the server is itself a
# container (docker compose sets this for you).
# DOCKER_AGENT_NETWORK= # (unset)
# AGENT_DEFAULT_MEMORY=1Gi
# AGENT_MEMORY_VOLUME=nasiko-agent-memory # backs `--writable` /workspace
# AGENT_MEMORY_INIT_IMAGE=alpine:3.21 # seeds per-agent /workspace subdirs
# Space-separated container images auto-deployed at boot. Read ONCE at startup;
# changing it needs a restart. Each image is copied into the embedded registry
# first and deployed from there, so later pulls never leave the server.
SEED_AGENTS=
# SEED_IMAGE_PLATFORM=linux/amd64 # os/arch copied from multi-platform seed images
# SEED_FORCE_PULL= # (unset) set to any value to re-pull seed images
# How often container-uptime rows are polled for FinOps.
# CONTAINER_HOURS_POLL_SECS=60
# ═══════════════════════════════════════════════════════════════════════════
# 4) OBJECT STORAGE & THE EMBEDDED OCI REGISTRY
# ═══════════════════════════════════════════════════════════════════════════
S3_ENDPOINT=http://localhost:9000 # any S3-compatible endpoint
S3_BUCKET=nasiko
S3_ACCESS_KEY=nasiko
S3_SECRET_KEY=nasiko123 # REQUIRED
S3_REGION=us-east-1
# S3_FORCE_PATH_STYLE= # (auto) force path-style addressing
# Where the free-assessment form (POST /api/assessments) is forwarded: the Nasiko
# assessment intake. Unset → the route answers 503 and the form falls back to its
# copy-your-answers step.
# ASSESSMENT_INTAKE_URL=https://yelsilh253pidzyo7chd2tb3mu0ngwmf.lambda-url.us-west-2.on.aws/
# Bucket holding OCI blobs/manifests for the embedded registry at /v2/*.
# OCI_STORAGE_BUCKET=nasiko-artifacts
# OCI_REGISTRY_HOST= # (unset) overrides auto-detection
# Registry that built agent images are pushed to and pulled from. Empty uses
# the server's own embedded registry.
# AGENT_IMAGE_REGISTRY= # ("")
# Credential for the ONE external registry seed images (SEED_AGENTS) come
# from. AGENT_REGISTRY_HOST is the bare host image refs start with (ghcr.io,
# us-central1-docker.pkg.dev, ...); unset = Docker Hub. Sent only to that host.
# AGENT_REGISTRY_USERNAME= # (unset)
# AGENT_REGISTRY_PASSWORD= # (unset)
# AGENT_REGISTRY_HOST= # (unset) Docker Hub
# Shared cluster-wide credential build tooling uses to push to /v2/* as
# `Basic build-service:<token>`. Empty disables that credential type.
# BUILD_PUSH_TOKEN= # ("")
# Parallel server-side builds. Clamped to 1-16.
# BUILD_CONCURRENCY=4
# ═══════════════════════════════════════════════════════════════════════════
# 5) LLM — routing engine, orchestrator, and deployed agents
# ═══════════════════════════════════════════════════════════════════════════
# Provider key for the routing engine and the LLM gateway's platform fallback.
# Gateway-wired agents receive an identity JWT rather than the provider key.
# A custom LLM config can use its own stored provider credentials instead;
# it still requires AGENT_JWT_SECRET for local coding-agent routing (section 6).
# OPENAI_API_KEY=sk-your-openai-api-key
# OPENAI_BASE_URL= # (unset) OpenAI-compatible endpoint
# OPENAI_BASE_URL is for the routing engine/direct-provider path; the gateway's
# built-in OpenAI provider uses OPENAI_API_BASE (section 6). Custom providers
# registered through the API/UI use their stored endpoints and credentials.
# Optional service for decomposing a workflow instruction into steps.
# Missing MODEL_API_URL makes that operation return 503, not server startup fail.
# MODEL_APIKEY is only needed if the decomposer service requires authentication.
# MODEL_API_URL= # (unset)
# MODEL_APIKEY= # (unset)
# OPENAI_MODEL=gpt-4o-mini # default model for agents
# ROUTER_MODEL=gpt-4o-mini # stage-3 agent selection
# EMBEDDING_MODEL=text-embedding-3-small # stages 1-2 shortlist/rerank
# CAPABILITY_GENERATOR_MODEL=gpt-4o-mini # generates agent capability summaries
# MCP_DESCRIPTION_MODEL=gpt-4o-mini # MCP tool-description fallback
# Routing engine shape: stage 1 is skipped below the threshold; stage 1 returns
# the top SIZE candidates.
# ROUTER_SHORTLIST_THRESHOLD=15
# ROUTER_SHORTLIST_SIZE=10
# ═══════════════════════════════════════════════════════════════════════════
# 6) LLM ROUTER — built into the server; routes agents' own LLM calls
# ═══════════════════════════════════════════════════════════════════════════
# Base URL deployed agents use to reach the router. For a host-run server with
# Docker agents, use http://host.docker.internal:8080 where supported, not
# localhost (which points to the agent container itself).
# Compose supplies http://server:8080. Local coding clients instead use their
# CLI cluster URL, e.g. nasiko connect http://localhost:8080.
# LLM_GATEWAY_BASE_URL= # ("")
# Bind address for the OPTIONAL standalone `llm-router` binary. Ignored by the
# server, which mounts the router in-process on CP_BIND.
# LLM_ROUTER_BIND=0.0.0.0:8081
# REQUIRED for local coding-agent routing (nasiko connect claude|codex|opencode
# --config <name>), including custom configs. Generate independently of JWT_SECRET:
# openssl rand -base64 48. Keep it server-side, never in the coding-agent config.
# Empty: /api/agents/{id}/llm-token returns 503; gateway auth fails closed.
# The server still boots and container deployment skips gateway wiring.
# AGENT_JWT_SECRET= # ("")
# AGENT_JWT_ALGORITHM=HS256
# Fallback when an agent has no llm_config row.
# DEFAULT_PROVIDER=openai
# DEFAULT_MODEL=gpt-4o-mini
# Platform-owned provider keys. Each falls back to the bare provider name
# (PLATFORM_OPENAI_API_KEY, else OPENAI_API_KEY).
# PLATFORM_OPENAI_API_KEY=
# PLATFORM_ANTHROPIC_API_KEY=
# PLATFORM_GEMINI_API_KEY=
# PLATFORM_OPENROUTER_API_KEY=
# Provider base URLs (override for self-hosted gateways or tests).
# OPENAI_API_BASE=https://api.openai.com/v1
# ANTHROPIC_API_BASE=https://api.anthropic.com/v1
# GEMINI_API_BASE=https://generativelanguage.googleapis.com/v1beta
# OPENROUTER_API_BASE=https://openrouter.ai/api/v1
# Optional OpenRouter attribution headers — affect openrouter.ai app rankings
# only, harmless to leave empty.
# OPENROUTER_HTTP_REFERER=
# OPENROUTER_X_TITLE=
# LLM_CONFIG_CACHE_TTL=30 # per-agent llm_config cache, seconds
# ROUTER_DECISION_TTL_SECS=3600 # conversation model-stickiness window
# Max age of a running flow that may still authorize an LLM call. Defaults to
# NASIKO_FLOW_TIMEOUT_SECS — never set it BELOW that value, or a turn still
# inside its budget takes a 403 part-way through. See section 9.
# LLM_ATTRIBUTION_WINDOW_SECS= # (defaults to the flow timeout)
# Background catalog/price syncs. Both reach the network at boot; turn them off
# for air-gapped installs.
# MODEL_CATALOG_SYNC_ENABLED=true
# MODEL_CATALOG_SYNC_INTERVAL_SECS=86400
# MODEL_PRICING_SYNC_ENABLED=true
# PRICING_SYNC_INTERVAL_SECS=86400
# PORTKEY_PRICING_BASE_URL= # (built-in) price-book source override
# OPENROUTER_MODELS_URL= # (built-in) model-catalog source override
# Salience gate — decides which turns are worth a larger model.
# SALIENCE_GATE_ENABLED=true
# SALIENCE_LOW_THRESHOLD=0.20
# SALIENCE_HIGH_THRESHOLD=0.80
# SALIENCE_WEIGHTS_PATH= # ("") external weights file
# ═══════════════════════════════════════════════════════════════════════════
# 7) TOKEN COMPRESSION — shrinks payloads before they reach a model
# ═══════════════════════════════════════════════════════════════════════════
# Router-side compression of provider-bound content.
# TOKEN_COMPRESS_ENABLED=true # master kill switch
# TOKEN_COMPRESS_MIN_BYTES=2048
# TOKEN_COMPRESS_TYPES=json,log,diff # prose/code/html/markup/text also valid
# TOKEN_COMPRESS_LEVEL=conservative # conservative | balanced | aggressive
# TOKEN_COMPRESS_DRY_RUN=false # measure only, change nothing
# TOKEN_BREVITY=true # strip redundant whitespace/framing
# TOKEN_BREVITY_MIN_BYTES=0
# Keeps the pre-compression original recoverable for this long.
# TOKEN_COMPRESS_RECOVERY=true
# TOKEN_COMPRESS_RECOVERY_MIN_BYTES=8192
# TOKEN_COMPRESS_RECOVERY_TTL_SECS=86400
# Orchestrator-side compression (tool results and replayed history).
# TOKEN_COMPRESS_TOOL_RESULTS=true
# TOKEN_COMPRESS_TOOL_RESULTS_MIN_BYTES=2048
# TOKEN_COMPRESS_HISTORY=true
# TOKEN_COMPRESS_HISTORY_MIN_BYTES=2048
# ═══════════════════════════════════════════════════════════════════════════
# 8) CHAT CONTEXT — how much conversation history is replayed
# ═══════════════════════════════════════════════════════════════════════════
# Each user picks a strategy (pacms|topk|lastk) and a tier (low|medium|high)
# with `nasiko context-strategy set` / `nasiko budget set`. These keys decide
# what those tiers are WORTH in this deployment; users cannot change them.
#
# `pacms` reads the tier as a token budget:
# PACMS_BUDGET_LOW=500
# PACMS_BUDGET_MEDIUM=1000
# PACMS_BUDGET_HIGH=5000
#
# `topk`/`lastk` read the same tier as an item count:
# CONTEXT_K_LOW=1
# CONTEXT_K_MEDIUM=5
# CONTEXT_K_HIGH=20
#
# Candidate window both embedding-backed strategies draw from, and how many
# recent messages `pacms` always keeps regardless of score.
# PACMS_HISTORY_POOL_SIZE=150
# PACMS_HISTORY_MANDATORY_RECENT=3
# ═══════════════════════════════════════════════════════════════════════════
# 9) FLOW GUARD & TIMEOUTS — the limits that stop runaway agent loops
# ═══════════════════════════════════════════════════════════════════════════
# Redis-backed, keyed by the W3C traceparent trace id. Fails CLOSED: if Redis
# is unreachable, inter-agent calls are rejected rather than waved through.
# NASIKO_FLOW_MAX_DEPTH=5 # max call depth per flow
# NASIKO_FLOW_MAX_FAN_OUT=20 # max agent invocations per flow
# NASIKO_FLOW_MAX_TOKENS=100000 # token budget per flow
# The platform's widest window. The MCP gateway and the LLM router both refuse
# to serve a flow older than this, so nothing an agent turn depends on may
# outlive it.
# NASIKO_FLOW_TIMEOUT_SECS=600
# Redis TTL for the flow's guard state. Defaults to the flow timeout + 60s and
# must ALWAYS exceed it: the guard reads `started_at` out of this key, so a
# shorter TTL expires the state the timeout check depends on — the check then
# passes silently and the depth/fan-out counters reset mid-flow.
# NASIKO_FLOW_STATE_TTL_SECS= # (flow timeout + 60)
# Budget for one agent hop: the A2A proxy, the orchestrator's streaming and
# non-streaming agent calls, and the MAF executor's. Keep at or below
# NASIKO_FLOW_TIMEOUT_SECS. Accepts the former name ROUTER_AGENT_TIMEOUT_SECS.
# AGENT_CALL_TIMEOUT_SECS=600
# ═══════════════════════════════════════════════════════════════════════════
# 10) HUMAN-IN-THE-LOOP
# ═══════════════════════════════════════════════════════════════════════════
# How long a pending hitl_requests row stays answerable.
# HITL_REQUEST_TTL_DAYS=7
# Resume dispatcher: poll cadence, stuck-claim recovery sweep, claim lease,
# retry ceiling, and the delay between attempts.
# HITL_RESUME_POLL_INTERVAL_SECS=5
# HITL_RESUME_RECOVERY_INTERVAL_SECS=600
# HITL_RESUME_LEASE_MINUTES=16
# HITL_RESUME_MAX_ATTEMPTS=3
# HITL_RESUME_RETRY_DELAY_SECS=2
# Re-sends of a resume the agent answered "task not found" before the row is recorded as
# agent_lost_task (a round-robin Service may reach a replica that never saw the task).
# HITL_LOST_TASK_RETRIES=3
# Retry ceiling for a MAF step.
# MAF_MAX_ATTEMPTS=3
# ═══════════════════════════════════════════════════════════════════════════
# 11) MCP GATEWAY — merged tool access for agents
# ═══════════════════════════════════════════════════════════════════════════
# Composio integration. Unset = Composio disabled; generic and uploaded MCP
# servers still work without it.
# COMPOSIO_API_KEY=ak_your-composio-api-key
# COMPOSIO_BASE_URL=https://backend.composio.dev
# COMPOSIO_WEBHOOK_SECRET= # (unset) unset skips signature checks — dev only
# Comma-separated Composio toolkits auto-registered at boot. These ship with
# curated display metadata:
# slack gmail github notion jira linear asana trello discord dropbox
# salesforce hubspot zendesk intercom stripe airtable clickup monday
# gitlab pagerduty sentry confluence bitbucket googlecalendar googledrive
# googlesheets
# NO-OP without COMPOSIO_API_KEY — setting this alone logs a warning at boot
# and does nothing further.
# SEED_TOOLKITS= # ("")
# Public URL of the gateway, injected into every agent as MCP_GATEWAY_URL.
# For a host-run server with Docker-based agents:
# MCP_GATEWAY_PUBLIC_URL=http://host.docker.internal:8080/api/mcp
#
# Agents also receive MCP_GATEWAY_TOKEN (their own credential) and
# MCP_GATEWAY_CONNECT_URL — the same endpoint with that credential in the path,
# for MCP clients that accept only a URL and cannot set an Authorization
# header. Prefer the header form where the client supports it.
# OAuth redirect bases, opened in the USER'S OWN BROWSER.
# MCP_OAUTH_REDIRECT_BASE_URL=http://localhost:8080/api/mcp
# COMPOSIO_CALLBACK_BASE_URL=http://localhost:8080/api/mcp
# Redis-cached TTLs (seconds).
# MCP_SESSION_TTL_SECONDS=300
# MCP_PERM_CACHE_TTL_SECONDS=30
# MCP_MANIFEST_TTL_SECONDS=300
# MCP_TOOLCOUNT_TTL_SECONDS=3600
# "Upload your own MCP server" build/deploy settings.
# MCP_UPLOAD_MAX_BYTES=52428800 # 50 MiB
# MCP_GATEWAY_MAX_BODY_BYTES=8388608 # 8 MiB — request body cap on the agent-facing /api/mcp routes
# MCP_UPLOAD_DEFAULT_PORT=8080 # port the uploaded container must bind via $PORT
# MCP_SERVERS_NETWORK=nasiko-mcp-servers-net
# Query-aware tool discovery: how tools are searched, how many are returned,
# and the cap on meta-tool results.
# MCP_TOOL_SEARCH_MODE=semantic # semantic | bm25
# MCP_TOOL_SEARCH_TOOL_LIMIT=15
# MCP_TOOL_SEARCH_META_LIMIT=10
# DEV/TEST ONLY. Disables the SSRF guard that blocks private/loopback connector
# URLs. Never set this in a deployment that accepts untrusted connector URLs.
# MCP_ALLOW_PRIVATE_URLS= # (unset = guard active)
# Gateway's own sentence advertised ahead of every connector's harvested
# initialize.instructions. Unset/blank = a built-in generic orientation sentence.
# MCP_GATEWAY_INSTRUCTIONS=
# HMAC key the gateway signs the x-nasiko-identity header with, when forwarding
# a caller's (agent_id, user_id, flow_id) to a system backend (e.g. the
# workspace server). Unset/blank falls back to JWT_SECRET.
# MCP_IDENTITY_SIGNING_KEY=
# ═══════════════════════════════════════════════════════════════════════════
# 12) OBSERVABILITY
# ═══════════════════════════════════════════════════════════════════════════
# Trace and log backends. The observability API turns itself on only when BOTH
# are set to a non-empty value.
# TEMPO_URL=http://localhost:3200
# LOKI_URL=http://localhost:3100
# OTLP endpoint the SERVER exports its own spans to.
# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
# OTEL_EXPORTER_OTLP_PROTOCOL=grpc # grpc (4317) | http/protobuf (4318)
# OTEL_EXPORTER_OTLP_HEADERS= # (unset) e.g. auth headers for a hosted collector
# OTLP endpoint injected into AGENT CONTAINERS — must be reachable from inside
# a container, which is usually a different address than the one above.
# OTEL_COLLECTOR_ENDPOINT=http://otel-collector:4317
# OTEL_SERVICE_NAME=nasiko-cp
# OTEL_TRACES_SAMPLER_ARG=1.0 # 1.0 = sample everything
# OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true # capture prompts/completions
# Base OTLP/HTTP JSON endpoint for the durable coding-agent outbox. The server
# appends /v1/traces and /v1/logs. Unset leaves receipts pending with no worker.
# CODING_AGENT_OTLP_ENDPOINT=http://localhost:4318
# Backfill of token usage from trace spans: cadence, re-read overlap that
# tolerates late-arriving spans, and rows per batch.
# TRACE_USAGE_SYNC_SECS=120
# TRACE_USAGE_OVERLAP_SECS=600
# TRACE_USAGE_BATCH_SIZE=50
# ═══════════════════════════════════════════════════════════════════════════
# 13) GITHUB OAUTH — optional; enables import-from-GitHub / clone flows
# ═══════════════════════════════════════════════════════════════════════════
# Create an OAuth App at https://github.com/settings/developers.
# GITHUB_CLIENT_ID=your-github-oauth-client-id
# GITHUB_CLIENT_SECRET=your-github-oauth-client-secret
# GITHUB_CALLBACK_URL=http://localhost:8080/api/auth/github/callback
# Shared OAuth relay used as the redirect_uri instead of GITHUB_CALLBACK_URL,
# so many clusters can share one GitHub OAuth app.
# GITHUB_CENTRAL_CALLBACK_URL= # (unset)
# Signs the OAuth `state` parameter. Defaults to GITHUB_CLIENT_SECRET.
# OAUTH_STATE_SIGNING_KEY= # (GitHub client secret)
# Clone limits for source deploys.
# GITHUB_CLONE_TIMEOUT_SECS=300
# GITHUB_CLONE_MAX_SIZE_MB=500
# ═══════════════════════════════════════════════════════════════════════════
# 14) NETWORK ALLOWLISTS & DISCOVERY
# ═══════════════════════════════════════════════════════════════════════════
# Git hosts accepted for source-clone deploys.
# GIT_CLONE_ALLOWED_HOSTS=github.com,gitlab.com,bitbucket.org
# OCI registry hosts accepted by /api/catalog/import/registry.
# EMPTY REJECTS ALL registry imports — the safe default.
# REGISTRY_IMPORT_ALLOWED_HOSTS= # ("")
# Where agents publish/discover A2A agent cards. Unset derives it from this
# server's own /a2a/v1 endpoint.
# A2A_DISCOVERY_URL= # (unset)
# ═══════════════════════════════════════════════════════════════════════════
# 15) AGENT STATE - durable tasks and key-value state held for agents
# ═══════════════════════════════════════════════════════════════════════════
# How long a stored task or key-value row lives after its last write (1-365).
# Reads do not extend it; expired rows read as absent and are swept every 10 minutes.
# Keep AGENT_STATE_TTL_DAYS at least HITL_REQUEST_TTL_DAYS (the server warns at startup
# otherwise), or a task paused for a human can lose its state before the human answers.
# AGENT_STATE_TTL_DAYS=7
# Largest task body or value an agent may store, counted on the bytes as sent.
# Writes over it get a 413.
# AGENT_STATE_MAX_BODY_BYTES=1048576
# Requests one agent may make to /api/agent-state per minute, for each of its ready replicas
# (an agent running three replicas may make three times this). Over it gets a 429.
# Counted in memory by each server process, as the other rate limits are. One network
# address may make ten times this before any of its tokens is looked up.
# AGENT_STATE_RATE_LIMIT_PER_MINUTE=1200
# Most body bytes one listing page carries. A page stops before the next row would pass it
# and returns a cursor, so short pages are normal.
# AGENT_STATE_LIST_BYTES_BUDGET=8388608