HelixML

Configuration reference

Environment variables, Helm values, project YAML, and agent app YAML schema for Helix deployments.

Project YAML

Projects are defined in YAML. The full schema:

apiVersion: helix.ml/v1alpha1
kind: Project
metadata:
  name: my-app                    # Used as the project identifier
 
spec:
  description: "What this project is for"
 
  repositories:
    - url: "https://github.com/org/my-app"
      branch: main
      primary: true               # The primary repo is cloned first and receives PRs
    - url: "https://github.com/org/shared-lib"
      branch: main
 
  agent:
    name: "My Agent"
    runtime: claude_code          # claude_code | goose_code | qwen_code | zed_agent
    model: claude-sonnet-4-6      # omit for claude_code
    provider: anthropic           # anthropic | openai | helix | (any configured provider)
    code_agent_credential_type: api_key  # api_key (default) | subscription (Claude Code only)
 
    # Goose-specific:
    goose:
      recipes:
        - name: triage
          path: .goose/recipes/triage.yaml

Agent app YAML

Agent apps (called assistants in the YAML schema) configure conversational agents with skills, knowledge, and triggers. See Build an agent app for a walkthrough.

name: My Assistant
description: "What this agent app does"
 
assistants:
- name: Support
  system_prompt: |
    You are a helpful assistant.
  temperature: 0.3
  max_tokens: 4096
  max_iterations: 10
  agent_type: helix_agent          # helix_basic | helix_agent
 
  # --- helix_agent model configuration ---
  # helix_agent uses four dedicated model roles instead of a single top-level
  # provider/model. Do NOT set provider or model on a helix_agent assistant —
  # the server silently clears those fields and they have no effect.
  reasoning_model_provider: anthropic
  reasoning_model: claude-sonnet-4-6
  reasoning_model_effort: ""       # optional: low | medium | high (default: provider default)
  generation_model_provider: anthropic
  generation_model: claude-haiku-4-5-20251001
  small_reasoning_model_provider: anthropic
  small_reasoning_model: claude-haiku-4-5-20251001
  small_reasoning_model_effort: "" # optional
  small_generation_model_provider: anthropic
  small_generation_model: claude-haiku-4-5-20251001
 
  # --- helix_basic model configuration (use instead of the block above) ---
  # helix_basic uses a single provider/model pair:
  #   provider: anthropic
  #   model: claude-sonnet-4-6
 
  # Skills
  web_search:
    enabled: true
    max_results: 10
 
  browser:
    enabled: true
 
  # Knowledge bases (RAG) — see guide-rag-knowledge
  knowledge:
  - name: my-docs
    description: "Product documentation"
    refresh_enabled: true
    refresh_schedule: "0 */6 * * *"
    rag_settings:
      results_count: 4
      chunk_size: 1024
      chunk_overflow: 64
      enable_vision: false         # true to index images and scanned PDFs
    source:
      web:
        urls:
        - https://docs.example.com/
        crawler:
          enabled: true
          max_depth: 2
          max_pages: 200
          readability: true
 
  # API integrations (OpenAPI)
  apis:
  - name: My API
    description: "Internal API"
    url: https://api.example.com
    schema: ./openapi.yaml
    headers:
      Authorization: Bearer ${MY_API_KEY}
 
  # MCP servers — HTTP transport
  mcps:
  - name: My MCP Server
    url: https://mcp.example.com/tools
    headers:
      Authorization: Bearer ${MCP_TOKEN}
 
  # MCP servers — stdio transport (runs as subprocess)
  # mcps:
  # - name: Filesystem
  #   type: stdio
  #   cmd: npx
  #   args: ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
 
  # Triggers — see guide-triggers
  triggers:
  - slack:
      bot_token: ${SLACK_BOT_TOKEN}
      channels:
      - support
  - teams:
      tenant_id: ${TEAMS_TENANT_ID}
      client_id: ${TEAMS_CLIENT_ID}
      client_secret: ${TEAMS_CLIENT_SECRET}
  - discord:
      bot_token: ${DISCORD_BOT_TOKEN}
      guild_id: "123456789"
  - cron:
      schedule: "0 9 * * 1-5"
      input: "Generate daily summary"
  - webhook: {}                    # Helix generates a unique URL
  - azure_devops:
      org_url: https://dev.azure.com/myorg
      token: ${AZURE_DEVOPS_TOKEN}
      events: [work_item_created, work_item_updated]
  - crisp:
      website_id: ${CRISP_WEBSITE_ID}
      api_key: ${CRISP_API_KEY}
      api_secret: ${CRISP_API_SECRET}

Control plane environment variables

These are passed via controlplane.extraEnv in the Helm chart (or as environment variables in a non-Kubernetes deploy). See Linux & Kubernetes for how to set them.

Desktop streaming

VariableDefaultDescription
HELIX_VIDEO_MODEzerocopyPipeWire capture: zerocopy (DMA-BUF→CUDA, fastest), native (DMA-BUF via GStreamer), shm (shared memory, most compatible). Use shm if browser shows endless reconnects.
HELIX_ENCODERautoH.264 encoder: nvenc (NVIDIA), vaapi/vaapi-legacy (Intel/AMD), openh264/x264 (software).
HELIX_GOP_SIZE120Group of Pictures size in frames (120 = 2s at 60fps). Lower = faster mid-stream join.
HELIX_RENDER_NODEunsetVA-API render device path (e.g. /dev/dri/renderD129). Set on multi-GPU hosts. Use SOFTWARE to disable VA-API.

Control plane behaviour

VariableDefaultDescription
HELIX_DISABLE_VERSION_CHECKunsetDisable the upstream version-check ping at startup. Set to any non-empty value.
HELIX_SKIP_AUTOMIGRATEunsetSkip GORM AutoMigrate on startup. Only set if you run schema migrations out-of-band.
HELIX_GITHUB_BASE_URLhttps://github.comOverride for GitHub Enterprise Server.
FRONTEND_URL(from serverUrl)Public URL of the Helix UI, injected into email links and OAuth callbacks.

VHost TLS (web service hosting)

VariableDefaultDescription
HELIX_VHOST_TLS_MODEoffoff (rely on upstream reverse proxy) or auto (embedded certmagic + Let's Encrypt).
HELIX_VHOST_LETSENCRYPT_EMAILunsetACME registration email. Required when HELIX_VHOST_TLS_MODE=auto.
HELIX_VHOST_ACME_DNS_PROVIDER""DNS-01 challenge provider. Empty = HTTP-01 + TLS-ALPN-01. Set to cloudflare when Helix is behind a Cloudflare proxy.
HELIX_VHOST_CLOUDFLARE_API_TOKENunsetCloudflare API token with Zone:Zone:Read + Zone:DNS:Edit. Required when HELIX_VHOST_ACME_DNS_PROVIDER=cloudflare.

See Host a project as a web service for a full setup walkthrough.

Prompt queue & auto-wake

VariableDefaultDescription
HELIX_MAX_PROMPT_QUEUE_RETRIES20Maximum number of times a failed prompt is retried by the queue before the selectors stop picking it up. Terminal conditions (wedged ACP threads) are crash-marked separately and excluded regardless of this cap. Increase in high-latency environments; decrease to surface failures sooner.
HELIX_AUTO_WAKE_SESSION_WEDGE_THRESHOLD3Session-scoped circuit breaker for auto-wake. Once this many consecutive errored interactions occur since the session's last successful completion, auto-wake stops retrying. A genuine completion resets the count; the circuit never trips on a healthy session.

Sandbox image registry

HELIX_SANDBOX_REGISTRY overrides the registry from which worker hosts pull the sandbox image. Useful for air-gapped deployments and for D3 autoscaling environments where the default GHCR pull can take several minutes across clouds.

VariableDefaultDescription
HELIX_SANDBOX_REGISTRYunsetRegistry hostname for sandbox image pulls (default ghcr.io). Must be a bare hostname (e.g. internal-registry.corp, <acct>.dkr.ecr.us-east-1.amazonaws.com). Helix appends /helixml/helix-sandbox:<version> automatically — do not include an org path. Rejected at boot if the value contains internal whitespace, a URL scheme (https://...), a leading slash, or an embedded path segment. Trailing slashes are tolerated. For Runner Profile compose stacks, use HELIX_RUNNER_REGISTRY instead.

Operator workflow: The image version is always derived from the Helix release — set the registry, never the tag. Before each Helix upgrade, pull helixml/helix-sandbox:<version> from ghcr.io, retag it for your registry, and push. Omitting this step leaves workers in a pull-retry loop with a clear diagnostic error.

Sandbox host (sandbox.extraEnv)

VariableDefaultDescription
HELIX_SANDBOX_APT_MIRRORunsetOverride APT mirror for dev container bootstrapping. Useful in air-gapped environments.
HELIX_SANDBOX_MAX_DEV_CONTAINERS20Maximum number of dev containers (spec-task sandboxes) a single Runner is allowed to host. Controls the max_sandboxes ceiling stored in the database for each Runner. Must be a positive integer — zero or negative is rejected at startup with an error.

How HELIX_SANDBOX_MAX_DEV_CONTAINERS takes effect:

When Helix starts, BackfillSandboxMaxSandboxes updates all existing Runner rows to the configured value, not only newly registered Runners. This means changing the variable and restarting the control plane propagates the new ceiling to your entire fleet without requiring Runner re-registration.

What the ceiling controls and what it does not:

The autoscaler's demand-pressure path uses headroom = max_sandboxes − active_sandboxes to decide whether to provision additional Runners. HELIX_SANDBOX_MAX_DEV_CONTAINERS sets the max_sandboxes side of that equation.

The dispatcher (FindAvailableSandboxInstance) sorts Runners by active_sandboxes ASC when choosing where to place a new container, but does not hard-reject placement on a Runner that has reached its ceiling. Hard per-Runner rejection is a planned follow-up; for now, the ceiling shapes autoscaler headroom math rather than acting as a strict placement guard.

Disk-pressure admission control

The disk-pressure controller prevents ZFS pool exhaustion by enforcing two pool-free-percent thresholds. It runs inside the sandbox host (hydra) — the only component with ZFS access and dev-container lifecycle management.

VariableDefaultDescription
HELIX_DISK_PRESSURE_ENABLEDtrueEnable or disable disk-pressure admission control.
HELIX_DISK_PRESSURE_REFUSE_FREE_PCT2Pool-free-percent threshold at-or-below which new dev containers are refused. CreateDevContainer returns a user-facing error and no container is started.
HELIX_DISK_PRESSURE_STOP_FREE_PCT1Pool-free-percent threshold at-or-below which running dev containers are emergency-stopped. The background monitor gracefully stops all tracked containers so they stop writing. Containers are stopped, never removed — sessions remain resumable once space recovers.
HELIX_DISK_PRESSURE_CHECK_INTERVAL30sHow often the background monitor checks pool free percent.

Behaviour:

  • Fail-open: if the ZFS pool cannot be measured (zpool list error, ZFS unavailable, unparsable output, or reported pool size zero), the controller takes no action — no starts are refused and no containers are stopped. A measurement failure never becomes a service outage.
  • Non-ZFS deployments: the controller is a no-op. No configuration change is required.
  • Emergency stop snapshots the tracked container list under lock (no Docker calls while locked), is idempotent across monitor ticks, and is per-container best-effort — one container failure does not prevent the rest from being stopped.

Helm chart key reference

helix-controlplane

KeyDescription
global.serverUrlPublic URL of the deployment. Must be set correctly — sandboxes use it to reach the control plane.
controlplane.licenseKeyExistingSecretKubernetes secret name containing the license key
controlplane.encryptionKeyExistingSecretAES-256-GCM encryption key secret. Do not rotate after data is written.
controlplane.runnerTokenExistingSecretShared token for sandbox↔control-plane auth
controlplane.providers.*LLM provider configuration (see Configure LLM providers)
controlplane.extraEnvAdditional environment variables for the control plane pod
controlplane.vhostTLS.enabledfalse — set true to expose :443 (and optionally :80) on the Service and Deployment for embedded TLS termination. Requires HELIX_VHOST_TLS_MODE=auto.
controlplane.vhostTLS.httpsPort443 — external HTTPS port.
controlplane.vhostTLS.httpEnabledtrue — set false when using DNS-01 (HELIX_VHOST_ACME_DNS_PROVIDER=cloudflare); the API does not bind :80 in DNS-01 mode.
controlplane.vhostTLS.httpPort80 — external HTTP port for HTTP-01 challenge. Only used when httpEnabled=true.
global.extraEnvEnvironment variables for all pods (useful for proxy settings)

helix-sandbox

KeyDescription
sandbox.apiUrlURL of the control plane, as seen from inside the cluster
sandbox.runnerTokenExistingSecretMust match controlplane.runnerTokenExistingSecret
sandbox.extraEnvAdditional environment variables for the sandbox pod

Full values-example.yaml files are in the Helix repository.