Skip to main content
Hooks serve as a bridge between your backend or server-side scripts and the Autosana testing environment. They allow you to communicate data, set the state of the app, set the state of a user, etc. They are short programs that run in sandboxed environments during the testing process. They can be added to suites and flows, and any output from them (print statements, console.log, echo) is visible to the agent. A few common examples:
  1. Resetting a user’s onboarding in the backend via JS code
  2. Generating a random email to be used by the Autosana agent via Python code
  3. Returning a magic link or OTP code from your server for Autosana to use in the flow via a cURL request
  4. Mocking audio or video input by hitting an endpoint on your server via TypeScript code
Possibilities are endless and usually the more hooks the better, as it adds a level of determinism to the state of the test! Execution Positions There are three hook execution positions:
  1. Setup Hooks: Run before suites or flows start. Great for providing context.
  2. Runtime Hooks: Run as an action during the flow — added directly into flow instructions, allows real-time backend interaction during testing
  3. Teardown Hooks: Run at the very end of suites and flows. Helpful to clean up testing states

Hook Types

Hooks allow you to configure your test environment in three ways:
  1. Scripts: Python, JavaScript, TypeScript, or Bash scripts that run server-side
  2. cURL Requests: Backend API calls for simple HTTP requests
  3. App Launch Configuration: Configure how your mobile app launches (feature flags, environment settings) - mobile only

Scripts

Server-side scripts that execute in a secure sandbox environment. Choose from Python, JavaScript, TypeScript, or Bash depending on your needs.
If your hook calls a firewalled API, see Network allowlist for the IPs to allow.
Scripts run in a sandboxed environment and cannot use external libraries. Use only built-in/standard libraries (e.g., urllib instead of requests for Python, built-in fetch for JavaScript/TypeScript).
Because hook sandboxes are created from snapshots, pseudo-random generators can repeat values across runs. Avoid Math.random() in JavaScript/TypeScript and unseeded random in Python when generating emails, usernames, IDs, or other unique test data.
Common use cases:
  • Complex multi-step API operations
  • Data processing and transformation
  • Conditional logic based on API responses
  • Generating dynamic test data
  • Chaining multiple API calls with error handling

Generating Random Values

Use cryptographically secure randomness from the language standard library when generating unique test data. JavaScript / TypeScript:
Python:
If you must use Python’s random module, seed it from OS entropy at the top of your script:
Export a freshly generated value rather than only printing it, or the flow cannot be cached. See Hooks and Run Caching.

cURL Requests

Backend API calls that execute before (setup) or after (teardown) a flow runs. Best for simple, single HTTP requests. Common use cases:
  • Create test user accounts via your API
  • Reset database state between flows
  • Generate auth tokens or session data
  • Configure backend feature flags
  • Clean up test data after flows complete

App Launch Configuration (Mobile Only)

Configure values that are passed to your mobile app when it launches. These values are available to your app code as environment variables (iOS) or intent extras (Android).
App Launch Configuration is only available for mobile apps (iOS and Android). For web testing, use Scripts or cURL Requests to configure your test environment.
Common use cases:
  • Override feature flag values for specific test scenarios
  • Set test environment parameters (staging vs. production mode)
  • Configure API timeouts or retry behavior
  • Enable debug modes or verbose logging
  • Set experiment variants for A/B testing

Creating a Hook

  1. Navigate to Hooks in the sidebar
  2. Click Create Hook
  3. Enter a hook name (e.g., “Create Test User” or “Generate Auth Token”)
  4. Select hook type:
    • Python: For complex logic and data processing
    • JavaScript: For Node.js-based operations
    • TypeScript: For type-safe Node.js operations
    • Bash: For shell script operations
    • cURL Request: For simple HTTP API calls
    • App Launch Configuration: For mobile app settings (mobile only)
  5. Enter your script or configuration:

For Python:

For JavaScript:

For TypeScript:

For Bash:

For cURL Requests:

For App Launch Configuration:

  1. Click Create Hook
Any output from your hooks (print statements, console.log, echo) is passed to the agent as additional context. Use this to provide helpful information about what the hook did!

Testing Hooks

Before attaching hooks to flows, you can test them to verify they work correctly. Dashboard tests use your signed-in session. You do not need to create or paste an Autosana API key.
  1. Open the hook you want to test
  2. Click the Test Hook button
  3. The hook will execute with a 1-minute timeout
  4. View the output to verify success or debug issues
What to check:
  • Script executes without errors
  • API calls return expected responses
  • Environment variables are being read correctly
  • Exported values (if any) are formatted correctly
Always test hooks independently before attaching them to flows. This helps isolate issues and speeds up debugging.

Using Hooks

Setup & Teardown Hooks

Attaching Setup & Teardown Hooks
  1. Create a new suite or flow or click Edit on an existing one
  2. Expand the Advanced section
  3. Expand the Setup Hooks or Teardown Hooks section
  4. Click the Add a setup hook… or Add a teardown hook… button
  5. Select the hook you want to attach
Hooks attached to a suite are also shown read-only when you expand the suite on the Flows page, so you can see what runs before and after the suite without opening the editor.

Runtime Hooks

You can execute hooks as actions during flow execution by using the syntax ${hooks:Hook Name} in the flow instructions. Example:
When the agent encounters ${hooks:Hook Name}, it will:
  1. Look up the hook by name
  2. Execute the hook script
  3. Continue with the rest of the action
This is useful for:
  • Creating data mid-flow (e.g., “add 5 items to cart, then ${hooks:Create Dummy Discount Code}”)
  • Triggering backend events at specific points
  • Resetting state between actions
Runtime Hooks execute synchronously - the flow waits for the hook to complete before continuing.

Execution Order

  1. Setup Hooks execute (if configured)
  2. Flow runs on app start
  3. Agent runs actions and any Runtime Hooks (if configured)
  4. Flow run stops
  5. Teardown Hooks execute (if configured)
Steps 1 and 2 overlap when a setup hook is an App Launch Configuration — the app starts at that hook’s position.

Environment Variables in Hooks

For cURL Requests

Reference environment variables using ${env:VARIABLE_NAME} syntax:
Environment variables (in Settings → Environments):
  • API_URL = https://staging-api.example.com
  • TEST_EMAIL = test@staging.com
  • TEST_PASSWORD = SecurePass123
Executed command:

For Scripts (Python, JavaScript, TypeScript, Bash)

Environment variables are automatically injected into the script environment. Access them using your language’s standard method: Python:
JavaScript / TypeScript:
Bash:
Learn more about environment variables →
Click Insert Environment Variable when creating/editing a hook to browse and select from your available environment variables.

Sharing Data Between Hooks

Hooks can pass data to subsequent hooks in the same suite. This is useful for scenarios like:
  • Generating an auth token in a setup hook and using it in a runtime hook
  • Creating a test user and passing the user ID to a teardown hook for cleanup
  • Sharing credentials across multiple flows in a suite

How It Works

  1. In your hook, write values to /tmp/autosana.env in KEY=VALUE format
  2. Subsequent hooks can access these values as environment variables
  3. Values persist for all subsequent hooks in the suite (across all flows)

Key Naming Rules

When exporting values, keys must follow these rules:

Example: Passing a Token Between Hooks

Setup Hook (Python) - Creates token:
Runtime Hook (cURL) - Uses the token:
Teardown Hook (Python) - Cleans up:

Important Notes

  • Scripts can read and write exported values
  • cURL hooks can only read exported values (they cannot write to /tmp/autosana.env)
  • If multiple hooks export the same key, the latest value wins
  • Exported values are available to all subsequent hooks in the suite (across all flows)
  • Exported values are also available to subsequent flows in the suite via ${env:KEY}
  • The agent can also retrieve exported values directly by name using Get Variable
Hook exports are part of Autosana’s runtime variable system. For a complete overview of how variables work across hooks, flows, and suites, see Variables.

Hooks and Run Caching

Run Caching speeds up a flow by replaying what a previous passing run did, instead of working it out again. Whether that replay is possible depends on how your hook passes values to the flow. If your hook makes a new value every run — a phone number, a test account, a booking reference — Autosana has to learn that the value is meant to change. Until it does, those runs skip the cache and run at full speed. They still pass or fail correctly; they are just slower.

Export the Values Your Flow Uses

Do this. Write the value to /tmp/autosana.env under a name, so each run can be given its own:
Then reference it in your flow instructions as ${env:TEST_PHONE}, or have the agent fetch it with Get Variable. Not this. Printing it is the only record, and there is no name to look it up by:
Everything a setup hook prints is part of what identifies the run. If a hook prints a value that is different every time, every run looks different, so none of them can use the cache — even if the flow never uses that value.
Keep printing things. The run log is the quickest way to debug a hook, and once a value is exported, printing it as well costs nothing.

Which Values Autosana Treats as Changing

Autosana does not guess. It compares each exported value against what the same hook exported last time — same flow version, same environment — and treats it as changing only if it actually changed. It takes three passing runs to settle: the first records the value, the second notices it changed and rebuilds the cache, the third can use it. Failed runs do not count. This is tracked per flow version and environment, so editing the flow’s instructions starts the count over.

Flows That Are Never Cached

Two things turn caching off for a flow, whatever your hooks do:
  • Using the Run Hook action to run a hook partway through the flow
  • Using the Set Variable action
Setup and teardown hooks do not affect this — only hooks the agent runs as a step.

Hook Examples

cURL Examples

Create User Account

Reset Database

Generate Auth Token

Delete Test Data (Teardown)

Script Examples

Python: Create User and Export Credentials

JavaScript: Fetch and Process Data

Bash: Quick API Check

App Launch Configuration (Mobile Only)

How It Works

App Launch Configuration hooks pass values to your mobile app when it launches. These values are set at app startup and are available throughout your test. This feature is only available for iOS and Android apps.

When It Runs

Setup hooks all run before the app starts — unless one of them is a launch configuration, in which case the app starts at that hook’s position. Put a hook that mints a token or seeds a user above it; hooks below it run against the already-running app. More than one. Each applies at its own position, restarting the app if it is already running. Nested objects merge — setting featureFlags.darkMode keeps the other featureFlags keys — while lists and single values are replaced. A restart keeps device data, not screen state. The app is not reinstalled or reset, so keychain, saved sessions and local databases survive, but the process restarts and the flow begins at your app’s launch screen. In a suite, flows share one session — opened by the suite’s own launch configuration if it declares one. A flow’s launch configuration restarts the app with its values merged over the suite’s; a flow with none keeps what the session already has. With Run flows in parallel, each flow gets its own session and applies the suite’s configuration from scratch.

Dynamic Values (Environment & Build Variables)

Launch configuration JSON supports ${env:VARIABLE_NAME} placeholders, resolved when the hook runs — so a placeholder sees values exported by setup hooks above it, as well as your environment variables and build variables passed via CI (the variables input on the GitHub Action / upload API). This lets you drive launch configuration dynamically — for example, passing an Expo Updates channel from CI:
The resolved value is delivered to your app as an iOS environment variable / Android intent extra (see below). Your app is responsible for acting on it — e.g. an Expo app must read the value and call Updates.setUpdateURLAndRequestHeadersOverride(...) followed by Updates.reloadAsync() to switch channels at runtime. If a referenced variable is not set — or is set to an empty or whitespace-only value — the run stops with an error naming it, rather than starting your app with a literal ${env:...} string.

Accessing Values in Your App

iOS (Swift):
Android (Kotlin):
React Native:
On iOS, launch configuration values are set as environment variables and accessed via ProcessInfo.processInfo.environment. On Android, they are passed as intent extras and accessed via intent.extras. See the platform-specific examples above for details.

Launch Configuration Examples

Override Feature Flags

Set Environment and Timeouts

A/B Testing Configuration

Debug Mode Settings

When to Use Each Hook Type

Setup Hooks & Agent Context

Pro Tip: When a hook produces output (via print statements, console.log, or echo), the agent automatically receives this data as additional context and can use it during flow execution. Example setup hook:
The agent receives this output and can reference it if needed during the flow execution.
A setup hook’s output also feeds into the run cache, so printing a value that changes every run — a timestamp, a fresh ID — costs you the cache. See Hooks and Run Caching.

Timeouts

Hooks have different timeout limits depending on the context: If a hook exceeds its timeout, it will be terminated and marked as failed.
Keep hooks focused and fast. If you have long-running operations, consider breaking them into multiple hooks or optimizing your API calls.

Best Practices

Use Descriptive NamesName hooks after what they do: “Create Premium Test User” instead of “Hook 1”
Store Secrets in Environment VariablesNever hardcode API keys or passwords in hooks. Use environment variables like ${env:API_KEY}.
Test Hooks IndependentlyUse the Test button to verify your hooks work correctly before attaching them to flows.
Use Teardown Hooks for CleanupAlways clean up test data created by setup hooks to avoid polluting your backend. For concurrent runs, follow Making Suites, Parallelizable, Isolated, and Repeatable so one session cannot change or delete another session’s data.
Keep Hooks SimpleEach hook should do one thing. Create separate hooks for different setup tasks.
Use Scripts for Complex LogicWhen you need conditionals, loops, error handling, or data processing, use Python/JavaScript instead of complex cURL commands.
Export Only What You NeedWhen sharing data between hooks, only export the values that subsequent hooks actually need.
Add Helpful Print StatementsOutput from your hooks is passed to the agent. Add print statements to provide context about what happened.

Hooks vs Suite Auth Instructions

Use hooks when: You need to configure backend state, create test data, or call APIs Use suite auth instructions when: You need to start the suite from a specific state (e.g., logged in with a certain test account)

Troubleshooting

Script Issues

Script times out
  • Hooks have a 5-minute timeout during flow execution (1 minute when testing)
  • Break long operations into multiple hooks
  • Check for infinite loops or slow API endpoints
Environment variable not found
  • Verify the variable exists in Settings → Environments
  • Check spelling and case (variable names are case-sensitive)
  • For scripts, use the correct access method for your language
Random values are the same every run
  • Hook sandboxes are created from snapshots, so pseudo-random generators may repeat their seed across runs
  • In JavaScript/TypeScript, use Node’s built-in crypto module (crypto.randomInt, crypto.randomUUID) instead of Math.random()
  • In Python, prefer secrets or uuid; if you must use random, call random.seed(os.urandom(32)) before generating values
Exported values not available in next hook
  • Verify you wrote to /tmp/autosana.env (exact path)
  • Check key naming rules (alphanumeric + underscore, can’t start with number)
  • Ensure the format is KEY=VALUE with one per line

cURL Request Issues

Hook fails to execute
  • Verify the curl command works in your terminal first
  • Check that environment variables are defined
  • Ensure API endpoints are accessible from Autosana’s infrastructure
Environment variables not replacing
  • Syntax must be ${env:VARIABLE_NAME} (not {{VARIABLE_NAME}} or $VARIABLE_NAME)
  • Variable names are case-sensitive
  • Variables must exist in Settings → Environments

App Launch Configuration Issues

Configuration not appearing in app
  • Verify JSON is valid (use a JSON validator)
  • Check you’re accessing values correctly for your platform (ProcessInfo for iOS, intent.extras for Android)
  • Ensure the hook is attached as a setup hook (launch configuration doesn’t work in teardown)
Values have wrong type
  • On iOS, all values become strings (including numbers and booleans)
  • On Android, primitives keep their types (int, float, boolean, string)
  • Nested objects are JSON-serialized as strings on both platforms
  • Use the examples in this guide to parse nested structures correctly

Data Sharing Issues

Hook can’t read value from previous hook
  • Ensure the previous hook successfully wrote to /tmp/autosana.env
  • Check that the previous hook completed without errors
  • Verify the key name matches exactly (case-sensitive)
Invalid key name warning
  • Keys must contain only letters, numbers, and underscores
  • Keys cannot start with a number
  • Examples: AUTH_TOKEN ✓, 123_KEY ✗, API-KEY

Managing Hooks via API

Hooks can be created, updated, and deleted programmatically via the Hooks API. Useful for syncing hook definitions from your repo, bulk-importing from another system, or wiring up custom tooling. Hooks can also live as script files in your repository and be referenced from code-managed flows — see Hooks as files.

Next Steps