agentainer 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +156 -33
- package/examples/brainstorm.yaml +147 -0
- package/examples/code-review-broadcast.yaml +109 -0
- package/examples/debate.yaml +99 -0
- package/examples/existing-repo.yaml +2 -0
- package/examples/incident-response.yaml +140 -0
- package/examples/localization.yaml +136 -0
- package/examples/multi-language-broadcast.yaml +127 -0
- package/examples/ping-pong.yaml +89 -0
- package/examples/red-team.yaml +117 -0
- package/examples/research-swarm.yaml +9 -0
- package/examples/software-company.yaml +16 -1
- package/examples/tdd-pingpong.yaml +82 -0
- package/examples/writers-room.yaml +129 -0
- package/lib/config.py +22 -2
- package/lib/minyaml.py +10 -7
- package/lib/swarm.py +172 -7
- package/llms.txt +26 -0
- package/package.json +10 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mehmetcanfarsak
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,11 +1,81 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- Banner -->
|
|
2
|
+
<p align="center">
|
|
3
|
+
<img alt="Agentainer — multi-agent orchestrator for AI coding agents" src="https://raw.githubusercontent.com/mehmetcanfarsak/AgentSwarm/main/assets/banner.svg" width="820">
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<!-- Badges -->
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img alt="license" src="https://img.shields.io/badge/license-MIT-blue.svg">
|
|
9
|
+
<img alt="zero deps" src="https://img.shields.io/badge/dependencies-zero-brightgreen.svg">
|
|
10
|
+
<img alt="platform" src="https://img.shields.io/badge/platform-linux%20%2F%20macOS-lightgrey.svg">
|
|
11
|
+
<img alt="tests" src="https://img.shields.io/badge/tests-48%20checks%20passing-success.svg">
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<h1 align="center">Agentainer — Multi-Agent Orchestrator for AI Coding Agents</h1>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<strong>A zero-dependency multi-agent orchestrator for AI coding agents.</strong><br>
|
|
18
|
+
Run a team of <b>Claude Code</b>, <b>OpenAI Codex</b>, <b>Gemini CLI</b>, and <b>Hermes</b> side by side in <b>tmux</b> — each in its own directory, each messaging the others only where your config allows.
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<em>Formerly <strong>AgentSwarm</strong>. Installed globally the command is <code>agentainer</code>; from a clone, <code>./agentainer</code> in the repo root is identical.</em>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
**Agentainer** is a lightweight, stdlib-only orchestrator (Python 3 + bash + tmux, no runtime dependencies) that launches multiple AI coding agents — Claude Code, OpenAI Codex, Google's Gemini CLI, and Hermes — in isolated tmux sessions, each with its own working directory, and routes messages between them under a configurable access-control list. Define your whole agent team in a single YAML file; one command brings it online.
|
|
26
|
+
|
|
27
|
+
<!-- Demo -->
|
|
28
|
+
<p align="center">
|
|
29
|
+
<img alt="Terminal demo: agentainer up starts four agents, status shows them running, send delivers a task, and logs stream the routed messages" src="https://raw.githubusercontent.com/mehmetcanfarsak/AgentSwarm/main/assets/demo.svg" width="760">
|
|
30
|
+
<br>
|
|
31
|
+
<em>Start a four-agent swarm, check status, hand it a task, and watch the messages route — in four commands.</em>
|
|
32
|
+
</p>
|
|
2
33
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## <span id="table-of-contents"></span>Table Of Contents
|
|
37
|
+
|
|
38
|
+
- [Why Agentainer](#why-agentainer)
|
|
39
|
+
- [How it fits together](#how-it-fits-together)
|
|
40
|
+
- [Requirements](#requirements)
|
|
41
|
+
- [Install](#install)
|
|
42
|
+
- [Quickstart](#quickstart)
|
|
43
|
+
- [FAQ](#faq)
|
|
44
|
+
- [How it works](#how-it-works)
|
|
45
|
+
- [Capturing what an agent says](#capturing-what-an-agent-says)
|
|
46
|
+
- [Subagents, parallel work, and busy agents](#subagents-parallel-work-and-busy-agents)
|
|
47
|
+
- [Configuration reference](#configuration-reference)
|
|
48
|
+
- [Examples](#examples)
|
|
49
|
+
- [Commands](#commands)
|
|
50
|
+
- [Project layout](#project-layout)
|
|
51
|
+
- [Tests](#tests)
|
|
52
|
+
- [Troubleshooting](#troubleshooting)
|
|
53
|
+
- [A note on flags](#a-note-on-flags)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## <span id="why-agentainer"></span>✨ Why Agentainer
|
|
6
57
|
|
|
7
|
-
|
|
8
|
-
|
|
58
|
+
- **Multi-agent, one command.** Spin up a whole team with `agentainer up` — folders, hooks, tmux sessions, and first prompts, all wired automatically.
|
|
59
|
+
- **Zero runtime dependencies.** Just Python 3 + bash + tmux. No pip installs, no bloated toolchain.
|
|
60
|
+
- **Real ACLs, not vibes.** Agents only message who your YAML `can_talk_to` list permits. `"*"` for everyone, an explicit list for tight graphs.
|
|
61
|
+
- **Survives restarts.** Each turn's conversation id is recorded; `up --resume` reattaches instead of starting cold.
|
|
62
|
+
- **Self-healing routing.** Busy agents queue inbound work, stranded messages get swept, and agents are nudged when a reply reaches nobody.
|
|
63
|
+
- **Any mix of CLIs.** Claude, Codex, Gemini, Hermes — or your own type — in the same swarm.
|
|
64
|
+
|
|
65
|
+
## <span id="how-it-fits-together"></span>🏗️ How It Fits Together
|
|
66
|
+
|
|
67
|
+
*Architecture at a glance: a single `agents.yaml` file maps each AI coding agent to its own tmux session and working directory, while Agentainer routes and logs every message between them under a `can_talk_to` access-control list.*
|
|
68
|
+
|
|
69
|
+
<p align="center">
|
|
70
|
+
<img alt="Agentainer architecture: one YAML file maps each agent to its own tmux session and working directory; Agentainer routes and logs permission-checked messages between them" src="https://raw.githubusercontent.com/mehmetcanfarsak/AgentSwarm/main/assets/architecture.svg" width="900">
|
|
71
|
+
</p>
|
|
72
|
+
|
|
73
|
+
One command starts the swarm: it creates a folder per agent, installs a
|
|
74
|
+
completion hook inside each folder, opens a tmux session per agent, launches
|
|
75
|
+
the CLI, and types each agent's first prompt into it.
|
|
76
|
+
|
|
77
|
+
<details>
|
|
78
|
+
<summary>Plain-text diagram</summary>
|
|
9
79
|
|
|
10
80
|
```
|
|
11
81
|
agents.yaml tmux
|
|
@@ -21,22 +91,20 @@ your YAML file says it may.
|
|
|
21
91
|
one folder per agent messages routed + logged
|
|
22
92
|
```
|
|
23
93
|
|
|
24
|
-
|
|
25
|
-
completion hook inside each folder, opens a tmux session per agent, launches
|
|
26
|
-
the agent's CLI, and types each agent's first prompt into it.
|
|
94
|
+
</details>
|
|
27
95
|
|
|
28
96
|
---
|
|
29
97
|
|
|
30
|
-
## Requirements
|
|
98
|
+
## <span id="requirements"></span>📋 Requirements
|
|
31
99
|
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
100
|
+
- **`tmux`** (3.0+)
|
|
101
|
+
- **`python3`** — PyYAML is used if present, otherwise a bundled parser handles the config
|
|
102
|
+
- **`node`** (16+) — only for the global `agentainer` command; not needed if you run `./agentainer` from a clone
|
|
35
103
|
- whichever agent CLIs you reference: `claude`, `codex`, `gemini`, `hermes` — install only the one(s) you actually use
|
|
36
104
|
|
|
37
|
-
## Install
|
|
105
|
+
## <span id="install"></span>🚀 Install
|
|
38
106
|
|
|
39
|
-
Global, via npm
|
|
107
|
+
**Global, via npm:**
|
|
40
108
|
|
|
41
109
|
```bash
|
|
42
110
|
npm install -g agentainer
|
|
@@ -47,14 +115,14 @@ agentainer doctor # check tmux/python3 are present; report which agent CL
|
|
|
47
115
|
which agent CLIs are available — it never fails on a missing *agent* CLI, since
|
|
48
116
|
you may only use one of them.
|
|
49
117
|
|
|
50
|
-
Or from a clone (no npm needed)
|
|
118
|
+
**Or from a clone (no npm needed):**
|
|
51
119
|
|
|
52
120
|
```bash
|
|
53
121
|
git clone https://github.com/mehmetcanfarsak/AgentSwarm.git && cd AgentSwarm
|
|
54
122
|
./agentainer --help # same commands as the global `agentainer`, straight from the repo
|
|
55
123
|
```
|
|
56
124
|
|
|
57
|
-
## Quickstart
|
|
125
|
+
## <span id="quickstart"></span>⚡ Quickstart
|
|
58
126
|
|
|
59
127
|
```bash
|
|
60
128
|
cp agents.example.yaml agents.yaml
|
|
@@ -80,9 +148,43 @@ agentainer logs reviewer -n 20 # one agent
|
|
|
80
148
|
agentainer inbox developer # messages an agent received
|
|
81
149
|
```
|
|
82
150
|
|
|
151
|
+
`agentainer status` gives you the whole swarm at a glance — who is up, who is mid-turn, and how deep each queue is:
|
|
152
|
+
|
|
153
|
+
<p align="center">
|
|
154
|
+
<img alt="agentainer status output: a table of agents with their type, state, turn, queue depth, capture mode, and can_talk_to permissions" src="https://raw.githubusercontent.com/mehmetcanfarsak/AgentSwarm/main/assets/screenshot-status.svg" width="820">
|
|
155
|
+
</p>
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## <span id="faq"></span>❓ FAQ
|
|
160
|
+
|
|
161
|
+
**What is Agentainer?**
|
|
162
|
+
Agentainer is a zero-dependency multi-agent orchestrator that runs a team of AI coding agents — Claude Code, OpenAI Codex, Google's Gemini CLI, and Hermes — in isolated tmux sessions, each with its own working directory, and routes messages between them under a configurable access-control list. You describe the whole team in one YAML file and start it with a single command.
|
|
163
|
+
|
|
164
|
+
**Which AI coding agents does Agentainer support?**
|
|
165
|
+
Claude Code (`claude`), OpenAI Codex (`codex`), Google's Gemini CLI (`gemini`), and Hermes (`hermes`) out of the box. You can also define your own agent type via `agent_types:` — any CLI that takes input on stdin/tty works, with `capture: pane` or `capture: none`.
|
|
166
|
+
|
|
167
|
+
**Does Agentainer need Docker or any runtime dependencies?**
|
|
168
|
+
No. It is stdlib-only: Python 3, bash, and tmux. PyYAML is used if present, but a bundled parser handles the config without it. Node is only needed for the global `npm` launcher — running `./agentainer` from a clone needs no Node at all.
|
|
169
|
+
|
|
170
|
+
**How do I run multiple coding agents together?**
|
|
171
|
+
Write a YAML config listing your agents (and who may talk to whom), then run `agentainer up`. It creates a folder and a tmux session per agent, installs a turn-completion hook, launches each CLI, and types in the first prompt. `agentainer send --to <agent> "…"` messages any agent; `agentainer validate` previews the resolved swarm without launching anything.
|
|
172
|
+
|
|
173
|
+
**Can agents communicate with each other, and how is that controlled?**
|
|
174
|
+
Yes. Agents exchange tagged `<swarm-message>` / `<swarm-send>` blocks. Messaging is a whitelist: an agent may only reach the agents in its `can_talk_to` list (`"*"` means everyone else); anything else is refused. Auto-forwarding (`forward_responses_to`) can relay finished turns hands-free, bounded by a hop count to prevent loops.
|
|
175
|
+
|
|
176
|
+
**How do I resume a swarm after a crash or reboot?**
|
|
177
|
+
Each finished turn records the agent's conversation id in `.swarm/sessions.yaml`. `agentainer up --resume` reattaches every agent to its own conversation instead of starting cold, keeping any queued mail. Claude resumes with `--resume <id>`, Codex with `resume <id>`; Gemini and Hermes have no recoverable session id and always start fresh (with a warning).
|
|
178
|
+
|
|
179
|
+
**Is it safe to let agents run unattended?**
|
|
180
|
+
Agents run with whatever privileges their CLI is launched with. Flags like `claude --dangerously-skip-permissions`, `codex --yolo`, and `gemini --yolo` let them act without confirmation, which is usually what you want for an unattended swarm — so point `root` at a disposable directory and never run a swarm over a checkout you can't afford to lose.
|
|
181
|
+
|
|
182
|
+
**How is Agentainer different from just opening several terminals?**
|
|
183
|
+
It automates the brittle parts: detecting when each turn finishes (via a Stop/notify hook for Claude/Codex, or pane polling for Gemini/Hermes), typing multi-line prompts reliably into a live TUI, pre-trusting folders so the "trust this directory?" modal doesn't eat the first prompt, enforcing the comms ACL, queueing messages to busy agents, and resuming conversations after a restart.
|
|
184
|
+
|
|
83
185
|
---
|
|
84
186
|
|
|
85
|
-
##
|
|
187
|
+
## <span id="how-it-works"></span>🔧 How It Works
|
|
86
188
|
|
|
87
189
|
**One folder + one tmux session per agent.** Agent `developer` gets
|
|
88
190
|
`workspace/developer/` and a tmux session named `developer` (plus any
|
|
@@ -121,9 +223,8 @@ agents:
|
|
|
121
223
|
checkout), but agents then overwrite each other's files and interleave commits,
|
|
122
224
|
so `validate` and `up` warn when it happens. See
|
|
123
225
|
[`examples/existing-repo.yaml`](examples/existing-repo.yaml).
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
with the logs, inboxes and the `swarm` shim.
|
|
226
|
+
- `root` is still used even when every agent lives elsewhere: it holds `.swarm/`
|
|
227
|
+
with the logs, inboxes and the `swarm` shim.
|
|
127
228
|
|
|
128
229
|
**Prompts are typed in, not piped.** `swarm up` drops each first prompt into the
|
|
129
230
|
agent's input box with a tmux bracketed paste, as one block, then presses Enter.
|
|
@@ -260,7 +361,7 @@ agent sees on its own terminal. Use `can_talk_to: "*"` for "everyone else".
|
|
|
260
361
|
|
|
261
362
|
---
|
|
262
363
|
|
|
263
|
-
##
|
|
364
|
+
## <span id="capturing-what-an-agent-says"></span>🎬 Capturing What An Agent Says
|
|
264
365
|
|
|
265
366
|
Agentainer needs to know when an agent finishes a turn — both to log it and to
|
|
266
367
|
support auto-forwarding. How it finds out depends on the CLI, and the two
|
|
@@ -293,7 +394,7 @@ mechanisms are **not** equally good:
|
|
|
293
394
|
|
|
294
395
|
Set `capture:` per agent to override the default for its type.
|
|
295
396
|
|
|
296
|
-
### Subagents, parallel work, and busy agents
|
|
397
|
+
### <span id="subagents-parallel-work-and-busy-agents"></span>🧩 Subagents, parallel work, and busy agents
|
|
297
398
|
|
|
298
399
|
Coding agents spawn subagents and background tasks. Four things follow from that.
|
|
299
400
|
|
|
@@ -408,7 +509,7 @@ speak, and leave `forward_responses_to` unset.
|
|
|
408
509
|
|
|
409
510
|
---
|
|
410
511
|
|
|
411
|
-
## Configuration
|
|
512
|
+
## <span id="configuration-reference"></span>⚙️ Configuration Reference
|
|
412
513
|
|
|
413
514
|
Full annotated example: [`agents.example.yaml`](agents.example.yaml).
|
|
414
515
|
Machine-readable summary for agents: [`llms.txt`](llms.txt).
|
|
@@ -485,7 +586,7 @@ placeholders.
|
|
|
485
586
|
|
|
486
587
|
---
|
|
487
588
|
|
|
488
|
-
## Examples
|
|
589
|
+
## <span id="examples"></span>🧪 Examples
|
|
489
590
|
|
|
490
591
|
Ready-to-run swarms in [`examples/`](examples/):
|
|
491
592
|
|
|
@@ -495,6 +596,16 @@ Ready-to-run swarms in [`examples/`](examples/):
|
|
|
495
596
|
| [`software-company.yaml`](examples/software-company.yaml) | Org chart | Six agents across all four CLIs, with a deliberately restricted comms graph |
|
|
496
597
|
| [`bug-hunt.yaml`](examples/bug-hunt.yaml) | Pipeline | `forward_responses_to` chaining reproduce → diagnose → fix → verify, hands-free |
|
|
497
598
|
| [`existing-repo.yaml`](examples/existing-repo.yaml) | Pairing | Two agents in one **existing** checkout, with `create_workdirs: false` |
|
|
599
|
+
| [`red-team.yaml`](examples/red-team.yaml) | Adversarial triad | Attacker vs defender arbitrated by a referee, over one **existing** checkout |
|
|
600
|
+
| [`debate.yaml`](examples/debate.yaml) | Debate + judge | Two advocates argue opposite sides; a judge cross-examines and rules |
|
|
601
|
+
| [`writers-room.yaml`](examples/writers-room.yaml) | Hub + review cycle | An editor driving a writer, fact-checker and critic to a finished article |
|
|
602
|
+
| [`incident-response.yaml`](examples/incident-response.yaml) | Incident hub | A commander coordinating investigator/responder/scribe under time pressure |
|
|
603
|
+
| [`tdd-pingpong.yaml`](examples/tdd-pingpong.yaml) | Tight 2-agent loop | Tester writes one failing test, coder makes it pass, in one shared repo |
|
|
604
|
+
| [`brainstorm.yaml`](examples/brainstorm.yaml) | Diverge + converge | Three angled idea-generators fanning out, then a synthesiser ranks them |
|
|
605
|
+
| [`localization.yaml`](examples/localization.yaml) | Pipeline | Translate → review → back-check, auto-forwarded via `forward_responses_to` |
|
|
606
|
+
| [`multi-language-broadcast.yaml`](examples/multi-language-broadcast.yaml) | Broadcast fan-out | One translator broadcasts a source to N language reviewers; a consolidator compiles and broadcasts back |
|
|
607
|
+
| [`code-review-broadcast.yaml`](examples/code-review-broadcast.yaml) | Broadcast hub | One PR broadcast to specialist reviewers (correctness/security/perf); each replies to the coordinator who synthesizes |
|
|
608
|
+
| [`ping-pong.yaml`](examples/ping-pong.yaml) | Round-robin | Two agents trade a unit of work, each broadcast naming who is up next (distinct from tdd-pingpong's fixed `forward_responses_to`) |
|
|
498
609
|
|
|
499
610
|
```bash
|
|
500
611
|
agentainer validate -c examples/research-swarm.yaml # look before you leap
|
|
@@ -505,7 +616,7 @@ agentainer send --to lead "Research the state of WebGPU compute shaders."
|
|
|
505
616
|
`existing-repo.yaml` intentionally refuses to start until you point `workdir` at
|
|
506
617
|
a repository that exists.
|
|
507
618
|
|
|
508
|
-
## Commands
|
|
619
|
+
## <span id="commands"></span>💻 Commands
|
|
509
620
|
|
|
510
621
|
| Command | Purpose |
|
|
511
622
|
|---|---|
|
|
@@ -526,7 +637,7 @@ a repository that exists.
|
|
|
526
637
|
`agentainer my-swarm.yaml` is shorthand for `agentainer up -c my-swarm.yaml`.
|
|
527
638
|
`-c` and `$SWARM_CONFIG` both select a config; `-c` wins.
|
|
528
639
|
|
|
529
|
-
## Layout
|
|
640
|
+
## <span id="project-layout"></span>📁 Project Layout
|
|
530
641
|
|
|
531
642
|
```
|
|
532
643
|
AgentSwarm/
|
|
@@ -541,19 +652,19 @@ AgentSwarm/
|
|
|
541
652
|
│ ├── config.py # schema, defaults, validation
|
|
542
653
|
│ └── minyaml.py # YAML subset parser, used when PyYAML is absent
|
|
543
654
|
├── tests/validate.sh # full suite: mock agents, no model calls
|
|
544
|
-
├── examples/ # research
|
|
655
|
+
├── examples/ # research, software company, bug hunt, pairing, red team, debate, writers' room, incident, tdd, brainstorm, l10n, multi-language + code-review (broadcast), ping-pong (round-robin)
|
|
545
656
|
└── workspace/ # created by `up`
|
|
546
657
|
├── <agent>/ # one folder per agent
|
|
547
658
|
└── .swarm/
|
|
548
659
|
├── state.json # what `up` started
|
|
549
|
-
|
|
660
|
+
├── sessions.yaml # each agent's conversation id, for `up --resume`
|
|
550
661
|
├── bin/swarm # the `swarm` command agents call
|
|
551
662
|
├── logs/ # <agent>.jsonl + swarm.jsonl
|
|
552
663
|
├── inbox/<agent>/ # archived messages
|
|
553
664
|
└── run/ # watcher pids, hop counters
|
|
554
665
|
```
|
|
555
666
|
|
|
556
|
-
## Tests
|
|
667
|
+
## <span id="tests"></span>✅ Tests
|
|
557
668
|
|
|
558
669
|
```bash
|
|
559
670
|
tests/validate.sh
|
|
@@ -565,7 +676,7 @@ nothing. It covers the awkward cases: the check-and-set race between concurrent
|
|
|
565
676
|
senders, a queued message beating a reply reminder, a subagent's sidechain turn
|
|
566
677
|
being skipped, and a transcript read before Claude has flushed it.
|
|
567
678
|
|
|
568
|
-
## Troubleshooting
|
|
679
|
+
## <span id="troubleshooting"></span>🛠️ Troubleshooting
|
|
569
680
|
|
|
570
681
|
**"could not confirm the text arrived; NOT pressing Enter".** The agent's input
|
|
571
682
|
box never echoed the prompt, so Agentainer refused to submit it. Attach to the
|
|
@@ -585,7 +696,7 @@ other. Raise `max_forward_hops`, or break the cycle in `forward_responses_to`.
|
|
|
585
696
|
**Nothing captured from a claude agent.** Check `<agent-dir>/.claude/settings.json`
|
|
586
697
|
exists and `.swarm/logs/hooks.log` for errors. If the agent also looks busy forever,
|
|
587
698
|
its `type` probably does not match the CLI its `command` runs (see the capture note
|
|
588
|
-
under [Busy agents](#
|
|
699
|
+
under [Busy agents](#subagents-parallel-work-and-busy-agents)).
|
|
589
700
|
|
|
590
701
|
**Can't scroll up in an attached session.** Agentainer raises tmux's scrollback to
|
|
591
702
|
`tmux_history_limit` (50000 lines) and turns on `tmux_mouse`, so the wheel scrolls
|
|
@@ -594,10 +705,22 @@ use `Ctrl-b [` then PageUp. Both options are set on the tmux server before sessi
|
|
|
594
705
|
are created, so a server that was already running keeps its old panes' smaller
|
|
595
706
|
buffer — restart the swarm (or that pane) to pick up the larger one.
|
|
596
707
|
|
|
597
|
-
##
|
|
708
|
+
## <span id="a-note-on-flags"></span>⚠️ A Note On Flags
|
|
598
709
|
|
|
599
710
|
`claude --dangerously-skip-permissions`, `codex --yolo` and `gemini --yolo` let
|
|
600
711
|
agents act without asking for confirmation. That is usually what you want for an
|
|
601
712
|
unattended swarm, and it means several models are running tools unsupervised in
|
|
602
713
|
these directories. Point `root` somewhere disposable, and don't run a swarm over
|
|
603
714
|
a directory you can't afford to lose.
|
|
715
|
+
|
|
716
|
+
---
|
|
717
|
+
|
|
718
|
+
## 🤝 Contributing
|
|
719
|
+
|
|
720
|
+
Pull requests and issues are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for
|
|
721
|
+
the zero-dependency principles, a key-free smoke test, and the PR checklist. A
|
|
722
|
+
safe first run with no API keys lives in [quickstart.yaml](quickstart.yaml).
|
|
723
|
+
|
|
724
|
+
## 📜 License
|
|
725
|
+
|
|
726
|
+
Released under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Brainstorm -- diverge into many ideas, then converge on a few worth doing.
|
|
3
|
+
#
|
|
4
|
+
# agentainer up -c examples/brainstorm.yaml
|
|
5
|
+
# agentainer send --to facilitator "Ways to cut our cloud bill by 30%."
|
|
6
|
+
#
|
|
7
|
+
# Shape: fan-out then funnel. A FACILITATOR poses the prompt to three idea
|
|
8
|
+
# generators who each riff from a different angle and never see each other's
|
|
9
|
+
# lists (so they don't converge too early), then hands the pile to a SYNTHESISER
|
|
10
|
+
# who clusters, de-dupes and ranks. The generators talk only to the facilitator.
|
|
11
|
+
#
|
|
12
|
+
# wildcard pragmatist contrarian
|
|
13
|
+
# \ | /
|
|
14
|
+
# `----- facilitator -----'
|
|
15
|
+
# |
|
|
16
|
+
# synthesiser
|
|
17
|
+
#
|
|
18
|
+
# Every link is two-way (the facilitator prompts each generator and they
|
|
19
|
+
# answer back). Ideas diverge across the three generators, then converge
|
|
20
|
+
# through the facilitator to the synthesiser.
|
|
21
|
+
#
|
|
22
|
+
# Deliberately divergent roles keep the three from producing the same list three
|
|
23
|
+
# times. This swarm creates its own folders under `root` -- no repo needed.
|
|
24
|
+
# =============================================================================
|
|
25
|
+
|
|
26
|
+
swarm:
|
|
27
|
+
name: brainstorm
|
|
28
|
+
root: ./brainstorm-workspace
|
|
29
|
+
session_prefix: "bs-"
|
|
30
|
+
|
|
31
|
+
# Fan-out then one funnel step: a single hop is enough.
|
|
32
|
+
max_forward_hops: 1
|
|
33
|
+
|
|
34
|
+
defaults:
|
|
35
|
+
type: claude
|
|
36
|
+
|
|
37
|
+
agents:
|
|
38
|
+
|
|
39
|
+
- name: facilitator
|
|
40
|
+
type: claude
|
|
41
|
+
command: "claude --dangerously-skip-permissions --model opus"
|
|
42
|
+
can_talk_to: ["wildcard", "pragmatist", "contrarian", "synthesiser"]
|
|
43
|
+
|
|
44
|
+
# Waits for the human to supply the actual prompt.
|
|
45
|
+
in_first_prompt_append_your_task_will_be_sent_in_the_next_prompt: true
|
|
46
|
+
|
|
47
|
+
first_prompt: |
|
|
48
|
+
You are the FACILITATOR. You run a divergent-then-convergent session.
|
|
49
|
+
|
|
50
|
+
You do not generate ideas or judge them yourself. You frame the prompt,
|
|
51
|
+
keep the three generators pulling in different directions, then hand the
|
|
52
|
+
raw pile to the synthesiser and relay the result.
|
|
53
|
+
|
|
54
|
+
Your room:
|
|
55
|
+
- wildcard: unconstrained, ambitious, "what if budget were no object"
|
|
56
|
+
- pragmatist: ships this quarter with what we already have
|
|
57
|
+
- contrarian: attacks the framing and the obvious answers
|
|
58
|
+
- synthesiser: clusters, de-dupes and ranks everything at the end
|
|
59
|
+
|
|
60
|
+
How to run it:
|
|
61
|
+
1. Sharpen the human's prompt into one clear question with a success
|
|
62
|
+
metric. Send it to all three generators, and tell each to lean fully
|
|
63
|
+
into ITS angle -- no self-censoring, no converging yet.
|
|
64
|
+
2. Do NOT show generators each other's ideas mid-round; that collapses
|
|
65
|
+
the diversity you are paying for.
|
|
66
|
+
3. When all three have reported, forward the combined, unedited list to
|
|
67
|
+
the synthesiser.
|
|
68
|
+
4. Relay the synthesiser's ranked shortlist to the human, with the one
|
|
69
|
+
bold idea and the one safe idea called out.
|
|
70
|
+
|
|
71
|
+
In the diverge phase, quantity and range beat quality. Save judgement for
|
|
72
|
+
the synthesiser.
|
|
73
|
+
|
|
74
|
+
- name: wildcard
|
|
75
|
+
type: claude
|
|
76
|
+
command: "claude --dangerously-skip-permissions"
|
|
77
|
+
can_talk_to: ["facilitator"]
|
|
78
|
+
|
|
79
|
+
first_prompt: |
|
|
80
|
+
You are the WILDCARD. Your job is range and ambition, not feasibility.
|
|
81
|
+
|
|
82
|
+
Given the question, produce 8-12 genuinely different ideas, including ones
|
|
83
|
+
that sound expensive, weird, or premature. Assume constraints can be
|
|
84
|
+
renegotiated. Chase the idea that would matter most if it worked.
|
|
85
|
+
|
|
86
|
+
For each: a one-line pitch and the single reason it could be a big deal.
|
|
87
|
+
Do not filter for practicality -- the pragmatist and synthesiser do that.
|
|
88
|
+
Avoid the obvious answer everyone already thought of; go past it.
|
|
89
|
+
|
|
90
|
+
- name: pragmatist
|
|
91
|
+
type: codex
|
|
92
|
+
command: "codex --yolo"
|
|
93
|
+
can_talk_to: ["facilitator"]
|
|
94
|
+
|
|
95
|
+
first_prompt: |
|
|
96
|
+
You are the PRAGMATIST. Your job is ideas that ship soon, cheaply.
|
|
97
|
+
|
|
98
|
+
Given the question, produce 8-12 ideas that a small team could start this
|
|
99
|
+
quarter with tools it already has. Favour reversible, low-risk moves with a
|
|
100
|
+
clear owner and a visible payoff.
|
|
101
|
+
|
|
102
|
+
For each: a one-line pitch, the rough effort, and the expected payoff. Bias
|
|
103
|
+
toward things measurable within a few weeks. Leave the moonshots to the
|
|
104
|
+
wildcard; you own "what can we actually do on Monday".
|
|
105
|
+
|
|
106
|
+
- name: contrarian
|
|
107
|
+
type: claude
|
|
108
|
+
command: "claude --dangerously-skip-permissions"
|
|
109
|
+
can_talk_to: ["facilitator"]
|
|
110
|
+
|
|
111
|
+
first_prompt: |
|
|
112
|
+
You are the CONTRARIAN. You attack the question and the easy answers.
|
|
113
|
+
|
|
114
|
+
First, challenge the framing: is the stated goal the real goal? Is the
|
|
115
|
+
metric measuring the right thing? Name the assumption everyone is making.
|
|
116
|
+
|
|
117
|
+
Then produce 6-10 ideas that come from rejecting the obvious approach:
|
|
118
|
+
do the opposite, remove the thing instead of optimising it, or solve the
|
|
119
|
+
problem one level up so it disappears.
|
|
120
|
+
|
|
121
|
+
For each: the conventional answer you are rejecting, and your alternative.
|
|
122
|
+
Be provocative but honest -- the goal is better options, not just dissent.
|
|
123
|
+
|
|
124
|
+
- name: synthesiser
|
|
125
|
+
type: claude
|
|
126
|
+
command: "claude --dangerously-skip-permissions"
|
|
127
|
+
can_talk_to: ["facilitator"]
|
|
128
|
+
|
|
129
|
+
# The shortlist lands somewhere predictable.
|
|
130
|
+
workdir: ./brainstorm-output
|
|
131
|
+
|
|
132
|
+
first_prompt: |
|
|
133
|
+
You are the SYNTHESISER. You turn a messy pile of ideas into a decision.
|
|
134
|
+
|
|
135
|
+
You receive every idea from all three generators. Write the result to
|
|
136
|
+
SHORTLIST.md.
|
|
137
|
+
|
|
138
|
+
Do this:
|
|
139
|
+
1. Cluster near-duplicates into single themes; note where two angles
|
|
140
|
+
independently converged (that is a signal).
|
|
141
|
+
2. Score each theme on impact vs effort. Be explicit about the criteria.
|
|
142
|
+
3. Produce a ranked shortlist of 3-5 things worth doing, each with why it
|
|
143
|
+
made the cut and the first concrete step.
|
|
144
|
+
4. Call out the single boldest bet and the single safest quick win, and
|
|
145
|
+
name any idea that is a trap (looks great, fails in practice).
|
|
146
|
+
|
|
147
|
+
Do not just list everything back. The value you add is cutting.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Code review by broadcast -- one PR, several specialist lenses at once.
|
|
3
|
+
#
|
|
4
|
+
# 1. agentainer validate -c examples/code-review-broadcast.yaml
|
|
5
|
+
# 2. agentainer up -c examples/code-review-broadcast.yaml
|
|
6
|
+
# 3. agentainer send --to coordinator "Review PR #42 (git diff main...HEAD)."
|
|
7
|
+
#
|
|
8
|
+
# Shape: a hub built on `broadcast`. The COORDINATOR fans the diff out to
|
|
9
|
+
# every reviewer in one message; each REVIEWER owns one concern (correctness,
|
|
10
|
+
# security, performance) and reports back to the coordinator, who synthesizes a
|
|
11
|
+
# single review. The reviewers never talk to each other -- cross-cutting findings
|
|
12
|
+
# are the coordinator's job to merge.
|
|
13
|
+
#
|
|
14
|
+
# coordinator
|
|
15
|
+
# | (broadcast the PR to all)
|
|
16
|
+
# v
|
|
17
|
+
# +-------+--------+
|
|
18
|
+
# | | |
|
|
19
|
+
# correctness security perf
|
|
20
|
+
# | | |
|
|
21
|
+
# +--- coordinator ---+ (each reviewer replies to the coordinator)
|
|
22
|
+
#
|
|
23
|
+
# `broadcast` is the point of the example: the coordinator reaches several
|
|
24
|
+
# peers with one message and does not care which are mid-task. Every link is
|
|
25
|
+
# two-way. The change under review is passed in the prompt, so the swarm
|
|
26
|
+
# validates and runs without pointing at any repo.
|
|
27
|
+
# =============================================================================
|
|
28
|
+
|
|
29
|
+
swarm:
|
|
30
|
+
name: review
|
|
31
|
+
root: ./review-runtime # only holds logs, inboxes and swarm state
|
|
32
|
+
session_prefix: "rv-"
|
|
33
|
+
|
|
34
|
+
# Broadcasts don't auto-forward, so one hop is all the guard ever needs.
|
|
35
|
+
max_forward_hops: 1
|
|
36
|
+
|
|
37
|
+
# Each agent gets its own scratch folder under `root` for logs and state.
|
|
38
|
+
# The change under review is passed in the prompt (a `git diff`), so the agents
|
|
39
|
+
# never need to read a repo off disk -- point `workdir` here only if you want
|
|
40
|
+
# them to read the tree directly.
|
|
41
|
+
create_workdirs: true
|
|
42
|
+
|
|
43
|
+
agents:
|
|
44
|
+
|
|
45
|
+
- name: coordinator
|
|
46
|
+
type: claude
|
|
47
|
+
command: "claude --dangerously-skip-permissions --model opus"
|
|
48
|
+
can_talk_to: ["correctness", "security", "perf"]
|
|
49
|
+
|
|
50
|
+
in_first_prompt_append_your_task_will_be_sent_in_the_next_prompt: true
|
|
51
|
+
|
|
52
|
+
first_prompt: |
|
|
53
|
+
You are the REVIEW COORDINATOR. You do not review code yourself; you run
|
|
54
|
+
the review and merge the findings.
|
|
55
|
+
|
|
56
|
+
When the human gives you a change (a PR or a `git diff`), broadcast it to
|
|
57
|
+
every reviewer at once, each with the one concern they own:
|
|
58
|
+
|
|
59
|
+
<swarm-broadcast>
|
|
60
|
+
Review this change (PR #42, git diff main...HEAD):
|
|
61
|
+
- correctness: does it do what it claims? logic, edge cases, regressions
|
|
62
|
+
- security: injection, authz, secrets, unsafe deserialization
|
|
63
|
+
- perf: hot paths, N+1s, allocations, unbounded growth
|
|
64
|
+
Reply to me (the coordinator) with findings only for your lane.
|
|
65
|
+
</swarm-broadcast>
|
|
66
|
+
|
|
67
|
+
Collect the three replies. Merge overlapping findings, dedupe, and rank by
|
|
68
|
+
severity. Produce ONE consolidated review: a short verdict (Approve / Request
|
|
69
|
+
changes) followed by a bullet list of findings with file:line and the lane
|
|
70
|
+
that raised each. Do not invent findings the reviewers did not make.
|
|
71
|
+
|
|
72
|
+
- name: correctness
|
|
73
|
+
type: claude
|
|
74
|
+
command: "claude --dangerously-skip-permissions"
|
|
75
|
+
can_talk_to: ["coordinator"]
|
|
76
|
+
first_prompt: |
|
|
77
|
+
You are the CORRECTNESS reviewer. You receive a change broadcast by the
|
|
78
|
+
coordinator; review ONLY whether it does what it claims.
|
|
79
|
+
|
|
80
|
+
Look for: logic errors, off-by-one and boundary mistakes, wrong types or
|
|
81
|
+
null handling, missing or wrong edge-case handling, and silent regressions
|
|
82
|
+
in behaviour. Quote the offending line. When done, reply to the coordinator
|
|
83
|
+
with findings for this lane only -- nothing about security or performance.
|
|
84
|
+
|
|
85
|
+
- name: security
|
|
86
|
+
type: claude
|
|
87
|
+
command: "claude --dangerously-skip-permissions"
|
|
88
|
+
can_talk_to: ["coordinator"]
|
|
89
|
+
first_prompt: |
|
|
90
|
+
You are the SECURITY reviewer. You receive a change broadcast by the
|
|
91
|
+
coordinator; review ONLY for security risk.
|
|
92
|
+
|
|
93
|
+
Look for: injection (SQL/command/HTML), broken or missing authz, secrets
|
|
94
|
+
committed or logged, unsafe deserialization, path traversal, and trust of
|
|
95
|
+
unvalidated input. Quote the offending line and the abuse scenario. When done,
|
|
96
|
+
reply to the coordinator with findings for this lane only.
|
|
97
|
+
|
|
98
|
+
- name: perf
|
|
99
|
+
type: codex
|
|
100
|
+
command: "codex --yolo"
|
|
101
|
+
can_talk_to: ["coordinator"]
|
|
102
|
+
first_prompt: |
|
|
103
|
+
You are the PERFORMANCE reviewer. You receive a change broadcast by the
|
|
104
|
+
coordinator; review ONLY for performance.
|
|
105
|
+
|
|
106
|
+
Look for: accidental O(n^2) or N+1 patterns, allocations in hot loops,
|
|
107
|
+
unbounded growth (caches, lists), missing batching or indexes, and blocking
|
|
108
|
+
calls on the request path. Quote the offending line and the expected cost.
|
|
109
|
+
When done, reply to the coordinator with findings for this lane only.
|