Skip to main content
This is the complete file reference for code-managed flows: where files live under .autosana/, and every recognized key in flow files, suite manifests, and hook scripts.

Repository layout

Everything Autosana manages lives under a single .autosana/ folder — at your repository root by default, or under a subdirectory you point Autosana at (see Monorepos). Flows are *.flow.yaml files, a suite is a folder containing a _suite.yaml manifest, and hooks are script files under a hooks/ directory.
The sync reads autosana.md at the root of .autosana/, files that end in .flow.yaml, are named exactly _suite.yaml, or scripts directly inside a hooks/ folder with a supported extension. Every other file under .autosana/ is ignored, including config.yaml, which only the CLI reads.

Flow files

A flow file ends in .flow.yaml. The only required keys are name and instructions, where instructions is either a single multiline prompt or a YAML list of steps. As a multiline prompt:
Or as a list of steps:
The recognized top-level keys are:
Any top-level key that isn’t in the table above is a hard error. A typo like instructoins: fails validation with a “Did you mean ‘instructions’?” suggestion on the Autosana - Code-Managed Flows check, so mechanical mistakes are caught before they merge.
Let the path derive your key. If you omit key, the key comes from the file path (.autosana/smoke/checkout.flow.yaml becomes smoke/checkout). Set an explicit key when you want the key to stay stable even if you move or rename the file — see Deleting and renaming.

Exporting caching settings

CLI 0.9.15 and later preserve each caching mode when exporting flows. Older CLI versions export an explicit Standard limit as caching Off, because their boolean format cannot preserve that limit. Upgrade the CLI before exporting to retain the exact setting.

Referencing variables

Define flow overrides in *.flow.yaml and suite defaults in _suite.yaml with variables:
Flow variables override suite defaults. Hooks read them as environment variables (see Variables). Values must be literal strings; quote numbers and booleans (CODE: "00123", ENABLED: "false"). Names use letters, digits, and underscores, and cannot start with a digit. A supplied map replaces that flow’s or suite’s overrides on sync. Omit variables to keep existing values, or use variables: {} to clear them. Keep secrets in Environments, since YAML values are committed to your repository.

Referencing hooks

Attach hooks to a flow with setup_hooks and teardown_hooks, each an ordered list of hook slugs:
A slug resolves against every active hook in your organization — not just repo files — so you can also reference hooks authored in the dashboard, including cURL hooks (which can only be created in the dashboard). Find a dashboard hook’s slug on the hook in the Hooks page. See Hooks as files for how a repo file’s slug is derived. Built-in hooks don’t need to be added from the Hook Library first. Reference Lease email address as lease-email-address and Lease phone number as lease-phone-number, and the sync adds the hook to your organization if it isn’t there yet. If one of your own hooks already uses that slug, your hook is used instead. Duplicate slugs within one list are rejected. The same slug may appear in both setup_hooks and teardown_hooks — that’s legal. To reference a hook by name inside your instructions at run time, use ${hooks:Hook Name} (by display name); see Hooks. When the list mixes scripts with a launch-args (.json) hook, the app starts where that hook sits — see when launch configuration runs.

Labels

Attach labels to a flow or suite with labels, a list of label names:
Names match case-insensitively against your org’s labels; unknown names are auto-created. Omitting labels leaves the flow/suite’s existing labels untouched — an explicit labels: [] clears them. Labeled flows and suites dispatch via run-by-label as usual.

Suites

A suite is a folder containing a _suite.yaml manifest. The suite’s key is its folder path (a smoke/ folder gives the suite key smoke). The only required key is name:
The recognized keys are: The Lease email address and Lease phone number built-in hooks may be listed in a suite’s setup_hooks. Unlike ordinary suite setup scripts, a lease hook is inherited by every member flow and creates a separate inbox or number for each flow run. The suite’s setup_flow, when configured, receives its own lease too. This also applies when parallelize_flows: true. These built-ins are setup-only and are rejected in teardown_hooks. Reference them as lease-email-address and lease-phone-number; you don’t need to add them from the Hook Library first. References in flows and setup_flow resolve sibling-first: a flow directly in the suite’s own folder wins, otherwise the reference is matched against every flow in the repo. Flows in a subfolder are not default members — list them explicitly (or give the subfolder its own _suite.yaml). Flow keys and suite keys must each be unique across the whole repo. An unknown reference, or the same flow listed twice, is a validation error.
The _suite.yaml file must live inside a folder — it cannot sit at the .autosana/ root, because a suite is a folder. Membership is defined by the suite (its flows list or its folder), never declared inside the flow files themselves.
YAML parses bare no, yes, on, and off as booleans (the “Norway problem”). Because setup_flow and name must be strings, setup_flow: no fails validation — quote the value if you really mean the string "no".
For how variables and setup flows propagate across a suite’s flows, see Suites.

Hooks as files

Hooks live as script files inside a hooks/ folder — either .autosana/hooks/ or <suite>/hooks/. The file extension determines the hook type, and the filename becomes the hook’s slug. The slug is derived from the filename with its final extension removed: lowercased, with runs of non-alphanumeric characters collapsed to -. So Seed DB.sh becomes slug seed-db, and reset.env.json becomes reset-env. This slug is what you reference in setup_hooks / teardown_hooks. The display name is the humanized filename (reset-test-env.sh shows as “Reset Test Env”).
Hook slugs are unique across your whole organization — the folder a hook lives in has no scoping effect. Two files that slugify the same (seed-db.py and seed_db.sh), or a slug that collides with a different repository’s hook, fail the sync with a rename error. A slug that matches an existing dashboard-authored hook is not an error — that hook is adopted (its run history preserved), the same way flows adopt by name; see Migrating existing flows. Rename the file if that isn’t what you intend.
The file content is the hook script, stored verbatim. Empty or whitespace-only files are rejected. A .json launch-args hook must parse as valid JSON, and a filename with no letters or digits (so it produces an empty slug) is rejected.
Script hooks (.py, .js, .ts, .sh) read environment variables natively — os.environ.get(...) in Python, process.env in JavaScript/TypeScript, $VAR in Bash. Launch-args (.json) hooks — and dashboard-authored cURL hooks — use the ${env:KEY} token instead, since they aren’t executed scripts. cURL hooks have no file form; reference an existing dashboard cURL hook by slug, or use a .sh hook that runs curl. See Hooks for the full hook model.

Config file

config.yaml at the root of .autosana/ sets defaults for autosana run. It is not a test: the sync never reads it and the CLI never uploads it. How the defaults apply is on Running from the CLI.
Any other key, an unknown platform, or a mobile entry without bundle_id (or a web entry without app_id) is an error. autosana flows validate reports it, and autosana run refuses to start until it is fixed.

Monorepos

By default Autosana looks for .autosana/ at your repository root. If your definitions live in a subdirectory — common in a monorepo — point Autosana at that folder with the repo’s Root directory setting.
  1. Go to Settings > Integrations > GitHub
  2. On the connected repo, set Root directory to the folder that contains .autosana/ (for example, services/mobile for services/mobile/.autosana/)
  3. Leave it blank to use the repository root
Flow and suite keys stay relative to .autosana/, so moving your definitions into a subdirectory doesn’t change any keys — a flow at services/mobile/.autosana/login.flow.yaml still has the key login. The GitHub links on each row point at the full path in your repo.
Saving a new Root directory doesn’t re-sync on its own. Click Resync on the repository card, or push to the default branch to sync from the new location. Once .autosana/ has been detected, the nightly resync also checks it for drift.

Next Steps