documenting action spec

This commit is contained in:
2026-02-09 00:30:48 -06:00
parent a74e13fa0b
commit 588b319fec
38 changed files with 3050 additions and 286 deletions

View File

@@ -1,8 +1,8 @@
# Build Pack Environments Action
# Creates runtime environments and installs dependencies for packs
name: build_pack_envs
ref: core.build_pack_envs
label: "Build Pack Environments"
description: "Build runtime environments for packs and install declared dependencies (Python requirements.txt, Node.js package.json)"
enabled: true
runner_type: shell

View File

@@ -1,8 +1,8 @@
# Download Packs Action
# Downloads packs from various sources (git repositories, HTTP archives, or pack registry)
name: download_packs
ref: core.download_packs
label: "Download Packs"
description: "Download packs from git repositories, HTTP archives, or pack registry to a temporary directory"
enabled: true
runner_type: shell

View File

@@ -1,8 +1,8 @@
# Echo Action
# Outputs a message to stdout
name: echo
ref: core.echo
label: "Echo"
description: "Echo a message to stdout"
enabled: true
@@ -26,7 +26,6 @@ parameters:
message:
type: string
description: "Message to echo (empty string if not provided)"
required: []
# Output schema: not applicable for text output format
# The action outputs plain text to stdout

View File

@@ -1,8 +1,8 @@
# Get Pack Dependencies Action
# Parses pack.yaml files to identify pack and runtime dependencies
name: get_pack_dependencies
ref: core.get_pack_dependencies
label: "Get Pack Dependencies"
description: "Parse pack.yaml files to extract pack dependencies and runtime requirements"
enabled: true
runner_type: shell

View File

@@ -1,209 +1,259 @@
#!/bin/bash
#!/bin/sh
# HTTP Request Action - Core Pack
# Make HTTP requests to external APIs using curl
#
# This script uses pure POSIX shell without external dependencies like jq.
# It reads parameters in DOTENV format from stdin until the delimiter.
set -e
set -o pipefail
# Read JSON parameters from stdin
INPUT=$(cat)
# Initialize variables
url=""
method="GET"
body=""
json_body=""
timeout="30"
verify_ssl="true"
auth_type="none"
auth_username=""
auth_password=""
auth_token=""
follow_redirects="true"
max_redirects="10"
# Parse required parameters
URL=$(echo "$INPUT" | jq -r '.url // ""')
# Temporary files
headers_file=$(mktemp)
query_params_file=$(mktemp)
body_file=""
temp_headers=$(mktemp)
curl_output=$(mktemp)
if [ -z "$URL" ] || [ "$URL" = "null" ]; then
echo "ERROR: 'url' parameter is required" >&2
cleanup() {
rm -f "$headers_file" "$query_params_file" "$temp_headers" "$curl_output"
[ -n "$body_file" ] && [ -f "$body_file" ] && rm -f "$body_file"
}
trap cleanup EXIT
# Read DOTENV-formatted parameters
while IFS= read -r line; do
case "$line" in
*"---ATTUNE_PARAMS_END---"*) break ;;
esac
[ -z "$line" ] && continue
key="${line%%=*}"
value="${line#*=}"
# Remove quotes
case "$value" in
\"*\") value="${value#\"}"; value="${value%\"}" ;;
\'*\') value="${value#\'}"; value="${value%\'}" ;;
esac
# Process parameters
case "$key" in
url) url="$value" ;;
method) method="$value" ;;
body) body="$value" ;;
json_body) json_body="$value" ;;
timeout) timeout="$value" ;;
verify_ssl) verify_ssl="$value" ;;
auth_type) auth_type="$value" ;;
auth_username) auth_username="$value" ;;
auth_password) auth_password="$value" ;;
auth_token) auth_token="$value" ;;
follow_redirects) follow_redirects="$value" ;;
max_redirects) max_redirects="$value" ;;
headers.*)
printf '%s: %s\n' "${key#headers.}" "$value" >> "$headers_file"
;;
query_params.*)
printf '%s=%s\n' "${key#query_params.}" "$value" >> "$query_params_file"
;;
esac
done
# Validate required
if [ -z "$url" ]; then
printf '{"status_code":0,"headers":{},"body":"","json":null,"elapsed_ms":0,"url":"","success":false,"error":"url parameter is required"}\n'
exit 1
fi
# Parse optional parameters
METHOD=$(echo "$INPUT" | jq -r '.method // "GET"' | tr '[:lower:]' '[:upper:]')
HEADERS=$(echo "$INPUT" | jq -r '.headers // {}')
BODY=$(echo "$INPUT" | jq -r '.body // ""')
JSON_BODY=$(echo "$INPUT" | jq -c '.json_body // null')
QUERY_PARAMS=$(echo "$INPUT" | jq -r '.query_params // {}')
TIMEOUT=$(echo "$INPUT" | jq -r '.timeout // 30')
VERIFY_SSL=$(echo "$INPUT" | jq -r '.verify_ssl // true')
AUTH_TYPE=$(echo "$INPUT" | jq -r '.auth_type // "none"')
FOLLOW_REDIRECTS=$(echo "$INPUT" | jq -r '.follow_redirects // true')
MAX_REDIRECTS=$(echo "$INPUT" | jq -r '.max_redirects // 10')
# Normalize method
method=$(printf '%s' "$method" | tr '[:lower:]' '[:upper:]')
# Build URL with query parameters
FINAL_URL="$URL"
if [ "$QUERY_PARAMS" != "{}" ] && [ "$QUERY_PARAMS" != "null" ]; then
QUERY_STRING=$(echo "$QUERY_PARAMS" | jq -r 'to_entries | map("\(.key)=\(.value | @uri)") | join("&")')
if [[ "$FINAL_URL" == *"?"* ]]; then
FINAL_URL="${FINAL_URL}&${QUERY_STRING}"
else
FINAL_URL="${FINAL_URL}?${QUERY_STRING}"
# URL encode helper
url_encode() {
printf '%s' "$1" | sed 's/ /%20/g; s/!/%21/g; s/"/%22/g; s/#/%23/g; s/\$/%24/g; s/&/%26/g; s/'\''/%27/g'
}
# Build URL with query params
final_url="$url"
if [ -s "$query_params_file" ]; then
query_string=""
while IFS='=' read -r param_name param_value; do
[ -z "$param_name" ] && continue
encoded=$(url_encode "$param_value")
[ -z "$query_string" ] && query_string="${param_name}=${encoded}" || query_string="${query_string}&${param_name}=${encoded}"
done < "$query_params_file"
if [ -n "$query_string" ]; then
case "$final_url" in
*\?*) final_url="${final_url}&${query_string}" ;;
*) final_url="${final_url}?${query_string}" ;;
esac
fi
fi
# Build curl arguments array
CURL_ARGS=(
-X "$METHOD"
-s # Silent mode
-w "\n%{http_code}\n%{time_total}\n%{url_effective}\n" # Write out metadata
--max-time "$TIMEOUT"
--connect-timeout 10
)
# Handle SSL verification
if [ "$VERIFY_SSL" = "false" ]; then
CURL_ARGS+=(-k)
# Prepare body
if [ -n "$json_body" ]; then
body_file=$(mktemp)
printf '%s' "$json_body" > "$body_file"
elif [ -n "$body" ]; then
body_file=$(mktemp)
printf '%s' "$body" > "$body_file"
fi
# Handle redirects
if [ "$FOLLOW_REDIRECTS" = "true" ]; then
CURL_ARGS+=(-L --max-redirs "$MAX_REDIRECTS")
fi
# Build curl args file (avoid shell escaping issues)
curl_args=$(mktemp)
{
printf -- '-X\n%s\n' "$method"
printf -- '-s\n'
printf -- '-w\n\n%%{http_code}\n%%{url_effective}\n\n'
printf -- '--max-time\n%s\n' "$timeout"
printf -- '--connect-timeout\n10\n'
printf -- '--dump-header\n%s\n' "$temp_headers"
[ "$verify_ssl" = "false" ] && printf -- '-k\n'
if [ "$follow_redirects" = "true" ]; then
printf -- '-L\n'
printf -- '--max-redirs\n%s\n' "$max_redirects"
fi
# Add headers
if [ "$HEADERS" != "{}" ] && [ "$HEADERS" != "null" ]; then
while IFS= read -r header; do
if [ -n "$header" ]; then
CURL_ARGS+=(-H "$header")
fi
done < <(echo "$HEADERS" | jq -r 'to_entries | map("\(.key): \(.value)") | .[]')
fi
if [ -s "$headers_file" ]; then
while IFS= read -r h; do
[ -n "$h" ] && printf -- '-H\n%s\n' "$h"
done < "$headers_file"
fi
# Handle authentication
case "$AUTH_TYPE" in
basic)
AUTH_USERNAME=$(echo "$INPUT" | jq -r '.auth_username // ""')
AUTH_PASSWORD=$(echo "$INPUT" | jq -r '.auth_password // ""')
if [ -n "$AUTH_USERNAME" ] && [ "$AUTH_USERNAME" != "null" ]; then
CURL_ARGS+=(-u "${AUTH_USERNAME}:${AUTH_PASSWORD}")
fi
;;
bearer)
AUTH_TOKEN=$(echo "$INPUT" | jq -r '.auth_token // ""')
if [ -n "$AUTH_TOKEN" ] && [ "$AUTH_TOKEN" != "null" ]; then
CURL_ARGS+=(-H "Authorization: Bearer ${AUTH_TOKEN}")
fi
;;
esac
# Handle request body
if [ "$JSON_BODY" != "null" ] && [ "$JSON_BODY" != "" ]; then
CURL_ARGS+=(-H "Content-Type: application/json")
CURL_ARGS+=(-d "$JSON_BODY")
elif [ -n "$BODY" ] && [ "$BODY" != "null" ]; then
CURL_ARGS+=(-d "$BODY")
fi
# Capture start time
START_TIME=$(date +%s%3N)
# Make the request and capture response headers
TEMP_HEADERS=$(mktemp)
CURL_ARGS+=(--dump-header "$TEMP_HEADERS")
# Execute curl and capture output
set +e
RESPONSE=$(curl "${CURL_ARGS[@]}" "$FINAL_URL" 2>&1)
CURL_EXIT_CODE=$?
set -e
# Calculate elapsed time
END_TIME=$(date +%s%3N)
ELAPSED_MS=$((END_TIME - START_TIME))
# Parse curl output (last 3 lines are: http_code, time_total, url_effective)
BODY_OUTPUT=$(echo "$RESPONSE" | head -n -3)
HTTP_CODE=$(echo "$RESPONSE" | tail -n 3 | head -n 1 | tr -d '\r\n')
CURL_TIME=$(echo "$RESPONSE" | tail -n 2 | head -n 1 | tr -d '\r\n')
EFFECTIVE_URL=$(echo "$RESPONSE" | tail -n 1 | tr -d '\r\n')
# Ensure HTTP_CODE is numeric, default to 0 if not
if ! [[ "$HTTP_CODE" =~ ^[0-9]+$ ]]; then
HTTP_CODE=0
fi
# If curl failed, handle error
if [ "$CURL_EXIT_CODE" -ne 0 ]; then
ERROR_MSG="curl failed with exit code $CURL_EXIT_CODE"
# Determine specific error
case $CURL_EXIT_CODE in
6) ERROR_MSG="Could not resolve host" ;;
7) ERROR_MSG="Failed to connect to host" ;;
28) ERROR_MSG="Request timeout" ;;
35) ERROR_MSG="SSL/TLS connection error" ;;
52) ERROR_MSG="Empty reply from server" ;;
56) ERROR_MSG="Failure receiving network data" ;;
*) ERROR_MSG="curl error code $CURL_EXIT_CODE" ;;
case "$auth_type" in
basic)
[ -n "$auth_username" ] && printf -- '-u\n%s:%s\n' "$auth_username" "$auth_password"
;;
bearer)
[ -n "$auth_token" ] && printf -- '-H\nAuthorization: Bearer %s\n' "$auth_token"
;;
esac
# Output error result as JSON
jq -n \
--arg error "$ERROR_MSG" \
--argjson elapsed "$ELAPSED_MS" \
--arg url "$FINAL_URL" \
'{
status_code: 0,
headers: {},
body: "",
json: null,
elapsed_ms: $elapsed,
url: $url,
success: false,
error: $error
}'
if [ -n "$body_file" ] && [ -f "$body_file" ]; then
[ -n "$json_body" ] && printf -- '-H\nContent-Type: application/json\n'
printf -- '-d\n@%s\n' "$body_file"
fi
rm -f "$TEMP_HEADERS"
printf -- '%s\n' "$final_url"
} > "$curl_args"
# Execute curl
start_time=$(date +%s%3N 2>/dev/null || echo $(($(date +%s) * 1000)))
set +e
xargs -a "$curl_args" curl > "$curl_output" 2>&1
curl_exit_code=$?
set -e
rm -f "$curl_args"
end_time=$(date +%s%3N 2>/dev/null || echo $(($(date +%s) * 1000)))
elapsed_ms=$((end_time - start_time))
# Parse output
response=$(cat "$curl_output")
total_lines=$(printf '%s\n' "$response" | wc -l)
body_lines=$((total_lines - 2))
if [ "$body_lines" -gt 0 ]; then
body_output=$(printf '%s\n' "$response" | head -n "$body_lines")
else
body_output=""
fi
http_code=$(printf '%s\n' "$response" | tail -n 2 | head -n 1 | tr -d '\r\n ')
effective_url=$(printf '%s\n' "$response" | tail -n 1 | tr -d '\r\n')
case "$http_code" in
''|*[!0-9]*) http_code=0 ;;
esac
# Handle errors
if [ "$curl_exit_code" -ne 0 ]; then
error_msg="curl error code $curl_exit_code"
case $curl_exit_code in
6) error_msg="Could not resolve host" ;;
7) error_msg="Failed to connect to host" ;;
28) error_msg="Request timeout" ;;
35) error_msg="SSL/TLS connection error" ;;
52) error_msg="Empty reply from server" ;;
56) error_msg="Failure receiving network data" ;;
esac
error_msg=$(printf '%s' "$error_msg" | sed 's/\\/\\\\/g; s/"/\\"/g')
printf '{"status_code":0,"headers":{},"body":"","json":null,"elapsed_ms":%d,"url":"%s","success":false,"error":"%s"}\n' \
"$elapsed_ms" "$final_url" "$error_msg"
exit 1
fi
# Parse response headers into JSON
HEADERS_JSON="{}"
if [ -f "$TEMP_HEADERS" ]; then
# Skip the status line and parse headers
HEADERS_JSON=$(grep -v "^HTTP/" "$TEMP_HEADERS" | grep ":" | sed 's/\r$//' | jq -R -s -c '
split("\n") |
map(select(length > 0)) |
map(split(": "; "") | select(length > 1) | {key: .[0], value: (.[1:] | join(": "))}) |
map({(.key): .value}) |
add // {}
' || echo '{}')
rm -f "$TEMP_HEADERS"
# Parse headers
headers_json="{"
first_header=true
if [ -f "$temp_headers" ]; then
while IFS= read -r line; do
case "$line" in HTTP/*|'') continue ;; esac
header_name="${line%%:*}"
header_value="${line#*:}"
[ "$header_name" = "$line" ] && continue
header_value=$(printf '%s' "$header_value" | sed 's/^ *//; s/ *$//; s/\r$//; s/\\/\\\\/g; s/"/\\"/g')
header_name=$(printf '%s' "$header_name" | sed 's/\\/\\\\/g; s/"/\\"/g')
if [ "$first_header" = true ]; then
headers_json="${headers_json}\"${header_name}\":\"${header_value}\""
first_header=false
else
headers_json="${headers_json},\"${header_name}\":\"${header_value}\""
fi
done < "$temp_headers"
fi
headers_json="${headers_json}}"
# Success check
success="false"
[ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ] && success="true"
# Escape body
body_escaped=$(printf '%s' "$body_output" | sed 's/\\/\\\\/g; s/"/\\"/g; s/ /\\t/g' | awk '{printf "%s\\n", $0}' | sed 's/\\n$//')
# Detect JSON
json_parsed="null"
if [ -n "$body_output" ]; then
first_char=$(printf '%s' "$body_output" | sed 's/^[[:space:]]*//' | head -c 1)
last_char=$(printf '%s' "$body_output" | sed 's/[[:space:]]*$//' | tail -c 1)
case "$first_char" in
'{'|'[')
case "$last_char" in
'}'|']') json_parsed="$body_output" ;;
esac
;;
esac
fi
# Ensure HEADERS_JSON is valid JSON
if ! echo "$HEADERS_JSON" | jq empty 2>/dev/null; then
HEADERS_JSON="{}"
# Output
if [ "$json_parsed" = "null" ]; then
printf '{"status_code":%d,"headers":%s,"body":"%s","json":null,"elapsed_ms":%d,"url":"%s","success":%s}\n' \
"$http_code" "$headers_json" "$body_escaped" "$elapsed_ms" "$effective_url" "$success"
else
printf '{"status_code":%d,"headers":%s,"body":"%s","json":%s,"elapsed_ms":%d,"url":"%s","success":%s}\n' \
"$http_code" "$headers_json" "$body_escaped" "$json_parsed" "$elapsed_ms" "$effective_url" "$success"
fi
# Determine if successful (2xx status code)
SUCCESS=false
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
SUCCESS=true
fi
# Try to parse body as JSON
JSON_PARSED="null"
if [ -n "$BODY_OUTPUT" ] && echo "$BODY_OUTPUT" | jq empty 2>/dev/null; then
JSON_PARSED=$(echo "$BODY_OUTPUT" | jq -c '.' || echo 'null')
fi
# Output result as JSON
jq -n \
--argjson status_code "$HTTP_CODE" \
--argjson headers "$HEADERS_JSON" \
--arg body "$BODY_OUTPUT" \
--argjson json "$JSON_PARSED" \
--argjson elapsed "$ELAPSED_MS" \
--arg url "$EFFECTIVE_URL" \
--argjson success "$SUCCESS" \
'{
status_code: $status_code,
headers: $headers,
body: $body,
json: $json,
elapsed_ms: $elapsed,
url: $url,
success: $success
}'
# Exit with success
exit 0

View File

@@ -1,8 +1,8 @@
# HTTP Request Action
# Make HTTP requests to external APIs
name: http_request
ref: core.http_request
label: "HTTP Request"
description: "Make HTTP requests to external APIs with support for various methods, headers, and authentication"
enabled: true
@@ -13,9 +13,9 @@ runner_type: shell
entry_point: http_request.sh
# Parameter delivery configuration (for security)
# Use stdin + JSON for secure parameter passing (credentials won't appear in process list)
# Use stdin + DOTENV for secure parameter passing (credentials won't appear in process list)
parameter_delivery: stdin
parameter_format: json
parameter_format: dotenv
# Output format: json (structured data parsing enabled)
output_format: json

View File

@@ -1,8 +1,8 @@
# No Operation Action
# Does nothing - useful for testing and placeholder workflows
name: noop
ref: core.noop
label: "No-Op"
description: "Does nothing - useful for testing and placeholder workflows"
enabled: true
@@ -32,7 +32,6 @@ parameters:
default: 0
minimum: 0
maximum: 255
required: []
# Output schema: not applicable for text output format
# The action outputs plain text to stdout

View File

@@ -1,8 +1,8 @@
# Register Packs Action
# Validates pack structure and loads components into database
name: register_packs
ref: core.register_packs
label: "Register Packs"
description: "Register packs by validating schemas, loading components into database, and copying to permanent storage"
enabled: true
runner_type: shell

View File

@@ -1,8 +1,8 @@
# Sleep Action
# Pauses execution for a specified duration
name: sleep
ref: core.sleep
label: "Sleep"
description: "Sleep for a specified number of seconds"
enabled: true

View File

@@ -25,7 +25,6 @@ conf_schema:
type: boolean
description: "Enable debug logging for core pack actions"
default: false
required: []
# Default pack configuration
config:

View File

@@ -1,8 +1,8 @@
# Timer Sensor
# Monitors time and fires all timer trigger types
name: interval_timer_sensor
ref: core.interval_timer_sensor
label: "Interval Timer Sensor"
description: "Built-in sensor that monitors time and fires timer triggers (interval, cron, and one-shot datetime)"
enabled: true
@@ -28,7 +28,6 @@ parameters:
default: 1
minimum: 1
maximum: 60
required: []
# Poll interval (how often the sensor checks for events)
poll_interval: 1

View File

@@ -1,8 +1,8 @@
# Cron Timer Trigger
# Fires based on cron schedule expressions
name: crontimer
ref: core.crontimer
label: "Cron Timer"
description: "Fires based on a cron schedule expression (e.g., '0 0 * * * *' for every hour)"
enabled: true

View File

@@ -1,8 +1,8 @@
# Datetime Timer Trigger
# Fires once at a specific date and time
name: datetimetimer
ref: core.datetimetimer
label: "DateTime Timer"
description: "Fires once at a specific date and time"
enabled: true

View File

@@ -1,8 +1,8 @@
# Interval Timer Trigger
# Fires at regular intervals based on time unit and interval
name: intervaltimer
ref: core.intervaltimer
label: "Interval Timer"
description: "Fires at regular intervals based on specified time unit and interval"
enabled: true

106
packs/examples/README.md Normal file
View File

@@ -0,0 +1,106 @@
# Examples Pack
**Demonstration actions and workflows for learning Attune**
## Overview
The Examples pack provides reference implementations that demonstrate various Attune features and best practices. These examples are designed for learning and can be used as templates for building your own actions.
## Contents
### Actions
#### `list_example` - JSON Lines Output Demo
Demonstrates the JSON Lines (JSONL) output format for streaming results.
**Features:**
- Streams multiple JSON objects as output
- Each line is a separate JSON object
- Results are collected into an array
- Useful for processing lists or progress updates
**Usage:**
```bash
attune action execute examples.list_example --param count=10
```
**Parameters:**
- `count` (integer): Number of items to generate (default: 5, range: 1-100)
**Output Format:** JSONL - Each line is parsed as JSON and collected into an array
**Example Output:**
```json
[
{"id": 0, "value": "item-0", "timestamp": "2024-01-20T10:30:00Z"},
{"id": 1, "value": "item-1", "timestamp": "2024-01-20T10:30:01Z"},
{"id": 2, "value": "item-2", "timestamp": "2024-01-20T10:30:02Z"}
]
```
## Use Cases
### Learning Attune
- Study action structure and metadata
- Understand parameter schemas
- Learn about different output formats
- See working implementations
### Templates
- Copy and modify examples for your own actions
- Reference implementations for common patterns
- Starting point for new packs
## Installation
The examples pack is not installed by default but can be easily added:
```bash
# Via pack registry (if published)
attune pack install examples
# Via local directory
attune pack install --local ./packs/examples
```
## Development
### Adding New Examples
When adding new example actions:
1. Create action metadata in `actions/<name>.yaml`
2. Implement the action script in `actions/<name>.sh` (or .py, .js)
3. Use ref format: `examples.<action_name>`
4. Add documentation to this README
5. Include clear comments in the code
6. Demonstrate a specific feature or pattern
### Guidelines
- **Keep it simple** - Examples should be easy to understand
- **One concept per example** - Focus on demonstrating one feature clearly
- **Well-commented** - Explain what the code does and why
- **Self-contained** - Minimize external dependencies
- **Documented** - Update this README with usage examples
## Related Documentation
- [Action Development Guide](../../docs/action-development-guide.md)
- [Pack Structure](../../docs/packs/pack-structure.md)
- [Parameter Configuration](../../docs/action-development-guide.md#parameter-configuration)
- [Output Formats](../../docs/action-development-guide.md#output-configuration)
## Contributing
Have an idea for a useful example? Contributions are welcome! Please ensure:
- Examples are educational and demonstrate best practices
- Code is well-commented and easy to follow
- Documentation is updated
- Examples are tested and working
## License
This pack is part of the Attune project and follows the same license terms.

View File

@@ -0,0 +1,17 @@
#!/bin/bash
# List Example Action
# Demonstrates JSON Lines output format for streaming results
set -euo pipefail
# Read parameters from stdin (JSON format)
read -r params_json
# Extract count parameter (default to 5 if not provided)
count=$(echo "$params_json" | jq -r '.count // 5')
# Generate JSON Lines output (one JSON object per line)
for i in $(seq 1 "$count"); do
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo "{\"id\": $i, \"value\": \"item_$i\", \"timestamp\": \"$timestamp\"}"
done

View File

@@ -0,0 +1,58 @@
# List Example Action
# Demonstrates JSON Lines output format for streaming results
ref: examples.list_example
label: "List Example"
description: "Example action that outputs multiple JSON objects as JSON Lines"
enabled: true
# Runner type determines how the action is executed
runner_type: shell
# Entry point is the shell script to execute
entry_point: list_example.sh
# Parameter delivery: stdin for secure parameter passing
parameter_delivery: stdin
parameter_format: json
# Output format: jsonl (each line is a JSON object, collected into array)
output_format: jsonl
# Action parameters schema (standard JSON Schema format)
parameters:
type: object
properties:
count:
type: integer
description: "Number of items to generate"
default: 5
minimum: 1
maximum: 100
# Output schema: array of objects (required for jsonl format)
# Each line in stdout will be parsed as JSON and collected into this array
output_schema:
type: array
items:
type: object
properties:
id:
type: integer
description: "Item identifier"
value:
type: string
description: "Item value"
timestamp:
type: string
description: "ISO 8601 timestamp"
required:
- id
- value
# Tags for categorization
tags:
- utility
- example
- jsonl
- streaming

54
packs/examples/pack.yaml Normal file
View File

@@ -0,0 +1,54 @@
# Examples Pack
# Demonstrates various Attune features and patterns
ref: examples
label: "Examples Pack"
description: "Example actions and workflows demonstrating Attune capabilities"
version: "1.0.0"
author: "Attune Team"
email: "support@attune.io"
# System pack flag
system: false
enabled: true
# Configuration schema
conf_schema:
type: object
properties:
example_setting:
type: string
description: "Example configuration setting"
default: "default_value"
# Default pack configuration
config:
example_setting: "default_value"
# Pack metadata
meta:
category: "examples"
keywords:
- "examples"
- "demos"
- "tutorials"
- "learning"
documentation_url: "https://docs.attune.io/packs/examples"
repository_url: "https://github.com/attune/attune"
description: |
The Examples pack provides reference implementations and demonstrations
of Attune features including:
- JSON Lines (JSONL) output format for streaming results
- Various parameter delivery methods
- Different output formats
- Best practices for action development
# Tags for categorization
tags:
- examples
- demos
- documentation
# Runtime dependencies (none for examples)
runtime_deps: []