Container Host AIops
Disclaimer: Community-maintained open-source project. Not affiliated with, endorsed by, or sponsored by Docker, Inc., Portainer.io, or any container-platform vendor. "Docker", "Portainer" and all product/trademark names belong to their respective owners. MIT licensed.
Governed AI-ops for non-orchestrator container hosts — the Docker Engine API (over a local unix socket or a TCP host), Portainer (its management API, which also proxies Docker), and Podman (a rootful/rootless service socket speaking the Docker-compatible API plus libpod-native endpoints) — with a built-in governance harness: unified audit log, policy engine, token/runaway budget guard, undo-token recording, and graduated-autonomy risk tiers. Multi-platform by construction: a registry keyed by platform means a per-target platform field (docker / portainer / podman) selects the API shape, and another host family could be added later without touching the ops/CLI/MCP layers. Exercised against a live Docker Engine 27.5.1 daemon (doctor, overview, the three flagship analyses, and a governed stop_container with audit + undo recorded); the Portainer and Podman API paths are covered by the mock suite only.
What it does
Three flagship signature analyses, plus the guarded reads and writes around them:
- Restart-loop RCA — inspect containers for restart count + exit code, flag the crash-looping ones (restartCount over threshold, or restarting/dead, or a non-zero exit), and map each to a likely cause + action from the exit code (137 OOM/SIGKILL, 143 SIGTERM, 139 segfault, 127 bad entrypoint, …), with a tail of logs. Every ranking carries its numbers, not a black-box verdict.
- Resource-pressure analysis — a one-shot CPU%/memory% sample per running container vs its configured limits, flagging each "near" (≥ 80% of a threshold) or "over", with a recommendation (raise a limit, set a missing memory limit, scale out).
- Image & volume bloat — dangling images + dangling volumes + build cache from
system/df, totalled into prune candidates with reclaimable bytes.
What works
- CLI (
container-host-aiops ...):init,overview,container,image,volume,network,system,stack,pod,analyze,manage,secret,doctor,mcp. - MCP server (
container-host-aiops mcporcontainer-host-aiops-mcp): 38 tools (29 read, 9 write), every one wrapped with the bundled@governed_toolharness. - Connection layer: Docker over a unix socket (
httpx.HTTPTransport(uds=...)) or a TCP host; Portainer over HTTPS with anX-API-Keytoken that also proxies the Docker API of a managed endpoint; Podman over its rootful/rootless service socket (autodetected:$XDG_RUNTIME_DIR/podman/podman.sockfirst, then/run/podman/podman.sock) speaking the Docker-compat layer (paths reused wholesale) plus libpod-native endpoints. A local Docker/Podman socket needs no secret — the socket's file permissions are the boundary. - Encrypted credentials: the Portainer API token lives in an encrypted store
~/.container-host-aiops/secrets.enc(Fernet + scrypt) — never plaintext on disk. Unlock with a master password fromCONTAINER_HOST_AIOPS_MASTER_PASSWORD(MCP/CI) or an interactive prompt (CLI). - Reversibility: mutating writes fetch the real before-state first and record a faithful inverse (
stop↔start;update_containerrestores prior CPU/memory limits). Irreversible ops (remove_container,prune_images,prune_volumes,recreate_stack) capture the before-state for audit but declare no undo. - Safety: every state-changing CLI op supports
--dry-runand requires double confirmation; every write MCP tool takes adry_runpreview — and prune previews list what would be removed + reclaimable bytes before doing it.
Security: read-only mode
This tool is meant to be handed to an AI agent, so its safety story is enforced by the server rather than requested in a prompt:
export CONTAINER_HOST_READ_ONLY=1
With that set, the 9 write tools are never registered. An MCP client lists 29 tools instead of 38 — the writes are not hidden, not gated behind a flag, and not merely refused when called. They are absent from the session. A model cannot invoke a tool it was never offered, and cannot be argued into one.
That distinction is the whole point. A tool that exists but refuses still invites retry loops and "I'll describe the call instead" behaviour from smaller models, and it leaves a reviewer trusting a promise. An absent tool is a fact you can check: connect, list the tools, and see that the writes are not there.
Enforcement is two layers deep, so the switch cannot be sidestepped by changing entry point:
| Layer | What it does | Covers |
|---|---|---|
@governed_tool harness |
refuses every non-read operation outright | MCP, CLI, and in-process callers |
| MCP registration | write tools are removed from list_tools() |
anything speaking MCP |
Read operations are unaffected, and every call is still audited to
~/.container-host-aiops/audit.db.
The read/write split is derived from each tool's declared
risk_level, and a test asserts that this never disagrees with the[READ]/[WRITE]tag in the tool's own documentation — so a write can't quietly present itself as a read.
Running a smaller / local model? See agent-guardrails.md — it lists the guardrails this tool now enforces for you (so you don't spend prompt budget restating them) and gives a ready-made system prompt for what's left.
Capability matrix (38 MCP tools)
| Domain | Tools | Count | R/W |
|---|---|---|---|
| Overview | overview |
1 | read |
| Containers | list_containers, inspect_container, container_logs, container_stats, container_top, container_restart_summary |
6 | read |
| Images | list_images, inspect_image, dangling_images, image_disk_usage |
4 | read |
| Volumes | list_volumes, inspect_volume, dangling_volumes |
3 | read |
| Networks | list_networks, inspect_network |
2 | read |
| System | system_info, system_version, system_df, system_events |
4 | read |
| Stacks | list_endpoints, list_stacks, stack_detail (Portainer), list_compose_stacks (docker+podman) |
4 | read |
| Pods (Podman) | list_pods |
1 | read |
| Analyses (flagship) | restart_loop_rca, resource_pressure_analysis, image_and_volume_bloat |
3 | read |
| Writes | remove_container, prune_images, prune_volumes, recreate_stack |
4 | write (high) |
restart_container, stop_container, start_container, update_container |
4 | write (medium) |
The three analyses accept injected data for offline analysis, or pull live from a configured target. list_endpoints/list_stacks/stack_detail require a portainer target; list_compose_stacks (Compose project rollup by the com.docker.compose.project label, with per-stack health) works on docker or podman; list_pods requires a podman target (Docker/Portainer have no pod concept).
Platform support matrix
| Capability | docker | portainer | podman |
|---|---|---|---|
| Container / image / volume / network / system reads | ✅ | ✅ (proxied) | ✅ (compat) |
| Flagship analyses (restart-loop RCA, resource pressure, bloat) | ✅ | ✅ | ✅ (compat) |
| Lifecycle + prune writes (stop/start/restart/remove/update/prune) | ✅ | ✅ | ✅ (compat) |
Compose-stack rollup (list_compose_stacks) |
✅ | ✅ (proxied) | ✅ |
Portainer endpoints / stacks / recreate_stack |
— | ✅ | — |
Podman pods (list_pods, libpod) |
— | — | ✅ |
Quick start
uv tool install container-host-aiops # or: pipx install container-host-aiops
container-host-aiops init # wizard: add a Docker/Podman socket or Portainer target
container-host-aiops doctor # verify config, secrets, connectivity
container-host-aiops overview # one-shot host health
container-host-aiops analyze restart-loop # crash-looping containers + cause/action
container-host-aiops container list --running # running containers
Run as an MCP server (stdio):
export CONTAINER_HOST_AIOPS_MASTER_PASSWORD=... # only needed for Portainer targets
container-host-aiops-mcp
Governance
Every MCP tool passes through the bundled @governed_tool harness:
- Audit — every call (params, result, status, duration, risk tier, approver, rationale) is logged to
~/.container-host-aiops/audit.db(relocatable viaCONTAINER_HOST_AIOPS_HOME). - Budget / runaway guard — token and call budgets trip a circuit breaker.
- Risk tiers — graduated autonomy; high-risk ops (remove / prune / recreate) can require a named approver.
- Undo recording — reversible writes record an inverse descriptor built from the fetched before-state.
Scope
This is the container-host member of the AIops-tools family (governed AI-ops with audit + budget + undo + risk tiers), for single-host Docker / Portainer / Podman. It is deliberately NOT for a cluster orchestrator, a hypervisor, a storage appliance, a backup product, or OT / industrial edge — those are separate tools/lines.
Missing a capability?
Coverage is intentionally a curated subset of the Docker Engine + Portainer + Podman (libpod) APIs. Missing a call, or want another container host family? Open an issue or PR — contributions welcome.
Verification status
- Docker — exercised against a live Docker Engine 27.5.1 daemon:
doctorandoverviewconnected over the local socket, therestart-loopand image/volumebloatanalyses were run against real crash-looping containers and real reclaimable data, and a governedstop_containerwrote a row to the audit DB and recorded a working undo descriptor. - Portainer and Podman — mock-validated only. Those API paths are modelled from each project's public API shape and have not been exercised against a live server.
- The full checklist — what the mock suite guarantees, what the Docker run already
satisfied, and what a Portainer/Podman run still has to prove — is in
docs/VERIFICATION.md.
container-host-aiops doctoris the fastest live check on any platform.
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 container_host_aiops-0.4.0.tar.gz.
File metadata
- Download URL: container_host_aiops-0.4.0.tar.gz
- Upload date:
- Size: 209.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea5c7b8b2497e7703254bc71d8f9582feb23bb88e08d38cc90c27a6b42e9466b
|
|
| MD5 |
005d464813f20e42dfb54ebe2751d2f9
|
|
| BLAKE2b-256 |
f3270fcbe6aea7c5dd8232bd948e7e89f3149a165f0c2f69b50e5896c500cd65
|
Provenance
The following attestation bundles were made for container_host_aiops-0.4.0.tar.gz:
Publisher:
publish.yml on AIops-tools/Container-Host-AIops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
container_host_aiops-0.4.0.tar.gz -
Subject digest:
ea5c7b8b2497e7703254bc71d8f9582feb23bb88e08d38cc90c27a6b42e9466b - Sigstore transparency entry: 2195662824
- Sigstore integration time:
-
Permalink:
AIops-tools/Container-Host-AIops@268ebcc4fea8c4ba96eff0622bb0789821584d90 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/AIops-tools
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@268ebcc4fea8c4ba96eff0622bb0789821584d90 -
Trigger Event:
release
-
Statement type:
File details
Details for the file container_host_aiops-0.4.0-py3-none-any.whl.
File metadata
- Download URL: container_host_aiops-0.4.0-py3-none-any.whl
- Upload date:
- Size: 111.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12b238bbb9efd7169c5a459158087637aa78e3f397e2f3f98c23693c4844c4bc
|
|
| MD5 |
203ebfbac89cc3b66d9b77ef476e0550
|
|
| BLAKE2b-256 |
6af567b2b3fab513e6d9ed7c2c8d30f429f776c49f18cb01b294bfa74fafb3fb
|
Provenance
The following attestation bundles were made for container_host_aiops-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on AIops-tools/Container-Host-AIops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
container_host_aiops-0.4.0-py3-none-any.whl -
Subject digest:
12b238bbb9efd7169c5a459158087637aa78e3f397e2f3f98c23693c4844c4bc - Sigstore transparency entry: 2195662829
- Sigstore integration time:
-
Permalink:
AIops-tools/Container-Host-AIops@268ebcc4fea8c4ba96eff0622bb0789821584d90 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/AIops-tools
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@268ebcc4fea8c4ba96eff0622bb0789821584d90 -
Trigger Event:
release
-
Statement type: