Token-optimized Ansible output for AI coding agents
Project description
ansible-agent-callback
Token-optimized Ansible stdout callback plugin for AI coding agents. Reduces output by 70-90% compared to the default callback.
Compression is asymmetric on purpose:
- Success path: aggressive — clean runs collapse to a single
RECAPline; ok and skipped tasks produce zero output. - Failure path: readable — full stack traces stay intact via
msg>/stderr>continuation lines, plusrc, and full per-task detail captured to a companion file on demand. Still smaller than default, but optimized for diagnosis over byte count.
Verified on a mixed-shape fixture (12 ok, 3 changed, 3 skipped, 2 ignored
failures, 1 loop) — see bench/ and run make bench to
reproduce:
| Metric | default | agent | Reduction |
|---|---|---|---|
| bytes | 3,174 | 499 | 84.3% |
| lines | 90 | 15 | 83.3% |
| words | 286 | 79 | 72.4% |
Clean runs (zero changes, zero failures) collapse to a single line regardless of task count, so the reduction approaches the default's total volume the larger your playbook.
Getting Started
Install the plugin and configure your AI coding agents in one command:
uvx ansible-agent-callback install
This will:
- Copy the callback plugin to
~/.ansible/plugins/callback/ - Detect which AI coding agents you have installed
- Let you pick which ones to configure (detected agents are pre-selected)
To skip the interactive selector and configure everything automatically:
uvx ansible-agent-callback install --all
That's it. Your agents will now use the token-optimized output when running Ansible.
Output Format
Only changed, failed, and unreachable results are shown. Ok and skipped tasks produce zero output. A fully successful playbook run outputs just the RECAP line.
PLAY | Configure webservers
TASK | Configure nginx
changed | web01 | diff: +worker_processes 4;
failed | db01 | msg: Permission denied | rc: 1
RECAP | web01: ok=3 changed=1 | db01: ok=1 failed=1
Diff summaries
For changed tasks with diff data, the plugin shows the first
non-comment change line. Comment-only changes (# or ; prefix)
are skipped so the agent isn't misled by -# old comment while the
real edit is buried below. Multi-line diffs append (+N -M) totals
to signal there's more context:
changed | web01 | diff: -workers 2
changed | web02 | diff: +listen 443 (+3 -1)
Failures with multi-line output
Stack traces stay readable. The lead failed line carries a
single-line summary plus rc; remaining content emits as
continuation lines prefixed with msg> or stderr> :
failed | db01 | stderr: Traceback (most recent call last): | rc: 1
stderr> File "/opt/app/run.py", line 5, in <module>
stderr> do_thing()
stderr> RuntimeError: oops
The prefix is unambiguous (real output never produces it) and
grep-friendly: ^failed finds every failure, and an agent reads
forward until the next non-continuation line for the full block.
Full Output When Things Fail
The compressed format keeps successful runs token-cheap, but agents
sometimes need the full picture to diagnose a failure. Set
ANSIBLE_LOG_PATH and the plugin captures the complete, untrimmed
result of every failed or unreachable task:
ANSIBLE_LOG_PATH=/tmp/ansible.log ansible-playbook site.yml
Full detail goes to a companion file beside the log,
<ANSIBLE_LOG_PATH>.details.jsonl, and a LOG line after the RECAP
points at it:
failed | db01 | msg: Permission denied | rc: 1
RECAP | db01: ok=1 failed=1
LOG | /tmp/ansible.log.details.jsonl
Each line is one JSON object with the host, task, status, and the full
result (rc, cmd, stderr, stdout, msg, diff, ...), everything
an agent needs without re-running the play. The module invocation and
internal keys are dropped, and no_log results stay censored by Ansible.
The file is written only when something fails and cleared at the start of
each run, so a clean run leaves no file and stdout stays token-cheap.
Why a companion file and not ANSIBLE_LOG_PATH itself? That log is fed by
Ansible's Display, which records whatever the active stdout callback
prints. With this callback that means the same compressed lines, not the
full result, so the untrimmed detail needs its own file.
When a run fails and ANSIBLE_LOG_PATH is not set, the plugin appends a
single HINT after the RECAP so an agent can opt in:
RECAP | db01: ok=1 failed=1
HINT | set ANSIBLE_LOG_PATH=<path> and re-run to capture full failure detail
Clean runs stay clean: no hint, no file, no extra lines.
Commands
ansible-agent-callback install # Install plugin + configure agents
ansible-agent-callback install --all # Auto-configure detected agents
ansible-agent-callback install --agents claude-code,codex-cli
ansible-agent-callback install --plugin-only # Just the plugin, no agent config
ansible-agent-callback update # Update plugin to latest version
ansible-agent-callback uninstall # Remove plugin + agent configs
ansible-agent-callback env # Print export for other agents
Supported Agents
| Agent | Config |
|---|---|
| Claude Code | ~/.claude/settings.json |
| Codex CLI | ~/.codex/config.toml |
| Gemini CLI | ~/.gemini/.env |
| Shell profile | ~/.zshrc or ~/.bashrc |
| Ansible global | ~/.ansible.cfg |
Development
make dev # Install in editable mode
make test # Run tests
make bench # Compare default vs agent callback output volume
make build # Build package
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ansible_agent_callback-0.3.2.tar.gz.
File metadata
- Download URL: ansible_agent_callback-0.3.2.tar.gz
- Upload date:
- Size: 23.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8db13259b6c8403df90554fa49602ed429ca79b0fc1f81903cd65440a7259a17
|
|
| MD5 |
85c5844964949ded6c3ca9ece0df14c2
|
|
| BLAKE2b-256 |
4104e513c5ffcc25cdc6ef1e5a867154d852c287b35e8f64cb8b768513c63562
|
File details
Details for the file ansible_agent_callback-0.3.2-py3-none-any.whl.
File metadata
- Download URL: ansible_agent_callback-0.3.2-py3-none-any.whl
- Upload date:
- Size: 15.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8262b2974d1f3ba9449fd2ce31f0b8d18e3a790e83062f571bd5ef7b8e1f5458
|
|
| MD5 |
943949f4368c75219248b956756bf35d
|
|
| BLAKE2b-256 |
3a544fe343985b214090d7798394508878d72bb13c226b7c9d593ed356f2cc6d
|