Date: 2026-05-11
Time: 15:17
The FTL2 automation context manager provides a Pythonic, async interface for writing automation scripts. Using async with automation() as ftl:, users access modules as attributes (ftl.file(...), ftl.copy(...)), manage inventory and secrets, run in check mode, handle errors, and control output — all without boilerplate. The interface is designed to be AI-friendly and runs FTL native modules in-process at 250x the speed of subprocess-based execution.
async with automation() as ftl: is the entry point for all automation scriptsawait ftl.module_name(param=value) — no string lookups or dictionariesftl.results accumulates all module execution results; each has .module, .success, and other fieldsautomation(modules=["file", "copy"]) limits which modules can be called; unauthorized access raises AttributeErrorautomation(inventory=...). Access hosts with ftl.hosts["group"], ftl.hosts.all, ftl.hosts.groupsrunon() method: Execute modules on specific hosts or groups — await ftl.runon("webservers", "file", path=..., state=...)automation(secrets=["KEY1", "KEY2"]) loads from environment variables. Values are never exposed in print()/repr(). Access via ftl.secrets["KEY"] or .get("KEY", default)automation(check_mode=True) previews changes without applying themverbose=True (with timing), quiet=True (no output), on_event=callback (structured events), and normal (default)ftl.failed (bool), ftl.errors (list of error objects with .host, .module, .error), ftl.error_messages (string list)automation(fail_fast=True) raises AutomationError on first failure instead of accumulatingftl.amazon.aws.ec2_instance(...)) via NamespaceProxy chaining — enables Ansible collection modules alongside native FTL modulesBasic script structure:
from ftl2 import automation
async with automation() as ftl:
await ftl.file(path="/tmp/test", state="directory")
await ftl.copy(src="config.yml", dest="/etc/app/config.yml")
await ftl.command(cmd="systemctl restart myapp")
Running examples: uv run python examplephase1basic.py
Inventory from YAML: automation(inventory="hosts.yml")
Inventory from dict: automation(inventory={"group": {"hosts": {"host01": {"ansible_host": "1.2.3.4"}}}})
Host access API:
ftl.hosts["web01"] — specific hostftl.hosts["webservers"] — all hosts in groupftl.hosts.all — all hostsftl.hosts.groups — group namesftl.hosts.keys() — all host nameslen(ftl.hosts) / "web01" in ftl.hostsSecrets: automation(secrets=["AWSACCESSKEYID", "APITOKEN"]) then ftl.secrets["AWSACCESSKEYID"], .get("KEY", "default"), .loadedkeys()
Check mode: automation(check_mode=True)
Fail fast with exception handling:
from ftl2.automation import AutomationError
try:
async with automation(fail_fast=True) as ftl:
await ftl.file(path="/nonexistent", state="touch")
except AutomationError as e:
print(f"Module: {e.result.module}")
FQCN: await ftl.amazon.aws.ec2instance(name="my-instance", instancetype="t3.micro")
automation(inventory=...) parameter connects directly to FTL2's YAML inventory system and host configurationftl.module_name() is the user-facing surface of FTL2's module execution engine; FQCN modules bridge to Ansible collectionsftl.secrets provides environment-variable-based secrets; relates to the broader Vault integration topicftl.failed, ftl.errors, and fail_fast are the primary error handling mechanisms, connecting to FTL2's result trackingon_event) connect to FTL2's event streaming and audit/replay capabilitiesautomation() context manager accepts: modules, verbose, quiet, checkmode, failfast, inventory, secrets, on_eventmodules=[...] causes AttributeError (not a runtime module error) when accessing disallowed modulesftl.secrets never exposes values in print/repr — this is a security featureKeyError: not requested; a requested but unset secret raises KeyError: not set in environmentftl.secrets.keys() returns all *requested* names; ftl.secrets.loaded_keys() returns only those actually set in the environment[CHECK MODE]fail_fast=True raises AutomationError which has .result.module for identifying the failing moduleNamespaceProxy objects: ftl.amazon -> NamespaceProxy("amazon") -> .aws -> NamespaceProxy("amazon.aws") -> .ec2instance(...) executes "amazon.aws.ec2instance"checkmode=True first, inspect ftl.results, then run with checkmode=FalseNORMAL, VERBOSE, QUIET, EVENTS — accessible via ftl.output_modeftl.results is a list accumulated across all module calls in a context; check with len(ftl.results) or iterate