Pack Architecture
Taskless Packs are monitoring components that observe HTTP requests and responses between your application and external services. They capture telemetry data without requiring changes to your existing code.
Overview
Section titled “Overview”Packs monitor HTTP traffic by intercepting requests and responses. When your application communicates with third-party services, packs analyze this traffic and extract useful data. Your application continues to function normally while packs collect information in the background.
Request Flow
Section titled “Request Flow”Here’s how packs integrate with your application:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ Your │───►│ Taskless │───►│ 3rd Party ││ Application │◄───│ Loader │◄───│ Service │└─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ (copies of req/resp) ▼ ┌─────────────────┐ │ Pack Collection │ │ (WebAssembly │ │ Plugins) │ └─────────────────┘ │ │ (pack output) ▼ ┌─────────────────┐ │ Logs + │ │ Telemetry │ └─────────────────┘
- Your application initiates a request to a third-party service
- The Taskless Loader intercepts the request and forwards it to the service
- Packs receive copies of the request and response data for processing
- Your application receives the response without any modification
- Telemetry data is sent to your configured destination
WebAssembly Runtime
Section titled “WebAssembly Runtime”Packs run in WebAssembly, a secure runtime environment that provides several important capabilities:
Security: WebAssembly operates in a sandboxed environment, preventing packs from affecting your application or system Performance: WebAssembly executes at near-native speed with minimal performance overhead Language Support: You can write packs in any language that compiles to WebAssembly Isolation: Packs cannot access external resources beyond the HTTP data they’re designed to monitor
Security Restrictions
Section titled “Security Restrictions”Packs operate under strict limitations to ensure system security:
- Network isolation - Cannot make HTTP requests or network connections
- File system isolation - Cannot read or write files
- System isolation - Cannot execute system calls or access operating system functions
- Memory limits - Operate within controlled memory boundaries
- Read-only access - Can observe HTTP data but cannot modify requests or responses
Pack Lifecycle
Section titled “Pack Lifecycle”Packs implement up to three methods that execute at different stages of an HTTP request:
Pre-Request Processing (pre
)
Section titled “Pre-Request Processing (pre)”Executes before the HTTP request is sent to the third-party service.
Common uses:
- Capture request metadata (URL, headers, method)
- Access configuration values
- Initialize tracking variables
- Set up context for subsequent methods
Available data:
- Outgoing request details (URL, headers, method, body when enabled)
- Pack configuration settings
- Environment context
Chunk Processing (chunk
)
Section titled “Chunk Processing (chunk)”Executes for each chunk of response data as it arrives. This method requires explicit enablement in the pack manifest.
Common uses:
- Process streaming responses (Server-Sent Events, chunked transfer encoding)
- Extract data from partial responses
- Monitor large download progress
- Handle real-time data streams
Available data:
- Individual data chunks (base64-encoded)
- Context from previous lifecycle methods
- State accumulated from earlier chunks
Post-Request Processing (post
)
Section titled “Post-Request Processing (post)”Executes after the complete HTTP response is received.
Common uses:
- Analyze complete response data
- Calculate metrics (response time, data size)
- Extract business-relevant information
- Finalize tracking and cleanup
Available data:
- Complete response (status code, headers, body)
- Original request data
- Context from pre and chunk methods
Pack Structure
Section titled “Pack Structure”When you install a pack, Taskless creates a .taskless
directory containing organized pack files:
.taskless/└── [pack-name]/ ├── manifest.json # Pack metadata and configuration schema ├── pack.wasm # Compiled WebAssembly binary └── config.json # User configuration values
Manifest File
Section titled “Manifest File”The manifest defines the pack’s metadata and configuration interface. Here’s an example from the Taskless pack-example repository:
{ "schema": "pre2", "name": "testpack", "version": "0.0.5", "description": "Test / example pack, never published to prod", "permissions": { "body": true }, "fields": [ { "name": "testField", "type": "string", "description": "Test field that should exist in the lifecycle", "default": "test_field_value" } ], "charts": []}
This manifest declares the pack’s name, version, required permissions, and available configuration fields.
WebAssembly Binary
Section titled “WebAssembly Binary”The pack.wasm file contains the compiled pack code that:
- Implements the lifecycle methods (pre, post, chunk)
- Executes within the WebAssembly security sandbox
- Communicates through the Extism plugin interface
Configuration File
Section titled “Configuration File”The config.json file contains user-specific settings:
{ "testField": "custom_value"}
This overrides the default value specified in the manifest.
Configuration System
Section titled “Configuration System”Packs support configurable behavior through a field-based system that allows customization without code changes.
Supported Field Types
Section titled “Supported Field Types”string
: Text values such as API keys, URLs, or descriptive textstring[]
: Arrays of strings for domain lists, tags, or multiple valuesnumber
: Numeric values for thresholds, timeouts, or quantitiesnumber[]
: Arrays of numbers for ranges, percentiles, or multiple numeric valuesboolean
: True/false flags for enabling or disabling features
Configuration Resolution Order
Section titled “Configuration Resolution Order”Pack configuration values are resolved using the following priority:
- User configuration - Values specified in config.json
- Manifest defaults - Default values defined in the pack manifest
- Undefined - No value if neither source provides one
This hierarchy allows pack authors to provide sensible defaults while giving users full control over pack behavior.
Language Support
Section titled “Language Support”Packs can be written in any programming language that compiles to WebAssembly. The Extism PDK ecosystem provides development kits for multiple languages including JavaScript/TypeScript, Rust, Go, Python, C/C++, Zig, Haskell, and F#.
All languages produce compatible WebAssembly modules that use the same lifecycle interface, ensuring consistent behavior regardless of implementation language.
Context and Data Flow
Section titled “Context and Data Flow”Inter-Method Communication
Section titled “Inter-Method Communication”Packs can maintain state between lifecycle methods using a context system. This allows data collected in one method to be used in subsequent methods:
// In pre(): Set up trackingwriteOutput({ context: { startTime: Date.now(), requestId: generateId(), }, capture: { url: request.url, },});
// In post(): Use context from pre()const duration = Date.now() - input.context.startTime;writeOutput({ capture: { requestId: input.context.requestId, duration: duration, },});
Telemetry Output
Section titled “Telemetry Output”Packs generate telemetry data through the capture
field in their output. This data becomes part of your monitoring and observability pipeline:
- Structured data for querying and analysis
- Time-series metrics for dashboards and alerting
- Event tracking for business intelligence
- Error detection for reliability monitoring
The pack architecture provides a secure foundation for observing application interactions with external services while maintaining isolation and zero-trust principles.