Anvil is a declarative AWS execution engine for running Python tasks across large account and region fleets. Describe the work in YAML, keep task logic in plain Python modules, and let the engine handle authentication, role assumption, dependency ordering, bounded concurrency, and structured results so repeatable AWS work can run faster without turning orchestration into custom scripts.
For more, see the documentation.
Anvil is built for teams that need repeatable AWS workflows, such as inventory, validation, enforcement, cleanup, and reporting, to run consistently across organizations, accounts, and regions.
- Declarative orchestration
- Define execution in reusable YAML instead of one-off scripts.
- Configure organizations, account lists, regions, tasks, task dependencies, dry runs, fail-fast behavior, and concurrency in one place.
- Multi-account and multi-organization by default
- Discover active accounts and enabled regions, support include/exclude filtering
- Parallel execution and caching
- Control concurrency at the target, account, and region levels. See Caching and reuse.
- Shared discovery and session reuse
- Validate the organization, discover accounts, and check enabled regions, only once, before execution.
- Task isolation
- Write tasks as simple Python files with a
run(...)function.
- Write tasks as simple Python files with a
- Built-in and custom tasks
- Use stock tasks for common AWS operations.
- Add project-local tasks for team-specific work.
- Extend the task set without changing the execution engine.
- Structured output and safer operations
- Record structured results at task, account, target, and engine levels.
Tip
It is recommended to use the foundry-anvil-template.
The template exposes project-local tasks and processors without forking Anvil.
If you do not need/want the full Anvil framework and only want a simple starting point for small AWS Organization tasks, see: templates/aws_multi_account_template.py
- When using the uv tool, there are several ways to run and install dependencies. Here are only a couple examples:
- uv sync:
- Sync the project's dependencies with the environment: uv sync
- Activate the virtual environment: .venv\Scripts\activate
- uv run:
- Run a command in the project environment.:
uv run example.py <args>- uv run anvil run --config-file ./yaml/orgs.yaml
- Note that if you use uv run in a project, i.e. a directory with a pyproject.toml, it will install the current project before running the script.
- Run a command in the project environment.:
There are multiple global commands:
anvil graph # Show the resolved task dependency graph
anvil results # Query JSONL results and rerun failures
anvil list # List available tasks and processors
anvil validate # Validate tasks, processors, and AWS authentication
anvil run # Execute YAML-defined workflowsRun a simple YAML file:
This executes the configured targets and tasks, then writes structured results under ./results.
anvil run --config-file ./yaml/orgs.yaml# orgs.yaml example
schema_version: 1
organizations:
- name: smoke
profile: root
tasks:
- name: noop
dry_run: trueFor delegated-administrator patterns, keep the base session on the
delegated-admin profile. Anvil uses that base session directly for the
delegated-admin account if it appears in Organizations discovery, and assumes
role_name in every other selected account, including the management/payer
account.
schema_version: 1
organizations:
- name: security
profile: delegated-admin-security
role_name: SecurityAuditRole
regions:
- us-east-1
tasks:
- name: noopanvil results queries completed run output without rerunning AWS work. Use it
to filter historical JSONL results by target, account, region, task, or status,
emit JSON/JSONL for automation, rerun failed work, or run a processor against a
completed results directory. When a run has failures, Anvil prints ready-to-use
anvil results commands that point at the affected run's results.jsonl file
so you can inspect or rerun the failed accounts.
See more at Common result queries and Rerun failures.
Use anvil validate before a run to perform one or more checks without running
tasks:
anvil validate --tasks --processors --auth --config-file ./yaml/orgs.yaml--tasks and --processors validate discovery and callable signatures.
--auth validates AWS access for the configured targets.
See more at Task validation.
Processors run after a target finishes and turn Anvil results into reports or
integration artifacts. Use them for formats that should stay outside task logic,
such as HTML, SARIF, Markdown, JSON summaries, tickets, or notification payloads.
Target post_run processor output is written under the run's reports
directory, so output: smoke.html becomes <run_dir>/reports/smoke.html.
Use html_report when you want a self-contained, human-readable report for a
completed target:
schema_version: 1
organizations:
- name: smoke
profile: root
regions:
- us-east-1
tasks:
- name: noop
post_run:
- processor: html_report
output: smoke.html
run_on_failure: trueUse sarif_report when detect_ tasks return sarif_findings and you want a
SARIF 2.1.0 report for code-scanning or security tooling:
schema_version: 1
organizations:
- name: lambda-runtime-audit
profile: root
regions:
- us-*
tasks:
- name: detect_deprecated_lambda_runtimes
metadata:
runtimes:
- python3.8
- nodejs16.x
post_run:
- processor: sarif_report
output: lambda-runtimes.sarif
run_on_failure: trueSee more at HTML result reports.
Run a more detailed YAML:
This shows multi-region execution, concurrency, account filtering, task dependencies, fail-fast behavior, dry-run mode, and task metadata.
anvil run --config-file ./yaml/advanced.yaml# advanced.yaml example
schema_version: 1
max_parallel_targets: 2
organizations:
- name: place
profile: place-root
# Organizations support explicit regions, all, glob selectors, and mixed
# glob plus explicit selectors.
regions:
- us-east-1
- us-west-2
role_name: OrganizationAccountAccessRole
max_workers: 5
max_parallel_regions: 2
fail_fast: false
dry_run: true
include:
- "111111111111"
- "222222222222"
tasks:
- name: discover_iam_users
- name: backup_iam_users
depends_on:
- discover_iam_users
- name: remove_iam_user
depends_on:
- discover_iam_users
- backup_iam_users
metadata:
user_name: testTo measure concurrency behavior, the engine was tested across 3 organizations with a combined 260 accounts using the count_vpc task. The comparison below shows the same kind of work moving from sequential execution to organization-level parallelism and then to account-level parallelism.
The fastest measured run in this benchmark completed 260 accounts in about 1m 35s for 1 region, compared with a 3h 15m manual sequential estimate at 45 seconds per account. With 2 regions, the parallel account run completed in about 2m 48s.

