Variables Reference
Habits uses a powerful variable system to pass data between nodes, access request data, environment variables, and utility functions. Variables use the syntax and are resolved at runtime.
Variable Syntax
Variables are enclosed in double curly braces:
{{variable.path}}Supports:
- Dot notation:
{{habits.input.userId}} - Nested access:
{{previous-node.result.items.name}} - Array indexing:
{{node-id.output.0.data}}
Variable Categories
Request Input (habits.input.*)
Access data from HTTP POST requests or CLI arguments.
| Variable | Description | Example |
|---|---|---|
{{habits.input}} | Full request body | {"name": "John", "age": 30} |
{{habits.input.fieldName}} | Specific field from request (POST or GET) | {{habits.input.userId}} |
{{habits.input.query}} | Nested Params | {{habits.input.query.page}} |
HTTP Request Example:
curl -X POST http://localhost:3000/api/my-workflow \
-H "Content-Type: application/json" \
-d '{"userId": "123", "action": "send"}'In your workflow, access with:
{{habits.input.userId}}→"123"{{habits.input.action}}→"send"
CLI Example:
habits execute --config ./stack.yaml --id my-workflow --input '{"userId": "123"}'HTTP Headers (habits.header.*)
Access HTTP request headers (case-insensitive).
| Variable | Description | Example |
|---|---|---|
{{habits.header.authorization}} | Authorization header | Bearer token |
{{habits.header.content-type}} | Content type | application/json |
{{habits.header.x-custom-header}} | Custom headers | Any custom value |
Note: Header names are case-insensitive. {{habits.header.Authorization}} and {{habits.header.authorization}} resolve to the same value.
Environment Variables (habits.env.*)
Access environment variables for configuration and secrets.
| Variable | Description |
|---|---|
{{habits.env.VAR_NAME}} | Value of environment variable |
{{habits.env.OPENAI_API_KEY}} | Example: OpenAI API key |
{{habits.env.DATABASE_URL}} | Example: Database connection string |
Security Note: Use environment variables for sensitive data like API keys, passwords, and connection strings. Never hardcode secrets in workflows.
Example .env file:
OPENAI_API_KEY=sk-...
DATABASE_URL=postgresql://user:pass@localhost/db
API_BASE_URL=https://api.example.comUsage in workflow:
nodes:
- id: call-api
data:
params:
apiKey: "{{habits.env.OPENAI_API_KEY}}"
url: "{{habits.env.API_BASE_URL}}/chat"Workflow Context (habits.context.*)
Access metadata about the current workflow execution.
| Variable | Description | Example Value |
|---|---|---|
{{habits.context.workflowId}} | Current workflow ID | "my-workflow" |
{{habits.context.workflowName}} | Workflow display name | "My Workflow" |
{{habits.context.executionId}} | Unique execution run ID | "550e8400-e29b..." |
{{habits.context.timestamp}} | Execution start time (ISO) | "2024-01-15T10:30:00.000Z" |
{{habits.context.startTime}} | Same as timestamp | "2024-01-15T10:30:00.000Z" |
{{habits.context.nodeId}} | Currently executing node ID | "send-email" |
Use Cases:
- Logging and auditing
- Creating unique identifiers
- Tracking execution flow
- Debugging
Utility Functions (habits.function.*)
Built-in functions for common operations.
| Function | Description | Example Output |
|---|---|---|
{{habits.function.date()}} | Current date/time (ISO format) | "2024-01-15T10:30:00.000Z" |
{{habits.function.now()}} | Alias for date() | "2024-01-15T10:30:00.000Z" |
{{habits.function.timestamp()}} | Unix timestamp (milliseconds) | 1705315800000 |
{{habits.function.uuid()}} | Generate random UUID v4 | "550e8400-e29b-41d4..." |
{{habits.function.random(min, max)}} | Random float in range | 0.7234 (for 0-1) |
{{habits.function.randomInt(min, max)}} | Random integer in range | 42 (for 1-100) |
{{habits.function.stringify(value)}} | Convert to JSON string | "value" |
Examples:
params:
uniqueId: "{{habits.function.uuid()}}"
createdAt: "{{habits.function.date()}}"
randomScore: "{{habits.function.random(0, 100)}}"
diceRoll: "{{habits.function.randomInt(1, 6)}}"Previous Node Outputs ({{nodeId.*}})
Reference output from previous nodes using their node ID.
| Variable | Description |
|---|---|
{{node-id.output}} | Full output from node |
{{node-id.output.fieldName}} | Specific field from output |
{{node-id.status}} | Node execution status |
{{node-id.output[0]}} | Array indexing |
Example workflow:
nodes:
- id: fetch-data
data:
module: "@ha-bits/bit-http"
params:
url: "https://api.example.com/users"
method: GET
- id: process-data
data:
module: "@ha-bits/bit-code"
params:
input: "{{fetch-data.output}}"
# Access nested data
firstUser: "{{fetch-data.output.data[0].name}}"Note: Node IDs must be unique within a workflow. Use descriptive IDs like fetch-users, send-email, transform-data.
Variable Resolution Order
When a variable is evaluated, Habits checks in this order:
habits.env.*- Environment variables (fromprocess.env)habits.function.*- Utility functionshabits.context.*- Workflow execution contexthabits.header.*- HTTP request headershabits.input.*- Request body / CLI input{nodeId}.*- Previous node outputs- Direct context access - Raw context property
Examples
Complete Workflow Example
name: User Notification Workflow
nodes:
- id: get-user
data:
framework: bits
module: "@ha-bits/bit-http"
params:
url: "{{habits.env.API_URL}}/users/{{habits.input.userId}}"
headers:
Authorization: "Bearer {{habits.env.API_TOKEN}}"
- id: send-notification
data:
framework: bits
module: "@ha-bits/bit-email"
params:
to: "{{get-user.output.email}}"
subject: "Hello {{get-user.output.name}}!"
body: |
Hi {{get-user.output.name}},
This notification was sent at {{habits.function.date()}}.
Execution ID: {{habits.context.executionId}}
Best regards,
Automated System
edges:
- source: get-user
target: send-notificationUsing Variables in Conditions
- id: check-status
data:
framework: bits
module: "@ha-bits/bit-if"
params:
branches:
- value1: "{{previous-node.output.status}}"
operator: equals
value2: "success"
label: on-success
- value1: "{{previous-node.output.status}}"
operator: equals
value2: "error"
label: on-errorTroubleshooting
Variable Not Resolving
Symptom: Variable appears as literal text {{habits.input.userId}}
Causes:
- Typo in variable path
- Property doesn't exist in context
- Node hasn't executed yet
Solution: Check the execution logs for warnings about missing properties.
Environment Variable Not Found
Symptom: Empty string returned for {{habits.env.VAR_NAME}}
Causes:
- Variable not set in environment
- Variable name case mismatch (environment variables are case-sensitive)
Solution:
- Check
.envfile exists and is loaded - Verify exact variable name
- Use
habits.env.VAR_NAME(not$VAR_NAME)
Node Output Not Available
Symptom: Error accessing {{node-id.output}}
Causes:
- Node hasn't executed yet (check edge connections)
- Node ID typo
- Node was skipped due to flow control
Solution:
- Verify edge connections in workflow
- Check node execution status in logs
- Use exact node ID (case-sensitive)
