aitomaton watches the errors of everything running on your Docker Swarm. It reads each one as a single event, as part of a burst, and as a long-term pattern, for one service or across a whole architecture. Then it decides what to do. When the answer is "this is a bug in our code", a coding agent gets a ready-to-push clone and a full brief, and a pull request comes back.
One small service with no dependencies beyond Python's standard library. Webhooks or polling bring errors in, and every tick turns them into findings, decisions and work.
Sentry / urgentry webhooks and API polling, Alertmanager alerts. Everything becomes per-minute occurrences.
Swarm service labels say where each service's source is, what it depends on, and what aitomaton may do.
Single errors, bursts and trends per issue, per service and per architecture, including cascades.
Rules, then laya, JEV and an LLM, each asked only when the last is unsure. Capped by policy.
A stairway space with a prepared clone; the agent fixes, tests and pushes, and aitomaton opens the PR.
One exception, a storm of them, and a slow creep over two weeks call for different responses. So does a failure in one app versus the whole stack failing because its database did.
dependsWhen the front end times out because the database is down, only the database is a root cause. Downstream services are reported, never "fixed".
Every tier answers the same three things: an action (ignore, watch,
report, fix), a confidence, and the probability that it is a code defect. The next
tier is asked only when the stakes are real and the last answer is unsure or disagrees. A tier that is down
hands over to the next.
Deterministic severity and code-defect scores from the analysis, memory pressure and cascade position.
Two calibrated yes/no reads in one forward pass: urgent? code defect? 0.96 vs 0.11 for a KeyError vs a full disk.
TypeSafe's jev-router on OpenRouter picks the model and reasoning effort per request.
Any OpenAI-compatible model, from OpenRouter or local through Ollama or vLLM. It sees what the earlier tiers said.
Guard rails no model can override: no repo means no fix; an unlikely code defect means no fix; the service's policy caps the action.
There's no registry of apps to keep in sync. Put a few labels on a service and aitomaton knows its repo, its Sentry project, what it depends on, which agent to use, and how far it may go.
holodocker.repo, …repo_ref, …repo_path)# any service in a stack deploy: labels: aitomaton.repo: https://github.com/acme/shop-api aitomaton.ref: main aitomaton.policy: pr # observe|report|pr|push aitomaton.sentry.project: shop-api aitomaton.depends: db aitomaton.test: pytest -q aitomaton.agent: opencode aitomaton.model: qwen/qwen3-coder aitomaton.git.credential: acme # a name, not a token aitomaton.notes: "never touch migrations/"
observeAnalyse and decide, record only.
reportOpen a GitHub issue with the full analysis.
prFix in a stairway space, deliver a pull request.
pushPush to the branch when the tests pass, open a PR otherwise.
A fix becomes a stairway experiment:
a folder on your server with a coding agent in it, visible in claude.ai/code so you can watch or take over.
aitomaton/fix-…. The agent only commits and pushes.AITOMATON-RESULT; aitomaton opens the PR and deletes the credential.## the brief, abridged You are aitomaton's fixer. A production error in service `billing_api` was judged a code defect. - GitHub: https://github.com/acme/billing (main) - Already cloned in ./repo on aitomaton/fix-5120, with push access configured. 4. Commit and `git push -u origin aitomaton/fix-5120`. Report status "branch": aitomaton opens the PR. ### KeyError: 'vat_rate' billing/invoice.py:88 in total rate = country['vat_rate'] AITOMATON-RESULT: {"status": "branch", "title": "Default VAT for countries without a rate", …}
/status.json lists works in progress, findings, every decision with each tier's reasoning, and the issues with
their analysis. The status page renders it. The demo below runs the real engine on a synthetic swarm: a
database takes down its stack, a new KeyError bursts, a worker slowly degrades.
Requirements: a swarm manager, a Sentry or urgentry, and optionally stairway, laya, an OpenRouter key and GitHub tokens. Start in dry-run, read its decisions for a few days, then let it act.
POST /hooks/sentry (HMAC-verified)POST /hooks/alertmanager?token=…POST /hooks/stairwayGET /status.json and GET /git clone https://github.com/sirmmo/aitomaton cd aitomaton docker build -t aitomaton:0.1 . docker build -t aitomaton-laya:0.1 laya cp .env.example .env # SENTRY_URL / SENTRY_TOKEN / SENTRY_ORG # STAIRWAY_URL / STAIRWAY_TOKEN # JEV_MODEL=typesafe/jev-router, LLM_API_KEY # AITOMATON_GIT_TOKEN_<OWNER>=… # AITOMATON_DISPATCH=0 ← dry run first docker stack deploy -c stack.yml aitomaton
All of it lives in the repository.