English | Türkçe
agent-orchestrator
Point it at the agent you are already running. It picks up from there.
No new harness. No re-planning. No "start a fresh session so the tool can manage it."
ao attaches to a coding agent that is already working — in your IDE, in a terminal,
started by someone else — reads its state without touching it, and takes over the
tedious half: noticing when it stalls, running the gates, deciding what may be
committed, and keeping work moving while you sleep.
That is the whole difference. Every other orchestrator owns the agent: it spawns the
process, it drives the loop, and adopting it means restarting your work inside it.
ao owns the authority instead — what is finished, what is good, what may land —
and leaves the agent where it is.
pip install ao-orchestrator # or: uv tool install ao-orchestrator
cd ~/your-project && ao status # it finds the running session by itself
Or with nothing installed at all, using the Python macOS and most Linux distributions already ship:
git clone https://github.com/hakkisagdic/agent-orchestrator ~/ao
mkdir -p ~/.local/bin && ln -s ~/ao/bin/ao ~/.local/bin/ao # ~/.local/bin must be on PATH
A symlink, not a shell alias: neither /bin/sh, which runs ao's commit hook, nor an agent
the watchdog starts without your shell can see an alias.
No dependencies, by choice — this watches agents on machines it does not control, and
a dependency is a thing that can be missing exactly there. Nothing to configure before
the first run: ao discovers the session from the agent's own store — Kiro's and Claude
Code's today — and session: auto in a config written by ao init --profile resolves the
same way. Where the implementer and the architect run one harness in one directory, ao
does not guess which session is whose: ao doctor says so, and a pinned id settles it
(docs/profiles.md).
Windows ships PowerShell and does not ship Python, so bin/ao.ps1 covers status,
board and doctor with nothing installed. It is a deliberate subset and stays one —
everything else either takes a decision, spends the machine, kills processes or speaks
a protocol, and a second implementation of any of those is a second thing to be wrong.
For the rest: winget install Python.Python.3.12 && pip install ao-orchestrator.
The test suite runs on a hosted Windows runner every week and on demand, and passes,
this script reading a board and the commit hook's execution proof included. Still open
on Windows (windows.md): the lane has yet to start an agent CLI
through a .cmd, which now takes its prompt on standard input.
Where this came from. Extracted from a 30-epic durable-workflow product built over weeks by exactly this loop. Every guard in here exists because something went wrong first: a watchdog that started a second turn on one session and left a rename half-applied; fifteen agent processes accumulated in one repository; a timestamp bug that made live evidence look three hours stale.
docs/lessons.mdis the list. None of it was designed in advance.
What it does
Watches. ao watch is a live panel: what the agent is doing, context and cost,
open reviews, the work board, and — the part no other panel has — whether it is
busy but producing nothing. An agent stuck in a wait loop looks perfectly healthy:
transcript growing, tool calls firing, credits burning. ao compares activity
against artifacts and says so.
Restarts. Turn-based agents stop when a turn ends, mid-slice or not. A watchdog
notices and nudges. Detection is free — a file mtime and a couple of git calls —
and a chain of guards makes sure a nudge is never spent where it cannot help: no
second turn while one is running, no nudge into a provider outage, no nudge past the
round budget, no nudge when a human has taken the tree.
Verifies. ao verify runs your gates and writes the numbers to a ledger. Not
the agent's report of its gates — the commands, run again, by something with no stake
in the result.
Decides. ao commit-ok grants commit authority from that evidence: gates passed,
review approved, plan unedited, and the measurement still describes the tree in front
of it. Every refusal names its missing condition. It never covers push.
Keeps going. A slice blocked on a human decision is parked with the reason recorded, and work moves to the next pre-authorised item. When the queue runs dry, the architect is woken to refill it — never the implementer, because choosing your own scope is the one authority an implementer must not have.
Setup, step by step
pip install ao-orchestrator(oruv tool install ao-orchestrator, or the Homebrew tap).- In the repository:
ao init --profile claude-kiro. Writes.ao/, the mailbox, the playbook, and registers the MCP server for the agents it detects. With one harness for every role,claude-claudeneeds a review tier, because its reviewer is of the implementer's own model family:ao init --profile claude-claude --review-tier same-family --by <name>lets another model of that family review, and every such review sayssame family: weaker independence;ao init --profile claude-claude --review-tier personconfigures no model reviewer, and a person reviews each candidate withao person-review --by <name>. A reviewer of another family stays the default and the strongest (review tiers). - Wire the rules. ao does not write your
CLAUDE.md/AGENTS.md: paste the printed pointer there, or re-runao init --rules. Until thenao doctorsaysrules-not-wired— the playbook is written but no agent reads it. (A Claude Code skill file is discovered on its own.) - Start or restart the agent's app in the directory so the
aoMCP tools load. ao doctor. Thenao email setupand, if you want it,ao telegram setup;ao pings setup --urlfor the dead man's switch.ao watchdog installfor unattended runs (a doctor job comes with it).ao featuresto choose what you pay for;ao remove --yestakes everything off again.ao prove. It runs the guarantees instead of describing them: the hook must refuse a synthetic candidate, the reviewer must answer as another actor, and a throwaway slice must pass verify, review and commit-ok. Nothing is committed. Getting started is the whole sequence.- Later,
ao updateupdates ao the way it was installed, whichever way that was, andao uninstalltakes its jobs, hooks and MCP entries off the machine before the program goes (update and uninstall).
Commands
ao status · ao watch |
one project: state, telemetry, problems, board |
ao watch --all · ao fleet |
every project, ordered by what needs a human first |
ao watch --web [--port N] |
the panel, the board and the fleet as read-only pages on 127.0.0.1: a browser tab in place of a terminal (surfaces.md) |
ao board |
where each item is; READY = queued items whose needs: are done |
ao board add ID "title" --acceptance "…" |
admit one item, only with its acceptance boundary |
ao verify [-p full] |
run the declared gates, record the result |
ao commit-ok [--verify] |
may this tree be committed? decided from evidence |
ao commit -m … · ao commit-check --range A..B |
commit the granted candidate, its message ending with Ao- trailers that name the grant; check that each landed commit has the tree its trailers name, with no .ao/ needed, as CI runs it (gates.md) |
ao hold / ao hold release --note … |
stop every agent in the tree, and keep them stopped |
ao writers / ao writers --clean |
live turns in the tree (one per turn, not per process), orphans set aside; --clean stops only the orphans |
ao fanout ok --agents N / ao fanout record … / ao fanout history |
may a fan-out of N sub-agents start now (hard cap, recent limit hit, provider window); record what one cost |
ao cost --since 24h |
what the coordination itself spends: implementer turns by class (product / analysis / ceremony / coordination), wasted turns, reviews; --since, like every time a command takes, is 30m, 2h, 1d, today, yesterday or a date; --usd prices the tokens in US dollars from a bundled price table, as an estimate (telemetry.md) |
| `ao features [on | off ]` |
| platforms | macOS and Linux native; Windows first cut (windows.md); the suite runs on Ubuntu for every push and pull request, on macOS and Windows weekly |
ao waive review --slice B7 --by <name> --why … / ao catchup |
a person bypasses a gate on the record; catchup reviews each landed range with a model family other than the one that wrote it, against what its commit messages claim, closes a move-only split on the proof its grant recorded, run again, and replays deferred wakes and nudges. ao catchup --plan previews it, names what closes by proof, and writes nothing, ao catchup --limit 10 and ao catchup --slice B7 bound a run, ao catchup --author-family <family> --by <name> is a person naming a family ao did not record, and ao catchup --move-only <slices> --by <name> is a person stating which waived slices only moved code, each closing only where the proof holds, and ao catchup --slice B7 --reviewer <actor> reviews with another reviewer actor of the table, so runs over different slices go side by side; a run exits 3 when the reviews it started decided nothing, and 0 when it made progress or had nothing to do |
ao pings setup --url … |
dead man's switch: external pings that alarm when the watchdog and its doctor job both die |
| `ao hooks [status | install |
ao skill install / ao skill show |
the playbook (roles, loop, authority, protocol, alarms, every command) rendered for the agents this repo uses: Claude skill, Kiro steering, AGENTS.md |
ao remove --yes [--allow-shared-hooks] |
two-phase removal: delete and commit .ao-project while enforcement remains active, then remove AO state after HEAD and index no longer contain it; foreign/protected hooks stay untouched. The second phase takes off the project's scheduled jobs and exactly its own files in ~/.ao, lists each by name in the dry run, and exits 1 naming what it could not remove (watchdog.md) |
ao update [--dry-run|--yes] |
update ao the way it was installed: a git clone fast-forwards, and is refused while it has uncommitted changes; a Homebrew, pipx or uv install upgrades through its own tool, a pip install through the pip of the interpreter running ao. The command is shown first and runs on --yes or a yes at the terminal (getting started) |
ao uninstall [--yes] [--purge] [--allow-shared-hooks] |
take what ao installed off this machine: every scheduled job of ao's, ao's own hooks in each project the registry knows, and the ao entry in their MCP files; a dry run unless --yes, naming what it leaves - each project's .ao/, ~/.ao unless --purge, and the program, with the command that removes it |
| `ao init --profile claude-kiro | claude-claude [--review-tier same-family |
ao doctor --check |
quiet doctor for a scheduler: one line per problem, exit 1, alarms raised — installed as a 15-minute launchd job, or systemd user timer on Linux, by ao watchdog install |
ao email setup / ao email test |
the red alarm channel: e-mail via formsubmit.co, no server (alarms.md) |
ao alarms / ao alarms test --level red |
live alarm episodes and their level; test rings every channel |
ao mail log / ao mail search <text> / ao mail ack <glob> |
the mail ledger: every message written and when it was consumed, searchable after deletion |
ao watchdog explain / ao watchdog trace |
why the watchdog did or did not act: measurements and verdicts of this cycle, and of the recorded ones (watchdog.md) |
ao source import |
admit tracker items onto the board |
ao mail · ao notices |
coordination messages; alerts this project raised |
ao watchdog install |
launchd job, or systemd user timer on Linux, that restarts a stalled agent (watchdog.md) |
ao mcp serve · ao a2a serve |
expose state to MCP clients / as A2A tasks |
ao telegram setup |
alerts to your phone, decisions back from it |
ao digest [--days N] |
what happened, read from the ledgers — also answers "why is nothing moving" |
ao ask · ao answer · ao decisions |
questions answerable in one tap; free text always last; an answer must be an offered key, and ao answer <D-id> <key> --change replaces one while the first stays on the record |
ao propose "…" --why "…" [--rule-file <path>] · ao proposals |
an agent proposes a change to a rule it works under instead of editing it: recorded in the decision ledger with its evidence, and a person accepts or rejects it with ao answer; nothing writes the rule file (protocol.md) |
ao note |
an architect message into the mailbox, through the tool |
ao review |
review the tree with an actor that did not write it |
ao person-review --by <name> |
a person reads the staged diff, then records --verdict APPROVED or NEEDS_CHANGES with the --digest it showed; bound to the candidate like any review, labeled person review, never an agent's command |
ao review --commits <range> |
review landed work after the fact; exit 3 means no reviewer could review (never a verdict), fallbacks in reviewer.fallbacks (roles.md) |
ao handoff |
write and send everything a successor needs |
ao a2a-mcp serve |
reach A2A agents from an MCP-only client |
ao prune |
trim accumulated records and logs |
ao doctor · ao adapters |
check the wiring; what is supported and how well |
ao completion zsh |
print a script that completes ao's commands, options and choices; bash, fish and powershell too, installed as getting started shows, and printed again after ao update |
ao --version |
the installed version |
Hook status separates static intent from executable enforcement. AO enforcement is
opted in only by a root .ao-project whose exact ao-project-v1\n bytes exist in
HEAD or the active index; an incidental .ao/ directory is inert. A staged marker
enables first adoption, while a staged deletion remains enrolled through HEAD until
that deletion is committed. An enrolled project requires .ao/config.json to be a
valid, non-empty top-level JSON object. AO reads at most 1,048,576 bytes and
rejects container nesting deeper than 64 before recursive JSON decoding;
pre-dispatch loading and commit enforcement use the same bounded result. Missing
or unreadable state refuses with the one-line ao init --profile claude-kiro
repair.
The current-local (behavior unverified) and current-scoped (behavior unverified)
labels describe bytes only; pre-commit execution: installed (execution proved)
is printed only after Git resolves and runs the active hook with an isolated
synthetic index and AO returns the nonce-bound refusal for that exact challenge.
The probe never commits, changes the real index, or writes a Git object. A missing,
misplaced, non-executable, stale, foreign, or fail-open hook is not installed, and
hooks status, doctor, doctor --check, and init consume the same result.
status also names the effective path, path class, winning core.hooksPath
scope/origin/value, track state, and misplaced AO forms. A hook installed in the
repository's git directory also names the ao that installed it, and falls back on that
file only when /bin/sh finds no ao on PATH; hooks status and doctor say when it
cannot, with the symlink that fixes it. Install handles
pre-commit and pre-push independently, so it may install an eligible pre-commit,
preserve a custom pre-push byte-for-byte, report the push-window hook unavailable,
and return 1. Install, uninstall, and remove refuse the entire mutation set when
any eligible target is shared, external, or selected by global/system config
unless --allow-shared-hooks is explicit.
The rules it enforces
These are not style preferences. Each one is a failure that cost real hours.
- Whoever writes the code does not verify it, and does not decide it may land.
- A plan is read, never edited — when the document a slice is judged against can be edited by the thing being judged, every later check is circular.
- Pulling work is not authorising it. A tracker item is something a person wrote, not a specification anyone verified. It enters the queue with a written acceptance boundary or it does not enter.
- Heavy operations belong to one actor. Gates are serialised machine-wide; N projects running N test suites is not N times the throughput, it is one suite that no longer finishes.
- Authority lives in always-included context, never in a mailbox. A stuck agent is exactly the agent not reading its mail.
pushis never granted by this tool. Nor PRs, force-pushes, or hook bypasses.
Agent support
ao reads each agent's own session store; the adapter says where and in what shape.
| verified | adapters |
|---|---|
| full — every capability exercised in a production run | kiro, claude-code, antigravity |
| partial — reads state, some capabilities unexercised | opencode, command-code, codex, qoder, openai-api |
| documented — written from published docs, not yet run | cursor-agent |
| untested — schema present, needs a first run | gemini, aider, amp, copilot, amazon-q, deepseek, ollama, droid, grok, hermes, kilocode, kimi, omp, pi, pr-agent, qwen, reasonix, trae |
ao adapters shows this table against what is actually installed on your machine, and
— with keyflip — whether an account exists
even when the CLI does not. Adding one is a JSON file; see
docs/adapters.md.
The hosted tests workflow runs the suite on every push to main and every pull request
on Ubuntu, with Python 3.9 (the support floor) and 3.12; macOS and Windows run every
week and on demand (gh workflow run tests -f os=windows-latest -f python=3.12). The
repository is public, so the hosted runners cost nothing, and the pre-push hook still
runs the suite locally before a push: first the tests the pushed commits touch, then the
whole suite, in four processes where pytest-xdist (the dev extra) is installed -
AO_PREPUSH_WORKERS sets how many, and 0 keeps one. A release tag runs the suite again
before it publishes. Hosted runs cover OS
API behavior and deterministic process crashes with real child processes and
temporary paths. They are not physical power-loss, storage-controller or filesystem
qualification, including unsupported and network filesystems.
Documentation
getting started · protocol · safety · roles · privacy · security policy · capability matrix · architecture decisions · slices · gates · sources · adapters · parallel · cloud · models · telegram · mcp · telemetry · surfaces · ledger · recovery · keyflip · ide-extensions · lessons
Status
Working today: everything in the command table above, exercised daily against a real project. Still specification: every passage the documents mark as not built yet, read lanes, a lane's role and the merge queue among them, and cross-project parallel execution (the view exists; running several implementers at once is governed by the machine gate lock but has not been run in anger).
MIT.
Metadata
Release files for ao-orchestrator 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ao_orchestrator-0.5.0.tar.gz | 1.0 MB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ao_orchestrator-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.8 MB
Release files / ao_orchestrator-0.5.0.tar.gz
| Download URL | ao_orchestrator-0.5.0.tar.gz |
|---|---|
| Size | 1.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7149c5e52efe50b9e0fe992a0ac4a5ae6d3b848f3e604f4b10a2885bd2d9a29b
|
|
BLAKE2b-256 checksum How to use checksums |
2b315249f4ed952a5e1cc29cbee55bb927551b437f43e8177b31fadaef30c339
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency logRelease files / ao_orchestrator-0.5.0-py3-none-any.whl
| Download URL | ao_orchestrator-0.5.0-py3-none-any.whl |
|---|---|
| Size | 730.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6a65ec9242fd15ec5ab5c89c803f8bc8f13534a280857860e032a6f94c8bb3e7
|
|
BLAKE2b-256 checksum How to use checksums |
ebae7e5411970033d2a38e499ffe3f8a4ec1698fec11aad85eb53d822c51c43d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency logSecurity for ao-orchestrator 0.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ao_orchestrator-0.5.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.