10 KiB
Core Pack Actions
Overview
All actions in the core pack are implemented as pure POSIX shell scripts with zero external dependencies (except curl for HTTP actions). This design ensures maximum portability and minimal runtime requirements.
Key Principles:
- POSIX shell only - No bash-specific features, works everywhere
- DOTENV parameter format - Simple key=value format, no JSON parsing needed
- No jq/yq/Python/Node.js - Core pack depends only on standard POSIX utilities
- Stdin parameter delivery - Secure, never exposed in process list
- Explicit output formats - text, json, or yaml
Parameter Delivery Method
All actions use stdin with DOTENV format:
- Parameters read from stdin in
key=valueformat - Use
parameter_delivery: stdinandparameter_format: dotenvin YAML - Stdin is closed after delivery; scripts read until EOF
- DO NOT use environment variables for parameters
Example DOTENV input:
message="Hello World"
seconds=5
enabled=true
Output Format
All actions must specify an output_format:
text- Plain text output (stored as-is, no parsing)json- JSON structured data (parsed into JSONB field)yaml- YAML structured data (parsed into JSONB field)
Output schema:
- Only applicable for
jsonandyamlformats - Describes the structure of data written to stdout
- Should NOT include stdout/stderr/exit_code (captured automatically)
Environment Variables
Standard Environment Variables (Provided by Worker)
The worker automatically provides these environment variables to all action executions:
| Variable | Description | Always Present |
|---|---|---|
ATTUNE_ACTION |
Action ref (e.g., core.http_request) |
✅ Yes |
ATTUNE_EXEC_ID |
Execution database ID | ✅ Yes |
ATTUNE_API_TOKEN |
Execution-scoped API token | ✅ Yes |
ATTUNE_RULE |
Rule ref that triggered execution | ❌ Only if from rule |
ATTUNE_TRIGGER |
Trigger ref that caused enforcement | ❌ Only if from trigger |
Use cases:
- Logging with execution context
- Calling Attune API (using
ATTUNE_API_TOKEN) - Conditional logic based on rule/trigger
- Creating child executions
- Accessing secrets via API
Custom Environment Variables (Optional)
Custom environment variables can be set via execution.env_vars field for:
- Debug/logging controls (e.g.,
DEBUG=1,LOG_LEVEL=debug) - Runtime configuration (e.g., custom paths, feature flags)
Environment variables should NEVER be used for:
- Action parameters (use stdin DOTENV instead)
- Secrets or credentials (use
ATTUNE_API_TOKENto fetch from key vault) - User-provided data (use stdin parameters)
Implementation Pattern
POSIX Shell Actions (Standard Pattern)
All core pack actions follow this pattern:
#!/bin/sh
# Action Name - Core Pack
# Brief description
#
# This script uses pure POSIX shell without external dependencies like jq.
# It reads parameters in DOTENV format from stdin until EOF.
set -e
# Initialize variables with defaults
param1=""
param2="default_value"
# Read DOTENV-formatted parameters from stdin until EOF
while IFS= read -r line; do
[ -z "$line" ] && continue
key="${line%%=*}"
value="${line#*=}"
# Remove quotes if present
case "$value" in
\"*\") value="${value#\"}"; value="${value%\"}" ;;
\'*\') value="${value#\'}"; value="${value%\'}" ;;
esac
# Process parameters
case "$key" in
param1) param1="$value" ;;
param2) param2="$value" ;;
esac
done
# Validate required parameters
if [ -z "$param1" ]; then
echo "ERROR: param1 is required" >&2
exit 1
fi
# Action logic
echo "Processing: $param1"
exit 0
Boolean Normalization
case "$bool_param" in
true|True|TRUE|yes|Yes|YES|1) bool_param="true" ;;
*) bool_param="false" ;;
esac
Numeric Validation
case "$number" in
''|*[!0-9]*)
echo "ERROR: must be a number" >&2
exit 1
;;
esac
Core Pack Actions
Simple Actions
- echo.sh - Outputs a message (reference implementation)
- sleep.sh - Pauses execution for a specified duration
- noop.sh - Does nothing (useful for testing and placeholder workflows)
HTTP Action
- http_request.sh - Makes HTTP requests with full feature support:
- Multiple HTTP methods (GET, POST, PUT, PATCH, DELETE, etc.)
- Custom headers and query parameters
- Authentication (basic, bearer token)
- SSL verification control
- Redirect following
- JSON output with parsed response
Pack Management Actions (API Wrappers)
These actions wrap Attune API endpoints for pack management:
- download_packs.sh - Downloads packs from git/HTTP/registry
- build_pack_envs.sh - Builds runtime environments for packs
- register_packs.sh - Registers packs in the database
- get_pack_dependencies.sh - Analyzes pack dependencies
All API wrappers:
- Accept parameters via DOTENV format
- Build JSON request bodies manually (no jq)
- Make authenticated API calls with curl
- Extract response data using simple sed patterns
- Return structured JSON output
Testing Actions Locally
Test actions by echoing DOTENV format to stdin:
# Test echo action
printf 'message="Hello World"\n' | ./echo.sh
# Test with empty parameters
printf '' | ./echo.sh
# Test sleep action
printf 'seconds=2\nmessage="Sleeping..."\n' | ./sleep.sh
# Test http_request action
printf 'url="https://api.github.com"\nmethod="GET"\n' | ./http_request.sh
# Test with file input
cat params.dotenv | ./echo.sh
YAML Configuration Example
ref: core.example_action
label: "Example Action"
description: "Example action demonstrating DOTENV format"
enabled: true
runner_type: shell
entry_point: example.sh
# IMPORTANT: Use DOTENV format for POSIX shell compatibility
parameter_delivery: stdin
parameter_format: dotenv
# Output format: text, json, or yaml
output_format: text
parameters:
type: object
properties:
message:
type: string
description: "Message to output"
default: ""
count:
type: integer
description: "Number of times to repeat"
default: 1
required:
- message
Dependencies
Core pack has ZERO runtime dependencies:
✅ Required (universally available):
- POSIX-compliant shell (
/bin/sh) curl(for HTTP actions only)- Standard POSIX utilities:
sed,mktemp,cat,printf,sleep
❌ NOT Required:
jq- Eliminated (was used for JSON parsing)yq- Never used- Python - Not used in core pack actions
- Node.js - Not used in core pack actions
- bash - Scripts are POSIX-compliant
- Any other external tools or libraries
This makes the core pack maximally portable and suitable for minimal containers (Alpine, distroless, etc.).
Security Benefits
- No process exposure - Parameters never appear in
ps,/proc/<pid>/environ - Secure by default - All actions use stdin, no special configuration needed
- Clear separation - Action parameters vs. environment configuration
- Audit friendly - All sensitive data flows through stdin, not environment
- Minimal attack surface - No external dependencies to exploit
Best Practices
Parameters
- Always use stdin with DOTENV format for action parameters
- Handle quoted values - Remove both single and double quotes
- Provide sensible defaults - Use empty string, 0, false as appropriate
- Validate required params - Exit with error if truly required parameters missing
- Mark secrets - Use
secret: truein YAML for sensitive parameters - Never use env vars for parameters - Parameters come from stdin only
Environment Variables
- Use standard ATTUNE_ variables* - Worker provides execution context
- Access API with ATTUNE_API_TOKEN - Execution-scoped authentication
- Log with context - Include
ATTUNE_ACTIONandATTUNE_EXEC_IDin logs - Never log ATTUNE_API_TOKEN - Security sensitive
- Use env vars for runtime config only - Not for user data or parameters
Output Format
- Specify output_format - Always set to "text", "json", or "yaml"
- Use text for simple output - Messages, logs, unstructured data
- Use json for structured data - API responses, complex results
- Define schema for structured output - Only for json/yaml formats
- Use stderr for diagnostics - Error messages go to stderr, not stdout
- Return proper exit codes - 0 for success, non-zero for failure
Shell Script Best Practices
- Use
#!/bin/sh- POSIX shell, not bash - Use
set -e- Exit on error - Quote all variables -
"$var"not$var - Use
casenotif- More portable for pattern matching - Clean up temp files - Use trap handlers
- Avoid bash-isms - No
[[,${var^^},=~, arrays, etc.
Execution Metadata (Automatic)
The following are automatically captured by the worker and should NOT be included in output schemas:
stdout- Raw standard output (captured as-is)stderr- Standard error output (written to log file)exit_code- Process exit code (0 = success)duration_ms- Execution duration in milliseconds
These are execution system concerns, not action output concerns.
Example: Complete Action
#!/bin/sh
# Example Action - Core Pack
# Demonstrates DOTENV parameter parsing and environment variable usage
#
# This script uses pure POSIX shell without external dependencies like jq.
set -e
# Log execution start
echo "[$ATTUNE_ACTION] [Exec: $ATTUNE_EXEC_ID] Starting" >&2
# Initialize variables
url=""
timeout="30"
# Read DOTENV parameters from stdin until EOF
while IFS= read -r line; do
[ -z "$line" ] && continue
key="${line%%=*}"
value="${line#*=}"
case "$value" in
\"*\") value="${value#\"}"; value="${value%\"}" ;;
esac
case "$key" in
url) url="$value" ;;
timeout) timeout="$value" ;;
esac
done
# Validate
if [ -z "$url" ]; then
echo "ERROR: url is required" >&2
exit 1
fi
# Execute
echo "Fetching: $url" >&2
result=$(curl -s --max-time "$timeout" "$url")
# Output
echo "$result"
echo "[$ATTUNE_ACTION] [Exec: $ATTUNE_EXEC_ID] Completed" >&2
exit 0
Further Documentation
- Pattern Reference:
docs/QUICKREF-dotenv-shell-actions.md - Pack Structure:
docs/pack-structure.md - Example Actions:
echo.sh- Simplest reference implementationhttp_request.sh- Complex action with full HTTP clientregister_packs.sh- API wrapper with JSON construction