One natural-language petition enters the city. One Decree comes out.
A config-driven multi-agent orchestrator for Claude Code β authored in TypeScript, shipped as one serverless file with zero runtime dependencies.
A single agent doing everything saturates: the context window is working memory, and once it fills the agent drifts out of character, mixes concerns, and lets through mistakes that nobody audits. And if you split the work across agents by hand, you end up rewriting routing, parallelism, and verification in every project.
So a request is split across specialists with fresh context, audited by always-on guardians, false blockers filtered out by an adversarial trial, and everything reconciled into one verdict β by configuring a single block, without touching the engine. The human still decides the irreversible (merge, deploy, publish): Atlantis prepares and reconciles, it doesn't ship to production.
Six acts, each with its name and its craft. Config-driven; runs with Claude Code's Workflow tool.
| Act | In the city | What it actually does |
|---|---|---|
| 1 Β· The Oracle | reads the petition | an LLM router splits it into lanes per expert + classifies complexity (trivial β swift current) |
| 2 Β· The Heralds | announce | (optional) register the initiative (ticket/card) before dispatch |
| 3 Β· The Artisans | build | one expert agent per lane, in parallel, each isolated in its worktree |
| 4 Β· The Guardians | watch | audit what was dispatched β always-on + conditional. They don't touch code |
| 5 Β· The three Judges | sentence | Minos Β· Rhadamanthus Β· Aeacus weigh each π΄; it survives only by majority |
| 6 Β· The Decree | proclaims | fuses everything into one verdict: β done Β· π΄ blocker Β· π‘ pending Β· β next step |
- Swift current. If the Oracle marks the petition trivial and it maps to β€1 lane, it resolves inline: no Heralds, no worktrees, no Guardians.
- Low tide (dry-run). To test the city without it doing anything real: the Artisans run in report mode (zero worktrees/branches/commits/issues) and only say what they would do.
- The Judges' trial. A single-voice Guardian can over-severize or hallucinate a π΄ that stops the human. Before the Decree, each π΄ passes through the three Judges (repro/authority/severity lenses) that try to refute it; it survives only by majority. π‘/βͺ findings don't pay this, and with zero π΄ the act is skipped entirely.
- Claude Code with the
Workflowtool available. - One or more subagents (the Artisans) in
.claude/agents/. Everyprofileand everyguard.profilemust exist as an agent there β seeexamples/agents/agent-docs.md. - To use Atlantis: no servers or build β the emitted
atlantis.mjsis still a single self-contained file you can copy into your repo. The TypeScript toolchain (src/+npm run build) is only for developing Atlantis itself.
Atlantis is also natively compatible with the Antigravity (Gemini) ecosystem, leveraging its Customizations (Skills) and parallel subagent orchestration.
- Antigravity environment active.
- Local skill configuration detailed under
integrations/antigravity/.
- Clone this repo (or copy
atlantis.mjsinto yours). - Define your roster in
src/workflow/config.tsand runnpm run buildβ or edit theCONFIGblock inside the emittedatlantis.mjsdirectly if you don't want the toolchain.Workflowscripts run sandboxed (no filesystem), so the config lives inline in the script.atlantis.config.example.tsis the commented shape. - Run the city with the
Workflowtool, passing your petition asargs:
Workflow({ scriptPath: 'atlantis.mjs', args: 'fix the back button on the map' })The return struct carries { request, dryRun, complexity, lanes, results, guards, verifiedBlockers, refutedBlockers, synthesis }. Low tide:
Workflow({ scriptPath: 'atlantis.mjs', args: { request: 'your request', dryRun: true } })Define your roster in src/workflow/config.ts (then npm run build). Commented shape: atlantis.config.example.ts. A real 14-Artisan roster: examples/example.config.ts.
- Copy the
.agents/folder to the root of your project. - Configure your roster in
integrations/antigravity/atlantis.config.json. - Ask the agent in the chat: "Use Atlantis for [your request]".
- To run the CLI simulation harness in your terminal:
node integrations/antigravity/atlantis-harness-gemini.mjs "Your development request"
Editing the CONFIG block by hand works, but for a quick roster tweak or to keep a vendored atlantis.mjs current, there's a small CLI β bin/atlantis.mjs, wired as the atlantis bin in package.json (npm link, or run it directly with node bin/atlantis.mjs).
atlantis config # interactive wizard: add/edit/remove Artisans, Guardians, Heralds, the dispatch preamble
atlantis config --show # print the current roster and exit
atlantis doctor # validate: do all referenced profiles exist as .claude/agents/*.md? any Guardian
# with neither `always` nor `when` (so it never runs)? Node version OK?
atlantis update # pull the latest engine from GitHub into your vendored atlantis.mjs β
# your CONFIG is spliced back in untouched, never overwritten
atlantis update --dry-run # show what would change without writing anythingatlantis config detects which mode you're in: if src/workflow/config.ts exists it edits that file (TypeScript source) and reruns npm run build on save; otherwise it edits the CONFIG block directly inside a vendored atlantis.mjs β the exact "copy the file into your repo" flow the README describes above.
The tricky part it gets right: a Guardian's when predicate is a hand-written function β the wizard never tries to regenerate it. Editing any other field on that Guardian (lens, focus, model, always) patches only that field surgically; the when function survives byte-for-byte. atlantis update uses the same trick in reverse: it fetches the newest engine from soyerno/Atlantis (override with --repo/--ref, or go fully offline with --from-file), grafts your local CONFIG block into it, and only writes the result after confirming the merged file still parses as a valid Workflow script β a .bak of your previous file is kept alongside it.
Claude Code already ships the bricks: subagents (the Task/Agent tool) and Workflow for deterministic fan-out. Atlantis doesn't replace them, it uses them β an opinionated recipe on top:
Bare subagent (Task) |
Raw Workflow |
Atlantis | |
|---|---|---|---|
| Decides which expert takes it | you, by hand | you, in the script | the Oracle over your roster |
| Runs several in parallel | no | yes, you wire it | yes, one Artisan per lane |
| Post-work safety net | no | whatever you write | always-on + conditional Guardians |
| Stops false π΄ | no | no | the three Judges (majority) |
| Reconciles into one verdict | no | whatever you write | the Decree |
| Per-project configurable | β | rewrite the script | one CONFIG block |
Rule of thumb: one expert + one task β just call a subagent. Atlantis wins when the request crosses several concerns and you want something to audit and reconcile the result β without rewriting the orchestration each time.
Atlantis can live in Slack as one more collaborator: you talk to it in a channel or thread, it runs the city, and the Decree returns to the thread. A reply in the same thread continues the task with live context. See slack/.
Privacy boundary (by design). The Slack-side Atlantis only sees what's said in Slack, plus its own scheduled daily reports. It never observes or mirrors work in your local/dev environment: what happens on your machine stays on your machine. The agent behaves as if it lives in Slack β not as a mirror of your terminal.
| File / Folder | What it is |
|---|---|
src/ |
TypeScript source (single source of truth): workflow body, shared types, interactive confirm, harness, Slack bridges, CLI. |
atlantis.mjs |
The orchestrator script β generated from src/workflow/ by npm run build, still one self-contained plain-JS file. |
atlantis.config.example.ts |
Commented, typed config example. |
examples/example.config.ts |
A real 14-Artisan + Guardian config. |
examples/agents/agent-docs.md |
Structure of an agent profile. |
integrations/antigravity/ |
Config and harness for Gemini Antigravity compatibility (harness generated from src/harness/). |
slack/ |
Two-way Slack bridge + daily reports (generated from src/slack/). |
bin/atlantis.mjs |
The atlantis CLI (config / update / doctor) β generated from src/cli/. |
scripts/ |
build.mjs (TS β emitted .mjs), smoke.mjs (Workflow sandbox test), verify-cli.mjs (CLI integration test). |
assets/ |
Visual assets (banner, diagrams). |
The Workflow sandbox only accepts plain JavaScript (type annotations don't parse, and there are no Node APIs), so Atlantis is authored in TypeScript under src/ and compiled to the .mjs files consumers use:
npm install
npm run verify # typecheck (tsc) + build (esbuild) + smoke test of atlantis.mjs + CLI integration testThe build guarantees the Workflow contract for atlantis.mjs: first statement is the literal export const meta = {β¦}, no static imports (the only import() of node:readline is dynamic and gated behind a TTY check that never runs in the sandbox), and the async body ends in a top-level return. The smoke test (npm test) re-runs the emitted file inside a simulated sandbox β agent/parallel/phase/log stubbed, every Node global shadowed (process, console, Buffer, timers, fetchβ¦) β across five scenarios: full standard run, judge-refuted blocker, swift current, dry-run via JSON-string args, and empty/non-string petition. Its asserts discover your roster from the Oracle prompt at runtime, so editing src/workflow/config.ts never breaks verify. scripts/verify-cli.mjs does the same for bin/atlantis.mjs: it drives the real emitted CLI as a subprocess (piped stdin for the interactive wizard) across both modes (toolchain / vendored file), and specifically checks that a hand-written Guardian when function survives byte-for-byte through unrelated edits.
The pattern orchestrator β swappable pool of experts β verification was productized by Sakana AI as Fugu (2026); Atlantis takes it to a small, serverless piece living inside your repo. Licensed MIT.
π± Atlantis Β· one petition in, one Decree out.