About the project

Inspiration

Every engineering team has the same quiet tax: someone has to read the board every morning, decide what's actually runnable, do the work, get it reviewed, and open the PR. The interesting part — designing and building — is wrapped in hours of triage and coordination. We wanted to close the loop from a Jira spec to a reviewed pull request without a human in the inner loop, while keeping a hard human gate on every merge. The "loop engineering" framing — observe, act, verify, self-correct — is exactly the shape of an autonomous engineer, so we built one.

What it does

MoANT is a never-exiting orchestrator that runs an autonomous engineering agent named MoANT. Every working morning at 06:00 a scheduler wakes MoANT, who:

  • Reads the whole Jira board through the Nexla MCP server and orders a runnable day, writing statuses back (To Do → Selected, unrunnable → Blocked with a stated reason).
  • Picks the top tickets by priority and, for each one, runs a bounded implement → verify loop: Claude Code writes the change on a fresh git worktree, then Codex adversarially reviews the diff refute-by-default, up to three rounds, until the change is correct or gets flagged.
  • Opens a GitHub pull request against main — and never merges it. A human reviews and merges.
  • Narrates every transition in Slack (plan, each verify round, PR link, blocks, summary) so a person always knows what the agent is doing. The autonomy boundary is explicit: code becomes a branch + PR only, status transitions are autonomous, and merge/apply requires a human identity — enforced at the proxy layer, not by convention.

How we built it

The core is a pure decision function (dispatcher.py) that takes the board, gates, a failure ledger, and a classifier, and returns a single next action — so it's fully unit-testable with no network and no token spend. All I/O lives at the edges in an integrations/ layer, and the daemon runs two lanes: a daily plan lane and a continuous code lane that runs exactly one heavy task at a time.

The stack is built around the hackathon's sponsor tools, each doing one job:

  • Nexla MCP server — the single data plane to Jira: read tickets, transition status, post observations, all through one MCP tool surface
  • Akash — every task runs in its own throwaway isolated container, so a worker can't see another task's files, tokens, or network.
  • Zero.xyz — keyless service discovery, reframed as a recovery class: when a worker hits a service it has no key for, it discovers and calls it with no keys and no config instead of dead-ending.
  • Claude Code as the implementer and Codex as the adversarial verifier, alternating in the fix loop.
  • Slack for narration and GitHub for the PR. A self-correction taxonomy (observe → classify → recover) maps each failure signature — transient, missing_service, spec_gap, logic_defect, env_broken, budget_exceeded — to a specific recovery, so the box is never idle while a runnable ticket exists.

Challenges we ran into

Keeping the decision logic honest was the hard part. Making the dispatcher a pure function meant every piece of real-world messiness — auth, isolation, rate limits, partial failures — had to be pushed to the edges so the core stayed deterministic and testable. Enforcing the human-merge gate as an actual policy (a Pomerium-denied endpoint for worker tokens) rather than a polite convention took care, as did designing a bounded fix loop that fails safe: three rejected rounds still opens a PR, but flags it and moves the ticket to Blocked instead of silently giving up or looping forever.

Accomplishments that we're proud of

  • A working orchestration core with a Streamable HTTP client for the Nexla MCP through Pomerium — initialization, tool discovery, board reads, transitions, and comments all verified against the live route by a moant-jira-check preflight.
  • A genuinely testable autonomous system: the dispatcher, ledger, planner, and taxonomy all have offline tests that run with no network and no tokens.
  • Turning keyless discovery (Zero.xyz) from a convenience into a first-class recovery in the self-correction taxonomy.
  • Safety rails that are real: a kill switch (touch /tmp/moant.pause), a dry-run mode, per-task wall-clock and token budgets, and an anti-thrash ledger that quarantines a ticket after three failures.

What we learned

The value of a hard boundary between the decision and the action. When the thing that decides "what should I do next" has no side effects, you can test it exhaustively and trust it in production; everything dangerous lives behind a scoped identity at the edge. We also learned that "self-correcting" is mostly a classification problem — a good failure taxonomy with a mapped recovery for each class is what keeps an autonomous agent from either dead-ending or thrashing.

What's next for MoANT

Letting Hermes propose new tickets from recurring failure patterns it observes on the board.

Built With

Share this project:

Updates