Configuration Reference¶
Configure your Helix AI platform via a single helix.yaml file. This file controls agent behavior, RAG pipeline settings, LLM providers, security policies, observability, clustering, and all component parameters. It is automatically loaded from the current working directory when running helix run.
Table of Contents¶
- Configuration File Location
- Environment Variable Resolution
- Full Reference
- Section Details
- name
- components
- management
- health
- metrics
- tracing
- shutdown
- logging
- tenant
- audit
- a2a
- agui
- a2ui
- Workflow Authentication
- OCR
- Session
- SmartMemory
- Built-in Function Security
- MCP Servers
- WebSocket
- SynaptX Integration
- CLI Flags
- Minimal Configuration
- Production Configuration Example
Configuration File Location¶
The CLI looks for helix.yaml in the current working directory. If the file is missing, sensible defaults are used.
Environment Variable Resolution¶
All string values in helix.yaml support environment variable substitution:
# Basic substitution
api_key: "${OPENAI_API_KEY}"
# With default value
port: "${SERVER_PORT:-8080}"
# Nested in connection strings
connection: "postgres://${DB_USER:-admin}:${DB_PASS}@${DB_HOST:-localhost}:5432/${DB_NAME}"
The syntax is:
- ${VAR} -- replaced with the environment variable value (empty string if unset)
- ${VAR:-default} -- replaced with the environment variable value, or default if unset or empty
Full Reference¶
helix:
# Application name (used in logs, metrics labels, tracing service name)
name: my-app
# Component-specific configuration overrides
# Keys are component scheme names, values are key-value maps
components:
kafka:
brokers: "kafka1:9092,kafka2:9092"
redis:
addr: "redis:6379"
password: "${REDIS_PASSWORD}"
# Management REST API
management:
enabled: true # Enable the management API
port: 9090 # Listen port (default: 9090)
# Health check HTTP endpoints
health:
enabled: true # Enable /health and /ready endpoints
port: 8081 # Listen port (default: 8081)
# Prometheus metrics
metrics:
prometheus:
enabled: true # Enable /metrics endpoint
port: 9100 # Listen port (default: 9100)
# Distributed tracing
tracing:
opentelemetry:
enabled: true # Enable tracing
endpoint: "http://otel-collector:4318" # OTel collector endpoint (empty = log exporter)
# Graceful shutdown
shutdown:
drain_timeout: "30s" # Max wait for in-flight exchanges to complete (Go duration)
# Structured logging
logging:
level: "info" # Global log level: debug, info, warn, error
format: "json" # Output format: text, json
components: # Per-component level overrides
kafka: "debug" # More verbose for Kafka
http: "warn" # Less verbose for HTTP
connector: "debug"
# Multi-tenancy
tenant:
enabled: true
header_name: "X-Tenant-ID" # Message header containing tenant ID (default: X-Tenant-ID)
required: true # Reject exchanges without tenant header
allowed_tenants: # Restrict to specific tenant IDs (empty = allow all)
- tenant-a
- tenant-b
- tenant-c
# Audit logging
audit:
enabled: true
store: "memory" # Storage backend: "memory" (ring buffer) or "log" (slog + ring buffer)
max_entries: 10000 # Ring buffer size (default: 10000)
body_preview: 256 # Max bytes of message body to capture (0 = none, default: 256)
# A2A (Agent-to-Agent) protocol servers
a2a:
servers:
- enabled: true
addr: "0.0.0.0:9000" # Listen address (default: 0.0.0.0:9000)
name: "my-agent" # Agent name in Agent Card
description: "My AI Agent" # Agent description in Agent Card
version: "1.0.0" # Agent version in Agent Card
# AG-UI (Agent-User Interaction) protocol servers
agui:
servers:
- enabled: true
addr: "0.0.0.0:4100" # Listen address (default: 0.0.0.0:4100)
path: "/agent" # HTTP path (default: /agent)
name: "my-chatbot" # Agent name
# A2UI (Agent to UI) protocol servers
a2ui:
servers:
- enabled: true
addr: "0.0.0.0:4200" # Listen address (default: 0.0.0.0:4200)
path: "/surface" # HTTP path (default: /surface)
name: "my-ui-agent" # Agent name
Section Details¶
name¶
The application name is used as: - The service name in distributed traces - A label in Prometheus metrics - The context name in management API responses - The log prefix
components¶
Component-specific configuration overrides. Each key is a component scheme name, and the value is a map of key-value pairs. These are made available to components at startup.
components:
kafka:
brokers: "host1:9092,host2:9092"
sasl_mechanism: "SCRAM-SHA-256"
postgres:
pool_max_conns: "20"
openai:
api_key: "${OPENAI_API_KEY}"
management¶
The management REST API provides runtime control and observation endpoints. When enabled, it listens on the configured port and exposes:
| Endpoint | Method | Description |
|---|---|---|
/api/info |
GET | Instance info (name, state, uptime, counts) |
/api/workflows |
GET | List all routes with state |
/api/workflows/{id} |
GET | Single workflow detail with metrics |
/api/workflows/{id}/start |
POST | Start a stopped workflow |
/api/workflows/{id}/stop |
POST | Stop a running workflow |
/api/workflows/{id}/suspend |
POST | Suspend a running workflow |
/api/workflows/{id}/resume |
POST | Resume a suspended workflow |
/api/components |
GET | List registered component schemes |
/api/health |
GET | Health check results |
/api/metrics |
GET | Metrics snapshot |
/api/config |
GET | Configuration dump |
/api/agents |
GET | List registered agents |
/api/audit |
GET | Recent audit entries |
/api/tracer |
GET | Backlog tracer status |
/api/tracer/enable |
POST | Enable backlog tracer |
/api/tracer/disable |
POST | Disable backlog tracer |
health¶
When enabled, the health manager listens on the configured port and exposes:
| Endpoint | Description |
|---|---|
/health |
Full health check with per-component results (JSON). Returns 200 if all UP, 503 if any DOWN. |
/ready |
Readiness probe. Returns 200 (READY) or 503 (NOT_READY). |
Health check response format:
{
"status": "UP",
"checks": {
"helix": {"status": "UP"},
"kafka": {"status": "UP", "details": {"brokers": 3}},
"postgres": {"status": "DOWN", "details": {"error": "connection refused"}}
}
}
metrics¶
When Prometheus metrics are enabled, the /metrics endpoint serves metrics in Prometheus text exposition format. Available metric types:
- Counters:
helix_exchanges_total,helix_exchanges_failed_total - Gauges:
helix_exchanges_inflight,helix_workflows_total - Histograms:
helix_exchange_duration_seconds
All metrics are labeled with workflow (workflow ID).
tracing¶
When OpenTelemetry tracing is enabled, every exchange is wrapped in a span. The tracer: - Generates W3C Trace Context IDs (128-bit trace ID, 64-bit span ID) - Propagates trace context via exchange properties - Records span attributes: workflow ID, trigger URI, exchange pattern, component scheme - Reports span events for errors - Exports to an OTel collector endpoint, or to structured logs if no endpoint is configured
shutdown¶
The drain_timeout controls how long the engine waits for in-flight exchanges to complete during graceful shutdown. If the timeout elapses, remaining exchanges are abandoned and the engine shuts down.
Default: 30 seconds.
logging¶
Helix uses Go's log/slog for structured logging. The logging section controls:
- level: Global minimum log level. Messages below this level are dropped.
- format: Output format.
textproduces human-readable lines;jsonproduces JSON-encoded log records. - components: Per-component overrides. Components are identified by the
componentattribute in log records.
The per-component overrides allow verbose logging for specific components without increasing overall noise. For example, setting kafka: debug while the global level is info will show debug messages only from the Kafka component.
tenant¶
Multi-tenancy isolates exchanges by tenant. When enabled, the tenant interceptor:
- Extracts the tenant ID from the configured message header
- If
required: true, rejects exchanges without a tenant header - If
allowed_tenantsis non-empty, rejects unknown tenants - Sets the
helix.tenantexchange property for downstream use
Downstream processors, metrics, and routing can use the helix.tenant property for tenant-aware behavior.
audit¶
The audit interceptor records exchange lifecycle events. Each audit entry captures:
| Field | Description |
|---|---|
timestamp |
When the event occurred |
exchange_id |
Exchange identifier |
workflow_id |
Route that processed the exchange |
from_uri |
Source URI |
operation |
"completed" or "failed" |
duration_ns |
Processing duration |
error |
Error message (if failed) |
headers |
Message headers |
body_preview |
First N bytes of message body |
Storage backends:
- memory -- in-memory ring buffer, queryable via the management API /api/audit endpoint
- log -- writes entries to slog AND stores in a ring buffer for API queries
a2a¶
The A2A section configures Agent-to-Agent protocol servers. Each server exposes Helix agents as A2A-compliant endpoints with Agent Cards for discovery. Multiple servers can run simultaneously on different ports.
| Field | Default | Description |
|---|---|---|
enabled |
false | Enable this A2A server instance |
addr |
0.0.0.0:9000 |
Listen address (increments port for additional servers) |
name |
helix-a2a-{index} |
Agent name in Agent Card |
description |
Helix AI Agent |
Agent description in Agent Card |
version |
1.0.0 |
Agent version in Agent Card |
The server auto-discovers agents from the agent:// component and invocable workflows (direct://, seda://), exposing them as A2A skills. Uses the official github.com/a2aproject/a2a-go SDK.
agui¶
The AG-UI section configures Agent-User Interaction protocol servers for real-time streaming to frontend applications. Each server exposes an HTTP POST endpoint that accepts RunAgentInput JSON and streams SSE events back.
| Field | Default | Description |
|---|---|---|
enabled |
false | Enable this AG-UI server instance |
addr |
0.0.0.0:4100 |
Listen address (increments port for additional servers) |
path |
/agent |
HTTP endpoint path |
name |
helix-agui-{index} |
Agent name |
Uses the official github.com/ag-ui-protocol/ag-ui/sdks/community/go SDK. Compatible with CopilotKit and other AG-UI clients.
a2ui¶
The A2UI section configures Agent to UI protocol servers for rich declarative UI generation. Each server exposes an SSE endpoint that streams A2UI JSONL messages (components, data model updates, rendering directives).
| Field | Default | Description |
|---|---|---|
enabled |
false | Enable this A2UI server instance |
addr |
0.0.0.0:4200 |
Listen address (increments port for additional servers) |
path |
/surface |
HTTP endpoint path |
name |
helix-a2ui-{index} |
Agent name |
GET requests stream A2UI component updates; POST requests receive client-side userAction events. Uses github.com/burka/a2ui-go SDK.
Workflow Authentication¶
Workflows support declarative authentication via the auth: block. The auth processor runs before any workflow steps -- unauthenticated requests are rejected immediately with a 401 response.
workflows:
- id: my-workflow
trigger:
uri: http-server://0.0.0.0:8080/api/data
auth:
# Choose one auth type per workflow: apikey, jwt, basic, or oauth2
type: apikey # required: apikey|jwt|basic|oauth2
# API Key authentication (when type: apikey)
apikey:
header: X-API-Key # header to check (default: X-API-Key)
keys:
- "${env:API_KEY_1}"
- "${vault:secret/api-keys#key2}"
# JWT authentication (when type: jwt)
# jwt:
# secret: "${env:JWT_SECRET}" # HMAC secret or RSA/EC public key
# issuer: "https://auth.example.com" # required issuer claim (optional)
# audience: "my-api" # required audience claim (optional)
# Basic authentication (when type: basic)
# basic:
# users: # map of username to bcrypt hash
# admin: "${env:ADMIN_PASSWORD}"
# reader: "${vault:secret/basic-auth#reader}"
# OAuth2 token introspection (when type: oauth2)
# oauth2:
# token-url: "https://auth.example.com/oauth2/introspect"
# client-id: "${env:OAUTH2_CLIENT_ID}"
# client-secret: "${env:OAUTH2_CLIENT_SECRET}"
# scopes:
# - read
# - write
steps:
- log:
message: "Authenticated request received"
Only one auth type should be specified per workflow. Secrets support resolution via ${env:VAR}, ${vault:path#key}, and ${aws-sm:secret-name}.
See the User Guide Authentication section for full examples including JWKS rotation, scope-based authorization, and per-workflow auth composition.
OCR¶
Configure OCR (Optical Character Recognition) for document intelligence in RAG pipelines. The OCR backend processes scanned PDFs, images with text, and complex document layouts into structured text for downstream chunking and embedding.
helix:
ocr:
backend: docling # OCR backend (see table below)
endpoint: http://localhost:5001 # Backend service endpoint
api_key: ${OCR_API_KEY} # API key for paid services (Azure, Unstructured)
timeout: 120s # Request timeout (default: 120s)
max_pages: 100 # Max pages to process per document (default: 100)
| Backend | Description | Self-Hosted | API Key Required |
|---|---|---|---|
docling |
IBM Docling -- best balance of accuracy and speed | Yes | No |
marker |
Marker -- fast PDF-to-markdown | Yes | No |
tesseract |
Tesseract OCR -- widely deployed, many languages | Yes | No |
surya |
Surya -- multilingual OCR with layout detection | Yes | No |
unstructured |
Unstructured.io -- enterprise document parsing | Yes | Optional |
azure-doc-intelligence |
Azure AI Document Intelligence | No (cloud) | Yes |
vision-llm |
Use a vision-capable LLM (GPT-4o, Claude) for OCR | N/A | Yes (LLM key) |
When backend: vision-llm is selected, the OCR step sends document pages as images to the configured LLM provider. This works well for complex layouts but is slower and more expensive than dedicated OCR backends.
Session¶
Configure per-session memory isolation for agents. When enabled, each unique session ID gets its own memory instance, preventing cross-user context leakage.
helix:
session:
header: X-Session-ID # Header name to extract session ID from (default: X-Session-ID)
timeout: 1h # Session inactivity timeout (default: 1h)
max_sessions: 10000 # Max concurrent sessions in cache (default: 10000)
Session IDs are extracted from the specified request header. If the header is missing, the exchange ID is used as a fallback, giving that request a one-shot memory. See the AI Agents Guide for detailed usage.
SmartMemory¶
SmartMemory is a token-aware memory backend for tool-using agents. It tracks token consumption rather than message count and intelligently compresses large tool results to stay within budget.
Configure SmartMemory on a per-agent basis in the agent's memory: block:
agents:
- id: code-agent
type: react
model:
provider: anthropic
model: claude-sonnet-4-20250514
memory:
enabled: true
type: smart # or "code" (alias for smart)
max_tokens: 100000 # token budget for conversation history
| Field | Type | Default | Description |
|---|---|---|---|
type |
string | -- | smart or code (alias). Activates token-managed memory |
max_tokens |
integer | 100000 |
Maximum tokens allowed in conversation history before eviction |
Behavior: - Tracks tokens per message, not turn count - Large tool results (file contents, command output) are compressed to first 10 + last 10 lines - Tool call and tool response pairs are always evicted together - Evicted messages are summarized in a context map appended to the system prompt - The system message is never evicted
See the AI Agents Guide for a detailed explanation of the compression and eviction algorithm.
Built-in Function Security¶
The built-in function registry provides 14 ready-to-use tools for agents. Security-sensitive functions (shell.exec, fs.write, fs.delete, fs.edit) can be configured in the agent YAML or globally in helix.yaml:
helix:
builtin_functions:
shell:
timeout: 30s # Max execution time for shell.exec (default: 30s)
blocked_commands: # Commands rejected by shell.exec
- "rm -rf /"
- "shutdown"
- "reboot"
- "mkfs"
- "dd"
allowed_dirs: # Restrict file system access to these dirs (empty = cwd)
- "/home/user/project"
web:
max_response_size: 30720 # Max bytes for web.fetch response (default: 30KB)
timeout: 30s # HTTP request timeout (default: 30s)
| Key | Type | Default | Description |
|---|---|---|---|
shell.timeout |
duration | 30s |
Kill shell commands after this duration |
shell.blocked_commands |
list | (see above) | Commands rejected outright |
shell.allowed_dirs |
list | (empty) | Restrict file/shell ops to these directories |
web.max_response_size |
integer | 30720 |
Truncation limit for web.fetch (bytes) |
web.timeout |
duration | 30s |
HTTP timeout for web.fetch |
When allowed_dirs is empty, file system operations are restricted to the working directory passed via --dir to helix chat or the current working directory for helix run.
MCP Servers¶
The mcps: top-level section configures MCP (Model Context Protocol) servers that expose agents, pipelines, and workflows as tools to LLM clients like Claude Desktop.
mcps:
# Public MCP server — exposes 3 agents as tools
- id: public-tools
addr: 0.0.0.0:3100
transport: http # http, sse, or stdio
expose: # Agent/workflow ID to expose (empty = all)
- code-assistant
- math-agent
- summarizer
# Security
api_keys: # API keys for direct access (Bearer or X-API-Key)
- mcp-public-key-2026
rate_limit: 120 # Max requests per minute (0 = unlimited)
cors_origins: # Allowed CORS origins (empty = none)
- "http://localhost:3000"
- "http://localhost:5173"
max_body_bytes: 2097152 # Max request body (default: 1MB)
trusted_proxies: # IPs that skip auth (gateway proxy)
- "127.0.0.1"
- "::1"
allowed_tools: [] # Whitelist (empty = all exposed tools allowed)
blocked_tools: [] # Blacklist (always blocked even if in allowed)
# Admin MCP server — separate port, separate key, restricted
- id: admin-tools
addr: 0.0.0.0:3101
transport: http
expose:
- admin-tool
- code-assistant
api_keys:
- mcp-admin-key-2026
rate_limit: 30
trusted_proxies:
- "127.0.0.1"
- "::1"
blocked_tools:
- summarizer # Block summarizer even if exposed
| Field | Type | Default | Description |
|---|---|---|---|
id |
string | required | Unique MCP server identifier |
addr |
string | 0.0.0.0:3100+i |
Listen address |
transport |
string | http |
Transport: http, sse, or stdio |
expose |
list | [] (all) |
Agent/workflow ID to expose as tools |
api_keys |
list | [] |
Allowed API keys for direct access |
rate_limit |
integer | 0 |
Max requests/minute (0 = unlimited) |
cors_origins |
list | [] |
CORS allowed origins |
max_body_bytes |
integer | 1048576 |
Max request body size |
trusted_proxies |
list | [] |
IPs that skip auth (e.g., gateway) |
allowed_tools |
list | [] |
Tool whitelist (empty = all) |
blocked_tools |
list | [] |
Tool blacklist (always blocked) |
Security layers (applied in order):
1. CORS — checks Origin header against cors_origins
2. Trusted proxy — requests from trusted_proxies IPs skip auth
3. IP allowlist — restricts by client IP (if configured)
4. API key auth — validates Authorization: Bearer <key> or X-API-Key
5. Rate limiting — token-bucket per minute
6. Body size — rejects oversized payloads
7. Tool filtering — blocked_tools checked at call time (returns isError: true)
WebSocket¶
WebSocket endpoints provide bidirectional real-time communication. Define them as workflows:
workflows:
# WebSocket AI Chat
- id: ws-chat
trigger:
uri: ws-server://0.0.0.0:8200/ws
steps:
- agent:
id: ws-agent
type: react
model:
provider: openai
model: gpt-4o-mini
api_key: ${OPENAI_API_KEY}
system_prompt: You are a chat assistant on WebSocket.
max_iterations: 3
# WebSocket Echo
- id: ws-echo
trigger:
uri: ws-server://0.0.0.0:8201/ws
steps:
- log:
message: "echo: ${body}"
The ws-server:// component:
- Accepts RFC 6455 WebSocket connections
- Runs incoming messages through the workflow pipeline
- Returns the pipeline output as the WebSocket response
- Supports text and binary frames
- Manages multiple concurrent client connections
- Each port hosts one WebSocket endpoint
The ws:// client component can connect to external WebSocket servers from within workflows.
SynaptX Integration¶
Helix integrates with SynaptX AI gateway for enterprise features:
helix:
management:
enabled: true
port: 9999 # SynaptX discovers Helix via this port
agents:
- id: code-assistant
model:
provider: openai
model: gpt-4o-mini
api_key: sk-vk-xxxxx # SynaptX virtual key
base_url: http://localhost:7080/ai/openai # Route through SynaptX
Virtual keys — SynaptX provides per-agent API keys with: - Budget limits (daily/monthly USD) - Rate limits (RPM, TPM, RPD) - Provider/model access control - Usage tracking and billing
SynaptX provides (when fronting Helix):
- Prompt injection guard (16 patterns, per-workflow)
- PII detection and blocking (SSN, credit card, API keys)
- WAF (SQL injection, XSS)
- Governance policies (ABAC/RBAC, agent budgets, inter-agent rules)
- MCP tool filtering (allowed_tools, blocked_tools at gateway level)
- A2A/AG-UI protocol proxying
- Audit trail and compliance logging
Discovery — SynaptX auto-discovers Helix agents via:
- GET http://localhost:9999/.well-known/helix-manifest.json
- Returns: agents, MCP servers, workflows, capabilities
Architecture:
Client → SynaptX (:7080) → Helix Agents
├─ /ai/* → LLM providers (virtual key auth)
├─ /a2a/ → A2A server (:9100)
├─ /agui/ → AG-UI server (:4100)
├─ /mcp/ → MCP public (:3100)
├─ /mcp-admin/ → MCP admin (:3101)
└─ /ws/ → WebSocket (:8200)
CLI Flags¶
In addition to the configuration file, the run command supports these flags:
| Flag | Description |
|---|---|
--watch, -w |
Enable hot reload: watch files for changes and reload workflows |
Minimal Configuration¶
The smallest valid helix.yaml:
Everything else uses defaults: - Management API on port 9090 (enabled) - Health checks on port 8081 (enabled) - Metrics disabled - Tracing disabled - 30s drain timeout - Info-level text logging - Multi-tenancy disabled - Audit disabled
Production Configuration Example¶
helix:
name: order-service
management:
enabled: true
port: 9090
health:
enabled: true
port: 8081
metrics:
prometheus:
enabled: true
port: 9100
tracing:
opentelemetry:
enabled: true
endpoint: "http://otel-collector:4318"
shutdown:
drain_timeout: "60s"
logging:
level: "info"
format: "json"
components:
kafka: "warn"
postgres: "warn"
tenant:
enabled: true
header_name: "X-Tenant-ID"
required: true
allowed_tenants:
- acme-corp
- globex
audit:
enabled: true
store: "log"
max_entries: 50000
body_preview: 512