forked from xorbitsai/xagent
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample.env
More file actions
608 lines (541 loc) · 28 KB
/
Copy pathexample.env
File metadata and controls
608 lines (541 loc) · 28 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
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
# ===========================================
# Logging Configuration
# ===========================================
# Log level for the application (default: INFO)
# Options: DEBUG, INFO, WARNING, ERROR, CRITICAL
# XAGENT_LOG_LEVEL="INFO"
# ===========================================
# Docker Compose Configuration
# ===========================================
# When using docker-compose.yml, DATABASE_URL is automatically set.
# You only need to configure the PostgreSQL password below.
# POSTGRES_PASSWORD is used by both postgres and xagent services.
POSTGRES_PASSWORD="xagent_password"
# Web service port (default: 80)
# Frontend and backend are both accessible through this single port
# nginx will route /api/* to backend and others to frontend
PORT="80"
# ===========================================
# Database Configuration (optional)
# ===========================================
# For local development without Docker Compose, uncomment and configure:
# DATABASE_URL="postgresql://xagent:xagent_password@localhost:5432/xagent"
# Or use SQLite (default, no configuration needed):
# DATABASE_URL="sqlite:///home/xagent/.xagent/xagent.db"
# SQLAlchemy connection pool settings (non-SQLite databases only). These
# apply to EACH of the two engines a process may create — the shared web
# engine and the ad-hoc engine behind create_db_session() (workspace file
# registration etc.) — so the worst case per process is
# 2 x (pool size + max overflow). Size that, multiplied by backend/worker
# process count, below PostgreSQL's max_connections.
# XAGENT_DB_POOL_SIZE="10"
# XAGENT_DB_MAX_OVERFLOW="20"
# Seconds to wait for a free pooled connection before raising.
# XAGENT_DB_POOL_TIMEOUT_SECONDS="30"
# Per-server timeout (seconds) for MCP tool initialization during agent
# setup (connect + initialize + list-tools, including retries and cleanup).
# A server that exceeds it is skipped for that task. 0 disables the timeout.
# XAGENT_MCP_TOOL_INIT_TIMEOUT_SECONDS="60"
# ===========================================
# Hot Path Cache Configuration
# ===========================================
# Enables short-TTL cache for high-frequency task/agent/model read paths.
# Docker Compose deployments start a Redis service and set
# XAGENT_REDIS_URL=redis://redis:6379/0 automatically.
#
# For local backend runs outside Docker Compose, uncomment these if Redis is
# running on your machine, for example via `brew services start redis`.
# XAGENT_REDIS_URL="redis://localhost:6379/0"
# XAGENT_HOT_PATH_CACHE_ENABLED="true"
# Default TTL for agent/model response cache entries.
# XAGENT_HOT_PATH_CACHE_TTL_SECONDS="30"
# Default TTL for task polling cache entries.
# XAGENT_HOT_PATH_TASK_CACHE_TTL_SECONDS="30"
# ===========================================
# Background Jobs / Triggers Configuration
# ===========================================
# Enables Celery-backed durable background jobs for trigger processing and
# knowledge-base ingestion. Agent execution is intentionally not routed through
# Celery.
#
# Docker Compose starts worker/scheduler services and sets these automatically.
# Redis DB 0 is reserved for hot-path cache. Redis DB 1 is the Celery broker.
# XAGENT_CELERY_ENABLED="true"
# XAGENT_CELERY_BROKER_URL="redis://localhost:6379/1"
# Background job status/result is stored in the database, so a Celery result
# backend is normally unnecessary. If enabled, keep it separate from DB 0/1.
# XAGENT_CELERY_RESULT_BACKEND="redis://localhost:6379/2"
# Broker visibility timeout for long-running KB jobs.
# XAGENT_BACKGROUND_JOB_VISIBILITY_TIMEOUT_SECONDS="3600"
# Default max attempts for newly-created durable jobs.
# XAGENT_BACKGROUND_JOB_MAX_RETRIES="3"
# Stale non-terminal jobs are requeued by the scheduler after this age.
# XAGENT_BACKGROUND_JOB_STALE_SECONDS="7200"
# Scheduler interval for scanning stale background jobs.
# XAGENT_BACKGROUND_JOB_SWEEP_INTERVAL_SECONDS="300"
# Backend dispatcher for prepared trigger runs. Celery scans scheduled triggers,
# but agent execution is started by backend processes.
# XAGENT_TRIGGER_DISPATCHER_ENABLED="true"
# XAGENT_TRIGGER_DISPATCHER_INTERVAL_SECONDS="5"
# XAGENT_TRIGGER_DISPATCHER_BATCH_SIZE="20"
# Rate limits for the public trigger callback endpoint (keyed by callback id +
# caller IP) and trigger create/update/delete APIs (keyed by user). Uses Redis
# when XAGENT_REDIS_URL is set; otherwise limits are per backend process.
# XAGENT_TRIGGER_CALLBACK_RATE_LIMIT="120/minute"
# Per-IP ceiling across all callback ids (blocks rotating-id floods).
# XAGENT_TRIGGER_CALLBACK_IP_RATE_LIMIT="600/minute"
# XAGENT_TRIGGER_CRUD_RATE_LIMIT="60/minute"
# Behind a reverse proxy, set the number of trusted proxy hops so the caller
# IP for rate limiting is read from X-Forwarded-For. 0 = use the peer address.
# IMPORTANT: when the backend sits behind a reverse proxy / load balancer and
# this stays at 0, every callback appears to come from the proxy's IP, so the
# per-IP limit above silently collapses into a single global cap across ALL
# callbacks (and can throttle legitimate traffic such as Gmail push for many
# mailboxes). Set this to the number of proxies you control in front of the
# backend (e.g. 1 for a single nginx/ingress hop).
# XAGENT_TRUSTED_PROXY_HOPS="0"
# Gmail incoming-email triggers (per-mailbox Pub/Sub provisioning).
#
# Credentials: the backend uses Application Default Credentials (ADC). Either
# run on GCP with an attached service account, or set
# GOOGLE_APPLICATION_CREDENTIALS to a service-account JSON key file. The
# service account needs roles/pubsub.editor (create/delete topics and
# subscriptions) on the project below, and each per-mailbox topic must allow
# gmail-api-push@system.gserviceaccount.com to publish
# (roles/pubsub.publisher) - granted automatically during provisioning.
# XAGENT_GMAIL_WATCH_ENABLED="false"
# XAGENT_GMAIL_PUBSUB_PROJECT_ID="your-gcp-project"
# Deterministic per-mailbox resource names: {prefix}-{mailbox-hash}.
# XAGENT_GMAIL_PUBSUB_TOPIC_PREFIX="xagent-gmail"
# XAGENT_GMAIL_PUBSUB_SUBSCRIPTION_PREFIX="xagent-gmail-push"
# Pub/Sub client transport: "grpc" (default) or "rest". Use "rest" behind
# egress proxies that cannot tunnel gRPC (the gRPC channel hangs there and
# Gmail provisioning stays pending without an error).
# XAGENT_GMAIL_PUBSUB_TRANSPORT="grpc"
# Public base URL of this backend API. A2A Agent Cards advertise interfaces
# under this base; MCP OAuth and Pub/Sub use it for externally reachable
# callbacks. This is NOT the frontend URL (XAGENT_APP_BASE_URL).
# XAGENT_PUBLIC_API_BASE_URL="https://api.example.com"
# Service-account email whose OIDC identity signs push deliveries.
# XAGENT_GMAIL_PUBSUB_PUSH_SERVICE_ACCOUNT="pubsub-push@your-gcp-project.iam.gserviceaccount.com"
# Trigger create/update returns a pending registration after this many seconds
# while provisioning converges in the background.
# XAGENT_GMAIL_REGISTRATION_TIMEOUT_SECONDS="10"
# XAGENT_GMAIL_WATCH_RENEWAL_INTERVAL_SECONDS="3600"
# XAGENT_GMAIL_WATCH_RENEWAL_LEAD_SECONDS="86400"
# ===========================================
# LLM API Keys
# ===========================================
# OPENAI_API_KEY="your-openai-api-key"
INFERENCE_API_KEY="your-inference-api-key"
# DEEPSEEK_API_KEY="your-deepseek-api-key"
# Optional DeepSeek defaults
# DEEPSEEK_MODEL_NAME="deepseek-v4-flash"
# Official default base URL does not use the legacy /v1 suffix
# DEEPSEEK_BASE_URL="https://api.deepseek.com"
# DEEPSEEK_REASONING_EFFORT="high"
# ElevenLabs speech (ASR/TTS)
# ELEVENLABS_API_KEY="your-elevenlabs-api-key"
# ELEVENLABS_BASE_URL="https://api.elevenlabs.io"
# OpenRouter official-provider pinning is disabled by default to preserve
# OpenRouter fallback behavior. Set to true to route official model families
# (OpenAI, Anthropic, Google, DeepSeek, MiniMax, Z.AI) only to official endpoints.
# XAGENT_OPENROUTER_OFFICIAL_PROVIDERS_ONLY="false"
# ===========================================
# Embedding API Keys (for vector memory)
# ===========================================
DASHSCOPE_API_KEY="your-dashscope-api-key"
OPENAI_EMBEDDING_API_KEY="your-openai-api-key"
# Memory Store Configuration
# Optional: Override automatic detection
# MEMORY_STORE_TYPE=in_memory|lancedb
# MEMORY_LANCEDB_DIR=./memory_store
#
# Auto-run LanceDB user_id migration on startup (default: false)
# Set to true to run background backfill when startup detects missing user_id fields.
# LANCEDB_AUTO_MIGRATE=true
# Milvus Vector Store Provider (optional, provider layer only)
# Used by xagent.providers.vector_store.milvus.get_client_from_env()
# Install dependency first: pip install pymilvus
# MILVUS_URI="http://localhost:19530"
# MILVUS_TOKEN=""
# MILVUS_DB_NAME=""
# ===========================================
# Other Configuration
# ===========================================
# JWT Authentication (required for production)
# Generate a secure secret with:
# python -c "import secrets; print(secrets.token_urlsafe(48))"
XAGENT_JWT_SECRET="replace-with-a-long-random-secret"
XAGENT_JWT_ALGORITHM="HS256"
# Access token expiry in minutes (default: 120)
XAGENT_ACCESS_TOKEN_EXPIRE_MINUTES="120"
# Refresh token expiry in days (default: 7)
XAGENT_REFRESH_TOKEN_EXPIRE_DAYS="7"
# Minimum password length for setup/register/change-password (default: 6)
XAGENT_PASSWORD_MIN_LENGTH="6"
# Password reset link expiry in minutes (default: 30)
# XAGENT_PASSWORD_RESET_EXPIRE_MINUTES="30"
# Frontend base URL used in reset-password emails
# XAGENT_APP_BASE_URL="http://localhost:3000"
# ===========================================
# SMTP Configuration (for password reset email)
# ===========================================
# XAGENT_SMTP_HOST="smtp.example.com"
# XAGENT_SMTP_PORT="587"
# XAGENT_SMTP_USERNAME=""
# XAGENT_SMTP_PASSWORD=""
# XAGENT_SMTP_USE_TLS="true"
# XAGENT_SMTP_USE_SSL="false"
# XAGENT_SMTP_FROM_EMAIL="no-reply@example.com"
# XAGENT_SMTP_FROM_NAME="Xagent"
# Google OIDC login (optional)
# Configure these to enable "Continue with Google" on the web login page.
# XAGENT_GOOGLE_OIDC_CLIENT_ID="your-google-oauth-client-id"
# XAGENT_GOOGLE_OIDC_CLIENT_SECRET="your-google-oauth-client-secret"
# XAGENT_GOOGLE_OIDC_REDIRECT_URI="http://localhost:8000/api/auth/oidc/google/callback"
# XAGENT_FRONTEND_URL="http://localhost:3000"
# XAGENT_SESSION_SECRET="change-me-to-a-random-session-secret"
# XAGENT_OIDC_LOGIN_TTL_SECONDS="600"
# XAGENT_OIDC_EXCHANGE_TTL_SECONDS="120"
# MCP OAuth local development only.
# Set XAGENT_PUBLIC_API_BASE_URL above to the externally reachable backend
# origin used for automatic {base}/api/mcp/oauth/callback redirect URIs.
# Keep disabled in production; enabling this allows OAuth discovery/token URLs
# to target localhost, private, link-local, reserved, multicast, or unspecified
# addresses for local authorization-server testing.
# XAGENT_MCP_OAUTH_ALLOW_PRIVATE_HOSTS="false"
# Optional explicit trusted proxy for outbound MCP OAuth discovery/token calls.
# System HTTP_PROXY/HTTPS_PROXY environment variables are intentionally ignored.
# XAGENT_MCP_OAUTH_PROXY_URL="http://proxy.example.com:8080"
# Image processing
CONCURRENT=5
# Langfuse Tracing
LANGFUSE_TRACING_ENABLED="true"
# Langfuse Python SDK v4 uses `base_url`; keep `LANGFUSE_HOST` only for legacy env fallback.
LANGFUSE_BASE_URL="http://127.0.0.1:3000"
LANGFUSE_PUBLIC_KEY="public key"
LANGFUSE_SECRET_KEY="secret key"
# Per-field byte cap for the LLM I/O audit trace written to trace_events
# (data.messages / data.response / etc.). Anything larger is truncated with a
# "[truncated N chars]" suffix. A long DAG task hitting all audit sites can
# otherwise write multi-MB rows. Default: 50000 (~50KB).
# XAGENT_MAX_TRACE_PAYLOAD_BYTES="50000"
# Web Search API Keys
# Provider selection: auto, google, tavily, exa, zhipu (default: auto)
# In auto mode, priority is Zhipu > Tavily > Exa > Google.
XAGENT_WEB_SEARCH_PROVIDER="auto"
# Website import TLS fingerprint impersonation for WAF-protected sites.
# Leave empty/none for plain httpx. Use auto to try the crawler fallback chain.
# Requires installing the optional extra: pip install "xagent[waf-crawl]"
# XAGENT_WEB_CRAWL_TLS_IMPERSONATE="auto"
# In-turn tool concurrency: run independent, concurrency-safe tool calls from a
# single ReAct turn in parallel instead of one-by-one. Default off (serial).
# XAGENT_TOOL_PARALLEL_ENABLED="false"
# Max concurrent tool calls per turn batch (kept low to limit API rate-limit
# pressure). Invalid/non-positive values fall back to the default.
# XAGENT_TOOL_MAX_CONCURRENCY="3"
# Context compaction: the conversation is compacted when the estimated context
# size reaches (model context window * ratio). Set a model's context window in
# the model config; models without one fall back to the default below.
# Ratio must be within (0, 1]; invalid values fall back to 0.75.
# XAGENT_COMPACT_THRESHOLD_RATIO="0.75"
# Fallback threshold in tokens when a model has no context window configured.
# XAGENT_COMPACT_THRESHOLD_DEFAULT="32000"
# Checkpoint storage encoding v2: dedup nested DAG/auto contexts, per-record
# tool ledgers, and large system prompts into content-addressed blob tables.
# Decode support is unconditional; this only gates NEW writes. For a mixed
# fleet, roll out in two phases: deploy every instance with "false" first
# (decode-only), then remove the override to start writing v2. Default on.
# XAGENT_CHECKPOINT_ENCODING_V2="true"
# How many checkpoint trace-event rows to keep per task execution. Older rows
# are pruned when a new checkpoint is written (resume only reads the latest
# readable one; a few extras are kept as fallback). "0" disables pruning.
# XAGENT_CHECKPOINT_HISTORY_LIMIT="8"
# Zhipu Web Search (recommended for Chinese users, get key at https://open.bigmodel.cn/)
ZHIPU_API_KEY=""
# Tavily Search API (alternative, get key at https://tavily.com)
TAVILY_API_KEY=""
# Exa AI-powered Search (get key at https://exa.ai)
EXA_API_KEY=""
# Google Custom Search (fallback, requires Google Cloud setup)
GOOGLE_API_KEY=""
GOOGLE_CSE_ID=""
# ===========================================
# Google OAuth Configuration (Optional)
# ===========================================
# Required for Google Login and Google Drive integration
# Create credentials at https://console.cloud.google.com/apis/credentials
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
# Redirect URI for Google OAuth callback (Required for Google Login)
# Example: http://localhost:8000/api/auth/google/callback
GOOGLE_REDIRECT_URI=""
# ===========================================
# LinkedIn OAuth Configuration (Optional)
# ===========================================
# Required for LinkedIn integration in MCP
# Create credentials at https://www.linkedin.com/developers/apps/new
LINKEDIN_CLIENT_ID=""
LINKEDIN_CLIENT_SECRET=""
# Redirect URI for LinkedIn OAuth callback
# Example: http://localhost:8000/api/auth/linkedin/callback
LINKEDIN_REDIRECT_URI=""
# ===========================================
# HubSpot OAuth Configuration (Optional)
# ===========================================
# Required for the HubSpot CRM integration in MCP
# Create a public app at https://developers.hubspot.com/ and configure the
# app's scopes to match the connector (crm.objects.contacts/companies read+write,
# crm.objects.deals.read)
HUBSPOT_CLIENT_ID=""
HUBSPOT_CLIENT_SECRET=""
# Redirect URI for HubSpot OAuth callback
# Example: http://localhost:8000/api/auth/hubspot/callback
HUBSPOT_REDIRECT_URI=""
# ===========================================
# Meta OAuth Configuration (Optional)
# ===========================================
# Required for Facebook Pages and Instagram integrations in MCP
# Create credentials at https://developers.facebook.com/apps/
META_CLIENT_ID=""
META_CLIENT_SECRET=""
# Redirect URI for Meta OAuth callback
# Example: http://localhost:8000/api/auth/meta/callback
META_REDIRECT_URI=""
# Optional Facebook Login for Business configuration ID. When set, Meta OAuth
# uses config_id instead of a raw scope list, which is required by some Meta app
# configurations for Pages and Instagram permissions.
META_CONFIG_ID=""
# Note:
# - If embedding API keys are configured, LanceDB will be used automatically
# - LanceDB storage path: <project_root>/memory_store/
# - Without embedding keys, InMemory storage will be used
# - Milvus support is currently optional at provider layer and does not change defaults
# ===========================================
# Skills Directories Configuration
# ===========================================
# Comma-separated list of skill directory paths
# Supports:
# - Absolute paths: /path/to/skills1,/path/to/skills2
# - Relative paths: ./skills,../shared_skills
# - Home directory: ~/skills,~/custom/skills
# - Environment variables: $HOME/skills,${USERPROFILE}/skills
#
# Examples:
XAGENT_EXTERNAL_SKILLS_LIBRARY_DIRS=""
# XAGENT_EXTERNAL_SKILLS_LIBRARY_DIRS="/path/to/custom/skills"
# XAGENT_EXTERNAL_SKILLS_LIBRARY_DIRS="~/skills,/usr/local/skills,$HOME/custom_skills"
# XAGENT_EXTERNAL_SKILLS_LIBRARY_DIRS="./local_skills,../shared_skills"
# ===========================================
# Storage and Directory Configuration
# ===========================================
# Root directory for all xagent data (default: ~/.xagent)
# XAGENT_STORAGE_ROOT=""
# Uploads directory for user files (default: src/xagent/web/uploads)
# For containerized deployments, use a persistent volume path
# XAGENT_UPLOADS_DIR=""
# Maximum per-file upload size enforced by the backend.
# Nginx maintains a separate, larger defense-in-depth ceiling (see docker/nginx.conf).
# Supports raw bytes or human-readable values like 100M, 1G, 512K.
XAGENT_MAX_UPLOAD_SIZE="100M"
# Durable file storage for user-visible uploads and registered workspace outputs.
# Defaults to file://$XAGENT_STORAGE_ROOT/files for local development.
# For S3-compatible storage, use a URI with bucket and optional prefix.
# XAGENT_FILE_STORAGE_URI="file:///home/xagent/.xagent/files"
# XAGENT_FILE_STORAGE_URI="s3://xagent-bucket/prod/files"
# Optional fsspec provider options as JSON. For S3-compatible providers this can
# include endpoint_url, region_name, profile, key, secret, or config_kwargs.
# S3 storage defaults to bounded botocore timeouts/retries so unavailable
# storage fails quickly; override config_kwargs here if your deployment needs
# longer waits.
# XAGENT_FILE_STORAGE_OPTIONS='{"endpoint_url":"https://s3.example.com","region_name":"us-east-1"}'
# Local temp/cache directory for materializing durable files when libraries need paths.
# XAGENT_FILE_MATERIALIZE_DIR="/tmp/xagent-materialized"
# Sync DB-registered local files to S3 durable storage during backend startup.
# Only applies when XAGENT_FILE_STORAGE_URI uses s3://. Missing local files are
# logged and skipped; unexpected S3 errors fail startup.
# XAGENT_FILE_STORAGE_STARTUP_SYNC_ENABLED="true"
# Redirect authenticated preview/download requests to short-lived durable-object
# URLs when the storage backend can sign them. Keep disabled unless the signed
# URL endpoint is reachable by browsers (for example public S3/MinIO or CDN).
# XAGENT_FILE_DELIVERY_REDIRECT_ENABLED="false"
# XAGENT_FILE_DELIVERY_SIGNED_URL_TTL_SECONDS="300"
# Let nginx serve local upload bytes after the backend authorizes a file_id.
# This requires docker/nginx.conf's internal location and a shared read-only
# uploads volume mounted into nginx. Keep disabled for direct local backend runs.
# XAGENT_FILE_DELIVERY_ACCEL_REDIRECT_ENABLED="false"
# XAGENT_FILE_DELIVERY_ACCEL_REDIRECT_PREFIX="/_xagent_internal_files/"
# External upload directories for knowledge base file access
# Comma-separated list of directory paths (existing dirs only)
# XAGENT_EXTERNAL_UPLOAD_DIRS="/path/to/uploads1,/path/to/uploads2"
# Web module directory (default: src/xagent/web)
# XAGENT_WEB_DIR=""
# Built frontend static export served by the backend in single-process
# (pip / uvx) mode (default: $XAGENT_WEB_DIR/frontend_dist). Leave unset unless
# serving a frontend build from a custom location.
# XAGENT_FRONTEND_DIST_DIR=""
# LanceDB database path (default: data/lancedb, relative to cwd)
# For production, use an absolute path under XAGENT_STORAGE_ROOT
# LANCEDB_PATH=""
# Database encryption key
# Generate one with: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
ENCRYPTION_KEY="RQMpe38gK3m0szjpSmTNw_sP3Y54r6hDc6JewBoPKXc="
# ===========================================
# Tool Output Configuration
# ===========================================
# Maximum length per string in tool output (default: 51200, ~50KB)
# This limits individual string values, not total output size
# XAGENT_TOOL_MAX_OUTPUT_LENGTH="51200"
# Maximum number of fields/items in dict/list (default: 1000)
# This limits collection cardinality to prevent excessive output
# XAGENT_TOOL_MAX_FIELD_COUNT="1000"
# Maximum recursion depth for nested structures (default: 20)
# This prevents excessively deep nesting in tool output
# XAGENT_TOOL_MAX_RECURSION_DEPTH="20"
# ===========================================
# External Database Connections (for SQL Query Tool)
# ===========================================
# SQL tool supports PostgreSQL, MySQL, and SQLite
# Connection format: XAGENT_EXTERNAL_DB_<NAME>=<connection_url>
#
# Install required database drivers:
# - PostgreSQL: pip install psycopg2-binary (or psycopg2)
# - MySQL: pip install pymysql (or mysqlclient)
# - SQLite: built-in (no installation needed)
#
# Format of the url is the same as used by SQLAlchemy, async drivers are not supported currently.
# Examples:
# XAGENT_EXTERNAL_DB_ANALYTICS="postgresql://user:password@localhost:5432/analytics"
# XAGENT_EXTERNAL_DB_PROD="mysql+pymysql://user:password@localhost:3306/production"
# XAGENT_EXTERNAL_DB_LOCAL="sqlite:///path/to/database.db"
# ===========================================
# Sandbox Configuration
# ===========================================
# Enable/disable sandbox execution environment (default: false)
# SANDBOX_ENABLED="false"
# Sandbox implementation type (default: docker)
# Available options: docker, boxlite
# SANDBOX_IMPLEMENTATION="docker"
# Recommended Docker deployment topology:
# - Prefer a dedicated Docker engine for sandbox workloads, for example a separate VM,
# a dedicated Docker host, or a dedicated DinD/containerized Docker daemon used only by Xagent.
# - Avoid sharing the host's primary Docker daemon with sandbox execution if possible.
#
# Security warning:
# - Do NOT mount the host Docker socket (for example /var/run/docker.sock) directly into the
# Xagent backend when it may execute untrusted sandbox code.
# - Access to that socket is effectively root-equivalent on the Docker host: an attacker could
# start privileged containers, mount host filesystems, read secrets, or escape the sandbox
# and gain control of the host.
#
# Suggested hardening measure:
# - Put a restricted proxy such as Tecnativa/docker-socket-proxy in front of the Docker
# daemon.
#
# When using SANDBOX_IMPLEMENTATION="docker", set DOCKER_HOST if your Docker-compatible
# runtime endpoint is not the default (for example Podman socket/service)
# DOCKER_HOST=""
# Docker sibling deployments resolve sandbox code mounts on the Docker host,
# not inside the Xagent backend container. Set this to the host-side project
# checkout root when it differs from the backend container path.
# XAGENT_SANDBOX_HOST_PROJECT_ROOT=""
# Docker sibling deployments also resolve workspace/storage mounts on the Docker
# host. Set this to the host-side Xagent storage root when manual deployments
# bind a different host path into the backend as XAGENT_STORAGE_ROOT.
# The provided Compose overlay accepts XAGENT_HOST_STORAGE_ROOT and passes it
# through as XAGENT_SANDBOX_HOST_STORAGE_ROOT automatically.
# XAGENT_SANDBOX_HOST_STORAGE_ROOT=""
# Boxlite home directory (default: ~/.boxlite)
# Takes effect only when using the boxlite implementation
# BOXLITE_HOME_DIR=""
# Sandbox container image (default: xprobe/xagent-sandbox:latest)
# We should pin the version at release (`latest` may lead to caching problems)
# SANDBOX_IMAGE=""
# Sandbox CPU core limit (default: 1)
# SANDBOX_CPUS=""
# Sandbox memory limit in MB (default: 512)
# SANDBOX_MEMORY=""
# Max concurrent worker sandboxes per user/task lifecycle. This only affects
# sandboxed tools that explicitly opt into concurrency-safe execution.
# Invalid/non-positive values fall back to the default.
# XAGENT_SANDBOX_MAX_CONCURRENCY="3"
# ===========================================
# Sandbox Idle Reclamation
# ===========================================
# Idle TTL in seconds after which sandbox containers with no active tasks are
# deleted by a background sweep (default: unset — containers live forever,
# matching previous behavior).
#
# Reclamation deletes the container. Workspace data lives on bind mounts and
# survives; the sandbox is transparently recreated on next use (cold-start
# latency only). Anything written OUTSIDE the mounted workspace/uploads paths
# is lost: lazily installed pip packages (reinstalled on demand), files under
# /tmp or $HOME inside the container. Containers found at backend startup
# with no recorded activity are treated as idle since startup and reclaimed
# one TTL later.
# XAGENT_SANDBOX_IDLE_TTL="86400"
# Interval in seconds between idle sweep runs (default: 60). Only meaningful
# when XAGENT_SANDBOX_IDLE_TTL is set.
# XAGENT_SANDBOX_SWEEP_INTERVAL="60"
# ===========================================
# Sandbox Capacity Limit
# ===========================================
# Maximum number of concurrently existing sandbox containers (default: unset
# — no cap, matching previous behavior). The cap counts all managed
# containers including per-lifecycle workers; the transient warmup container
# is excluded.
#
# When a new sandbox is requested at the cap, the least-recently-used idle
# sandbox (no active tasks) is deleted to make room. If nothing is evictable
# (all sandboxes busy), a task's primary sandbox request fails at task
# admission with a clear capacity error by default instead of silently
# running on the host. A worker sandbox for a concurrency-safe tool that
# cannot fit under the cap (a task's own primary occupies a slot and is
# never evicted to make room for its workers) degrades to running on the
# task's primary sandbox with a warning log — reduced isolation, but the
# tool keeps working mid-task.
#
# Size the cap for full worker isolation: allow roughly expected concurrent
# primaries x (1 + XAGENT_SANDBOX_MAX_CONCURRENCY) containers.
#
# Note: the ref-count and cap are per-backend-process state. Deployments
# running multiple backend workers/replicas against one Docker daemon get
# approximate enforcement only.
# XAGENT_SANDBOX_MAX_CONTAINERS="20"
# Allow tasks to fall back to local (host) execution when the sandbox cap is
# reached and nothing is evictable (default: false — reject the task).
# Enable only if you prefer availability over strict sandboxing; sandbox
# service unavailability keeps its local fallback regardless of this flag.
# XAGENT_SANDBOX_ALLOW_LOCAL_FALLBACK_ON_CAPACITY="false"
# ===========================================
# Sandbox Volume Mount Configuration
# ===========================================
# Mount host directories into sandbox (Docker-style format)
# Format: SANDBOX_VOLUMES="src:dst:mode;src:dst:mode"
# - src: Path on host machine (supports ~ expansion)
# - dst: Path inside sandbox container
# - mode: 'ro' (read-only) or 'rw' (read-write), default is 'ro' when omitted
# - Multiple volumes are separated by semicolon (;)
# - In Docker sibling mode, src is interpreted by the Docker host daemon.
# Use absolute host paths; relative paths and ~ are rejected.
#
# Examples:
# Mount Python venv site-packages (read-only recommended)
# SANDBOX_VOLUMES="/home/user/my-python-site:/usr/local/lib/python3.14/site-packages:ro"
#
# Mount node_modules
# SANDBOX_VOLUMES="/home/user/my-node_modules:/usr/local/lib/node_modules"
#
# Mount multiple directories
# SANDBOX_VOLUMES="/home/user/my-python-site:/usr/local/lib/python3.14/site-packages;/home/user/my-python-app:/opt/my-python-app"
# ===========================================
# Sandbox Environment Variables
# ===========================================
# Additional environment variables to inject into sandbox
# Format: SANDBOX_ENV="KEY1=value1;KEY2=value2"
# - Multiple variables are separated by semicolon (;)
# - Values should not contain semicolon
#
# Example: Set PYTHONPATH to include mounted site-packages
# SANDBOX_ENV="PYTHONPATH=/home/user/my-python-app:/opt/my-python-app"