agentainer 0.1.0
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/README.md +603 -0
- package/agents.example.yaml +257 -0
- package/bin/agentainer.js +74 -0
- package/examples/bug-hunt.yaml +112 -0
- package/examples/existing-repo.yaml +72 -0
- package/examples/research-swarm.yaml +120 -0
- package/examples/software-company.yaml +152 -0
- package/hooks/claude_stop.sh +17 -0
- package/hooks/codex_notify.sh +16 -0
- package/lib/config.py +641 -0
- package/lib/minyaml.py +376 -0
- package/lib/swarm.py +2277 -0
- package/llms.txt +405 -0
- package/package.json +52 -0
- package/scripts/check-deps.js +76 -0
- package/swarm.sh +43 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# AgentSwarm example configuration
|
|
3
|
+
#
|
|
4
|
+
# cp agents.example.yaml agents.yaml
|
|
5
|
+
# ./swarm.sh validate --show-prompts # check it without launching anything
|
|
6
|
+
# ./swarm.sh up # launch the swarm
|
|
7
|
+
#
|
|
8
|
+
# Every key is documented inline. Anything marked (optional) can be omitted.
|
|
9
|
+
# =============================================================================
|
|
10
|
+
|
|
11
|
+
swarm:
|
|
12
|
+
name: dev-swarm
|
|
13
|
+
|
|
14
|
+
# Where agent working directories are created. One folder per agent, named
|
|
15
|
+
# after the agent. Relative paths resolve against this file's directory.
|
|
16
|
+
root: ./workspace
|
|
17
|
+
|
|
18
|
+
# (optional) Create missing agent folders automatically. Default true.
|
|
19
|
+
# Set to false to point agents at directories that must already exist, so a
|
|
20
|
+
# typo in a path fails loudly instead of silently creating an empty folder.
|
|
21
|
+
create_workdirs: true
|
|
22
|
+
|
|
23
|
+
# (optional) Prefix for tmux session names. With `swarm-`, the agent named
|
|
24
|
+
# `developer` lives in the tmux session `swarm-developer`.
|
|
25
|
+
session_prefix: ""
|
|
26
|
+
|
|
27
|
+
# (optional) Timing knobs, all in milliseconds.
|
|
28
|
+
send_delay_ms: 150 # pause before pasting text into a pane
|
|
29
|
+
enter_delay_ms: 250 # pause between pasting text and pressing Enter
|
|
30
|
+
max_forward_hops: 3 # stops auto-forward loops (A -> B -> A -> ...)
|
|
31
|
+
|
|
32
|
+
# (optional) How long to keep probing an agent's input box for a response
|
|
33
|
+
# before giving up and typing the first prompt anyway. Some CLIs (Claude Code)
|
|
34
|
+
# silently discard keystrokes for several seconds partway through startup, so
|
|
35
|
+
# AgentSwarm waits for the input box to echo a throwaway token before typing.
|
|
36
|
+
ready_timeout_ms: 60000
|
|
37
|
+
|
|
38
|
+
# (optional) An agent is "busy" from when a message is submitted to it until its
|
|
39
|
+
# next captured turn end; senders are refused meanwhile and told to --queue or
|
|
40
|
+
# --wait. If a capture never fires (crashed CLI, bad hook) the agent would look
|
|
41
|
+
# busy forever, so after this long it is treated as idle again, with a warning.
|
|
42
|
+
busy_timeout_ms: 900000
|
|
43
|
+
|
|
44
|
+
# (optional) How messages look on the wire.
|
|
45
|
+
# tagged -- messages arrive inside <swarm-message from=".." id=".."> ... </swarm-message>,
|
|
46
|
+
# and an agent sends one by writing <swarm-send to="..."> ... </swarm-send>
|
|
47
|
+
# in its reply. No shell quoting, so multi-line bodies survive intact.
|
|
48
|
+
# plain -- the older "[swarm] message from <sender>:" header.
|
|
49
|
+
message_format: tagged
|
|
50
|
+
|
|
51
|
+
# (optional) An agent that answers a question as plain prose sends nothing: only a
|
|
52
|
+
# <swarm-send> block is delivered. When it owes a reply and its turn ends without
|
|
53
|
+
# one, AgentSwarm messages it explaining how to send. This is how many times.
|
|
54
|
+
max_reply_reminders: 1
|
|
55
|
+
|
|
56
|
+
# (optional) Reattach agents to their previous conversations on `up`, using the ids
|
|
57
|
+
# recorded in <root>/.swarm/sessions.yaml. Same as passing `up --resume` every time.
|
|
58
|
+
# Useful after a reboot. `up --no-resume` overrides it.
|
|
59
|
+
resume: false
|
|
60
|
+
|
|
61
|
+
# (optional) Only used by agents with `capture: pane` (gemini, hermes).
|
|
62
|
+
pane_idle_ms: 2500 # pane must be unchanged this long to count as "done"
|
|
63
|
+
pane_poll_ms: 700 # how often the watcher samples the pane
|
|
64
|
+
pane_scrollback: 400 # lines of scrollback to diff
|
|
65
|
+
|
|
66
|
+
# (optional) tmux comfort settings for when you `swarm attach <agent>`.
|
|
67
|
+
# The default tmux scrollback (2000 lines) is too small to hold a long
|
|
68
|
+
# multi-agent conversation, so AgentSwarm raises it before creating sessions.
|
|
69
|
+
# mouse mode lets you wheel-scroll the backlog; press q to leave copy mode.
|
|
70
|
+
# Both are applied to the tmux server, so they also affect your other sessions.
|
|
71
|
+
tmux_history_limit: 50000 # lines of scrollback per agent pane (0 = leave tmux's default)
|
|
72
|
+
tmux_mouse: true # enable mouse wheel scrolling in the panes
|
|
73
|
+
|
|
74
|
+
# -----------------------------------------------------------------------------
|
|
75
|
+
# defaults (optional) -- applied to every agent that does not override them.
|
|
76
|
+
# -----------------------------------------------------------------------------
|
|
77
|
+
defaults:
|
|
78
|
+
type: claude
|
|
79
|
+
append_agents_that_you_can_talk_to_prompt: true
|
|
80
|
+
in_first_prompt_append_your_task_will_be_sent_in_the_next_prompt: false
|
|
81
|
+
env:
|
|
82
|
+
SWARM_DEMO: "1"
|
|
83
|
+
|
|
84
|
+
# -----------------------------------------------------------------------------
|
|
85
|
+
# agent_types (optional) -- override the built-in launch commands, or define
|
|
86
|
+
# entirely new agent types. Built-ins are: claude, codex, gemini, hermes.
|
|
87
|
+
#
|
|
88
|
+
# capture: how AgentSwarm learns that an agent finished a turn.
|
|
89
|
+
# hook -- the CLI can run an external program on turn completion.
|
|
90
|
+
# Supported for claude (Stop hook) and codex (notify program).
|
|
91
|
+
# pane -- no such facility: poll the tmux pane and diff it. Heuristic.
|
|
92
|
+
# none -- do not capture at all.
|
|
93
|
+
#
|
|
94
|
+
# boot_delay_ms: a grace period before AgentSwarm starts probing the input
|
|
95
|
+
# box. It does NOT need to cover the full startup time -- delivery of the
|
|
96
|
+
# first prompt is verified and retried, so a small value is fine.
|
|
97
|
+
# -----------------------------------------------------------------------------
|
|
98
|
+
agent_types:
|
|
99
|
+
claude:
|
|
100
|
+
command: "claude --dangerously-skip-permissions"
|
|
101
|
+
capture: hook
|
|
102
|
+
boot_delay_ms: 3000
|
|
103
|
+
codex:
|
|
104
|
+
command: "codex --yolo"
|
|
105
|
+
capture: hook
|
|
106
|
+
boot_delay_ms: 3000
|
|
107
|
+
gemini:
|
|
108
|
+
command: "gemini --yolo"
|
|
109
|
+
capture: pane
|
|
110
|
+
boot_delay_ms: 4000
|
|
111
|
+
hermes:
|
|
112
|
+
command: "hermes"
|
|
113
|
+
capture: pane
|
|
114
|
+
boot_delay_ms: 3000
|
|
115
|
+
|
|
116
|
+
# -----------------------------------------------------------------------------
|
|
117
|
+
# agents -- one tmux session and one directory each.
|
|
118
|
+
# -----------------------------------------------------------------------------
|
|
119
|
+
agents:
|
|
120
|
+
|
|
121
|
+
- name: orchestrator
|
|
122
|
+
type: claude
|
|
123
|
+
# (optional) Override the type's command, e.g. to pin a model.
|
|
124
|
+
command: "claude --dangerously-skip-permissions --model opus"
|
|
125
|
+
|
|
126
|
+
# Who this agent is allowed to message. Use "*" for "everyone else".
|
|
127
|
+
# An agent that tries to message anyone not listed here is refused.
|
|
128
|
+
can_talk_to: ["researcher", "developer", "reviewer"]
|
|
129
|
+
|
|
130
|
+
first_prompt: |
|
|
131
|
+
You are the ORCHESTRATOR of a small software team.
|
|
132
|
+
|
|
133
|
+
Your job is to break the user's goal into concrete pieces of work, hand
|
|
134
|
+
each piece to the right specialist, and assemble their answers into a
|
|
135
|
+
final result. You do not write production code yourself.
|
|
136
|
+
|
|
137
|
+
Team:
|
|
138
|
+
- researcher: investigates prior art, APIs and docs
|
|
139
|
+
- developer: writes the implementation
|
|
140
|
+
- reviewer: critiques diffs and finds bugs
|
|
141
|
+
|
|
142
|
+
Start by asking the researcher what they can find, then brief the developer.
|
|
143
|
+
|
|
144
|
+
# This agent is told its task arrives in a follow-up prompt, so it will
|
|
145
|
+
# acknowledge and wait rather than inventing work.
|
|
146
|
+
in_first_prompt_append_your_task_will_be_sent_in_the_next_prompt: true
|
|
147
|
+
|
|
148
|
+
- name: researcher
|
|
149
|
+
type: gemini
|
|
150
|
+
command: "gemini --yolo"
|
|
151
|
+
can_talk_to: ["orchestrator", "developer"]
|
|
152
|
+
|
|
153
|
+
# Whenever this agent finishes a turn, its final message is automatically
|
|
154
|
+
# relayed to these agents. Every name here must also be in can_talk_to.
|
|
155
|
+
# Leave it out (the default) to let the agent decide when to speak.
|
|
156
|
+
forward_responses_to: ["orchestrator"]
|
|
157
|
+
|
|
158
|
+
first_prompt: |
|
|
159
|
+
You are the RESEARCHER. You investigate libraries, APIs, prior art and
|
|
160
|
+
documentation, then report findings concisely with sources.
|
|
161
|
+
|
|
162
|
+
You never write production code. When you have an answer, state it plainly:
|
|
163
|
+
what exists, what it costs, and what you recommend.
|
|
164
|
+
|
|
165
|
+
- name: developer
|
|
166
|
+
type: codex
|
|
167
|
+
command: "codex --yolo"
|
|
168
|
+
can_talk_to: ["orchestrator", "reviewer"]
|
|
169
|
+
|
|
170
|
+
# (optional) Per-agent environment variables, exported into its tmux session.
|
|
171
|
+
env:
|
|
172
|
+
GIT_AUTHOR_NAME: "swarm-developer"
|
|
173
|
+
|
|
174
|
+
# (optional) Before typing the first prompt, type a throwaway token and wait
|
|
175
|
+
# for the input box to echo it back. Defaults to true; turn it off only for
|
|
176
|
+
# a command that is not an interactive TUI.
|
|
177
|
+
ready_probe: true
|
|
178
|
+
|
|
179
|
+
# (optional) Refuse incoming messages while this agent is mid-turn, so a second
|
|
180
|
+
# agent is told "developer is busy, --queue it or --wait" instead of interrupting.
|
|
181
|
+
# Needs a capture to know when a turn ends; forced off when capture: none.
|
|
182
|
+
busy_check: true
|
|
183
|
+
|
|
184
|
+
# (optional) Read <swarm-send> blocks out of this agent's replies and deliver
|
|
185
|
+
# them. Needs a capture; forced off when capture: none or message_format: plain.
|
|
186
|
+
parse_outbound_tags: true
|
|
187
|
+
|
|
188
|
+
# (optional) Nudge this agent when it owes a reply but sent nothing, or when the
|
|
189
|
+
# block it wrote could not be delivered. Off when its tags are not parsed.
|
|
190
|
+
reply_reminder: true
|
|
191
|
+
|
|
192
|
+
# (optional) How to reattach this agent to a previous conversation. `resume_args`
|
|
193
|
+
# is appended to `command`; `resume_command` replaces it outright, which you need
|
|
194
|
+
# when the command goes through an alias or wrapper. {session_id} is substituted.
|
|
195
|
+
#
|
|
196
|
+
# resume_args: "resume {session_id}" # -> codex --yolo resume <id>
|
|
197
|
+
# resume_command: "bash -ic 'mywrapper --resume {session_id}'"
|
|
198
|
+
|
|
199
|
+
first_prompt: |
|
|
200
|
+
You are the DEVELOPER. You implement what the orchestrator asks for, in
|
|
201
|
+
the working directory you were started in.
|
|
202
|
+
|
|
203
|
+
Write real, runnable code. When you finish a unit of work, send the
|
|
204
|
+
reviewer a short summary of what you changed and why, and ask for review.
|
|
205
|
+
|
|
206
|
+
- name: reviewer
|
|
207
|
+
type: claude
|
|
208
|
+
command: "claude --dangerously-skip-permissions"
|
|
209
|
+
can_talk_to: ["developer", "orchestrator"]
|
|
210
|
+
|
|
211
|
+
# (optional) Run this agent somewhere specific instead of <root>/<name>.
|
|
212
|
+
# Relative paths resolve against this file. `~` is expanded. The
|
|
213
|
+
# placeholders {name}, {root}, {swarm} and {type} are substituted, so a
|
|
214
|
+
# single `defaults.workdir` can serve every agent, e.g. "{root}/{name}-wt".
|
|
215
|
+
#
|
|
216
|
+
# Several agents may share one directory (they then see each other's edits;
|
|
217
|
+
# AgentSwarm warns you). Pair `create_workdir: false` with an existing
|
|
218
|
+
# project so a bad path is an error, not a new empty folder.
|
|
219
|
+
#
|
|
220
|
+
# workdir: ~/projects/acme-api
|
|
221
|
+
# create_workdir: false
|
|
222
|
+
|
|
223
|
+
# (optional) Read the prompt from a file instead of inlining it here.
|
|
224
|
+
# first_prompt_file: ./prompts/reviewer.md
|
|
225
|
+
first_prompt: |
|
|
226
|
+
You are the REVIEWER. You read the developer's changes and hunt for real
|
|
227
|
+
bugs: wrong logic, unhandled errors, race conditions, security problems.
|
|
228
|
+
|
|
229
|
+
Be specific and cite file:line. If a change is fine, say so briefly rather
|
|
230
|
+
than inventing nitpicks. Report your verdict back to the developer.
|
|
231
|
+
|
|
232
|
+
- name: scribe
|
|
233
|
+
type: hermes
|
|
234
|
+
command: "hermes"
|
|
235
|
+
|
|
236
|
+
# This agent listens only: nobody can be messaged by it, and its own
|
|
237
|
+
# responses are not captured.
|
|
238
|
+
can_talk_to: []
|
|
239
|
+
capture: none
|
|
240
|
+
|
|
241
|
+
# Turn off the auto-appended communication block, since it has no peers.
|
|
242
|
+
append_agents_that_you_can_talk_to_prompt: false
|
|
243
|
+
|
|
244
|
+
first_prompt: |
|
|
245
|
+
You are the SCRIBE. Keep a running changelog of the project in NOTES.md.
|
|
246
|
+
|
|
247
|
+
# -----------------------------------------------------------------------------
|
|
248
|
+
# templates (optional) -- override the text AgentSwarm appends to first prompts.
|
|
249
|
+
# Available placeholders: {agent} {swarm} {peers} {prefix} {inbox} {workdir}
|
|
250
|
+
# -----------------------------------------------------------------------------
|
|
251
|
+
#
|
|
252
|
+
# templates:
|
|
253
|
+
# comms: |
|
|
254
|
+
# You are {agent}. You may message: {peers}.
|
|
255
|
+
# Send with: swarm send --to <agent> "message"
|
|
256
|
+
# task_notice: |
|
|
257
|
+
# Stand by. Your real task arrives in the next message.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Agentainer -- global CLI launcher.
|
|
3
|
+
//
|
|
4
|
+
// npm symlinks this file into a bin directory (e.g. /usr/local/bin/agentainer).
|
|
5
|
+
// Node resolves that symlink before setting __dirname, so __dirname always
|
|
6
|
+
// points at the real bin/ inside the installed package -- which makes the
|
|
7
|
+
// package root, and therefore SWARM_HOME, reliable no matter where npm puts us.
|
|
8
|
+
"use strict";
|
|
9
|
+
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const { spawnSync } = require("child_process");
|
|
12
|
+
|
|
13
|
+
const PKG_ROOT = path.resolve(__dirname, "..");
|
|
14
|
+
const ENTRY = path.join(PKG_ROOT, "lib", "swarm.py");
|
|
15
|
+
|
|
16
|
+
// `agentainer doctor` re-runs the dependency check without touching Python.
|
|
17
|
+
if (process.argv[2] === "doctor") {
|
|
18
|
+
const r = spawnSync(process.execPath, [path.join(PKG_ROOT, "scripts", "check-deps.js")], {
|
|
19
|
+
stdio: "inherit",
|
|
20
|
+
});
|
|
21
|
+
process.exit(r.status === null ? 1 : r.status);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Locate a Python interpreter, mirroring swarm.sh (SWARM_PYTHON, then python3,
|
|
25
|
+
// then python).
|
|
26
|
+
function findPython() {
|
|
27
|
+
const candidates = process.env.SWARM_PYTHON
|
|
28
|
+
? [process.env.SWARM_PYTHON]
|
|
29
|
+
: ["python3", "python"];
|
|
30
|
+
for (const cand of candidates) {
|
|
31
|
+
const probe = spawnSync(cand, ["--version"], { stdio: "ignore" });
|
|
32
|
+
if (!probe.error && probe.status === 0) return cand;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function has(cmd, args) {
|
|
38
|
+
const probe = spawnSync(cmd, args, { stdio: "ignore" });
|
|
39
|
+
return !probe.error && probe.status === 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const python = findPython();
|
|
43
|
+
if (!python) {
|
|
44
|
+
process.stderr.write(
|
|
45
|
+
"xx Agentainer needs python3 on PATH (or set SWARM_PYTHON).\n" +
|
|
46
|
+
" Run `agentainer doctor` for install hints.\n"
|
|
47
|
+
);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// tmux is required for everything except `validate`; warn but don't block, so
|
|
52
|
+
// `agentainer validate` and `agentainer doctor` still work without it.
|
|
53
|
+
if (!has("tmux", ["-V"])) {
|
|
54
|
+
process.stderr.write(
|
|
55
|
+
"!! tmux was not found on PATH; every command except 'validate' will fail.\n" +
|
|
56
|
+
" Run `agentainer doctor` for install hints.\n"
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const result = spawnSync(python, [ENTRY, ...process.argv.slice(2)], {
|
|
61
|
+
stdio: "inherit",
|
|
62
|
+
env: { ...process.env, SWARM_HOME: PKG_ROOT },
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (result.error) {
|
|
66
|
+
process.stderr.write(`xx failed to launch Agentainer: ${result.error.message}\n`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
if (result.signal) {
|
|
70
|
+
// Re-raise the signal so the parent shell sees the real cause (e.g. Ctrl-C).
|
|
71
|
+
process.kill(process.pid, result.signal);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Bug hunt -- an automatic pipeline: reproduce -> diagnose -> fix -> verify.
|
|
3
|
+
#
|
|
4
|
+
# ./swarm.sh up -c examples/bug-hunt.yaml
|
|
5
|
+
# ./swarm.sh send --to reproducer "Uploads over 2MB fail with a 500 in prod."
|
|
6
|
+
#
|
|
7
|
+
# This is the one shape where `forward_responses_to` earns its keep: each stage
|
|
8
|
+
# hands its finished turn to the next stage automatically, with no human in the
|
|
9
|
+
# loop. Everything flows one way, so the hop guard never has to save you.
|
|
10
|
+
#
|
|
11
|
+
# reproducer --> diagnoser --> fixer --> verifier
|
|
12
|
+
#
|
|
13
|
+
# Auto-forwarding is chatty by nature. If you want agents to speak only when
|
|
14
|
+
# they have something to say, delete `forward_responses_to` and let them call
|
|
15
|
+
# `swarm send` themselves.
|
|
16
|
+
# =============================================================================
|
|
17
|
+
|
|
18
|
+
swarm:
|
|
19
|
+
name: bughunt
|
|
20
|
+
root: ./bughunt
|
|
21
|
+
session_prefix: "bug-"
|
|
22
|
+
|
|
23
|
+
# A straight line needs exactly as many hops as it has stages.
|
|
24
|
+
max_forward_hops: 4
|
|
25
|
+
|
|
26
|
+
agents:
|
|
27
|
+
|
|
28
|
+
- name: reproducer
|
|
29
|
+
type: codex
|
|
30
|
+
command: "codex --yolo"
|
|
31
|
+
can_talk_to: ["diagnoser"]
|
|
32
|
+
forward_responses_to: ["diagnoser"]
|
|
33
|
+
|
|
34
|
+
first_prompt: |
|
|
35
|
+
You are the REPRODUCER, the first stage of a bug-hunting pipeline.
|
|
36
|
+
|
|
37
|
+
Given a bug report, your only job is to turn it into a deterministic,
|
|
38
|
+
minimal reproduction: a script or test that fails now and would pass if
|
|
39
|
+
the bug were fixed.
|
|
40
|
+
|
|
41
|
+
Report, in this order:
|
|
42
|
+
1. The exact command to reproduce.
|
|
43
|
+
2. The observed output, verbatim.
|
|
44
|
+
3. The expected output.
|
|
45
|
+
4. What you had to assume, because the report did not say.
|
|
46
|
+
|
|
47
|
+
If you cannot reproduce it, say so and explain precisely what you tried.
|
|
48
|
+
Do not attempt a fix -- the next stage does that. Everything you say at
|
|
49
|
+
the end of your turn is forwarded automatically to the diagnoser.
|
|
50
|
+
|
|
51
|
+
- name: diagnoser
|
|
52
|
+
type: claude
|
|
53
|
+
command: "claude --dangerously-skip-permissions --model opus"
|
|
54
|
+
can_talk_to: ["fixer"]
|
|
55
|
+
forward_responses_to: ["fixer"]
|
|
56
|
+
|
|
57
|
+
first_prompt: |
|
|
58
|
+
You are the DIAGNOSER, the second stage of a bug-hunting pipeline.
|
|
59
|
+
|
|
60
|
+
You receive a reproduction. Find the root cause -- the specific line or
|
|
61
|
+
design decision that makes the failure inevitable. Not the symptom, and
|
|
62
|
+
not the first suspicious thing you see.
|
|
63
|
+
|
|
64
|
+
Report:
|
|
65
|
+
1. Root cause, at file:line, in one paragraph.
|
|
66
|
+
2. The causal chain from input to wrong output.
|
|
67
|
+
3. Why it was not caught: the missing test, the wrong assumption.
|
|
68
|
+
4. The smallest correct fix, and one alternative you rejected (say why).
|
|
69
|
+
|
|
70
|
+
Do not write the fix. Describe it. Your turn is forwarded to the fixer.
|
|
71
|
+
|
|
72
|
+
- name: fixer
|
|
73
|
+
type: codex
|
|
74
|
+
command: "codex --yolo"
|
|
75
|
+
can_talk_to: ["verifier"]
|
|
76
|
+
forward_responses_to: ["verifier"]
|
|
77
|
+
|
|
78
|
+
first_prompt: |
|
|
79
|
+
You are the FIXER, the third stage of a bug-hunting pipeline.
|
|
80
|
+
|
|
81
|
+
You receive a diagnosis. Implement the smallest change that fixes the root
|
|
82
|
+
cause, plus a regression test that fails without your change and passes
|
|
83
|
+
with it.
|
|
84
|
+
|
|
85
|
+
Do not refactor surrounding code, rename things, or fix unrelated bugs you
|
|
86
|
+
notice on the way. Mention them instead.
|
|
87
|
+
|
|
88
|
+
Report the diff you made, the test you added, and the test output. Your
|
|
89
|
+
turn is forwarded to the verifier, who does not trust you.
|
|
90
|
+
|
|
91
|
+
- name: verifier
|
|
92
|
+
type: claude
|
|
93
|
+
command: "claude --dangerously-skip-permissions"
|
|
94
|
+
|
|
95
|
+
# End of the line: it forwards to nobody, so the pipeline stops here.
|
|
96
|
+
can_talk_to: []
|
|
97
|
+
append_agents_that_you_can_talk_to_prompt: false
|
|
98
|
+
|
|
99
|
+
first_prompt: |
|
|
100
|
+
You are the VERIFIER, the last stage of a bug-hunting pipeline.
|
|
101
|
+
|
|
102
|
+
You receive a proposed fix. Assume it is wrong until you have checked.
|
|
103
|
+
|
|
104
|
+
Do all of these:
|
|
105
|
+
1. Run the original reproduction. Does it now pass?
|
|
106
|
+
2. Run the whole test suite. Did anything else break?
|
|
107
|
+
3. Read the fix. Does it address the root cause, or only the symptom
|
|
108
|
+
that the reproduction happened to exercise?
|
|
109
|
+
4. Find one input near the boundary of the change that would still
|
|
110
|
+
break. If you find one, the fix is not done.
|
|
111
|
+
|
|
112
|
+
Print a verdict: SHIPPABLE or NOT SHIPPABLE, then the evidence. Be blunt.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Pair programming on a repository you already have.
|
|
3
|
+
#
|
|
4
|
+
# This example does NOT create any folders. Both agents are started inside one
|
|
5
|
+
# existing checkout, so they see each other's edits immediately -- a driver who
|
|
6
|
+
# writes the code and a navigator who reads it as it lands.
|
|
7
|
+
#
|
|
8
|
+
# 1. Point `workdir` below at a real repository.
|
|
9
|
+
# 2. ./swarm.sh validate -c examples/existing-repo.yaml
|
|
10
|
+
# 3. ./swarm.sh up -c examples/existing-repo.yaml
|
|
11
|
+
# 4. ./swarm.sh send --to driver "Add retry-with-backoff to the HTTP client."
|
|
12
|
+
#
|
|
13
|
+
# Until you edit the paths, `validate` will refuse to run and tell you so --
|
|
14
|
+
# that is the point of `create_workdir: false`.
|
|
15
|
+
# =============================================================================
|
|
16
|
+
|
|
17
|
+
swarm:
|
|
18
|
+
name: pair
|
|
19
|
+
root: ./pair-runtime # only holds logs, inboxes and swarm state
|
|
20
|
+
session_prefix: "pair-"
|
|
21
|
+
|
|
22
|
+
# Never silently mkdir a path the user typed. If it does not exist, that is a
|
|
23
|
+
# typo, not an instruction to create it.
|
|
24
|
+
create_workdirs: false
|
|
25
|
+
|
|
26
|
+
defaults:
|
|
27
|
+
# Both agents share one checkout. Every agent inherits this unless it
|
|
28
|
+
# overrides `workdir` itself.
|
|
29
|
+
#
|
|
30
|
+
# >>> EDIT ME <<<
|
|
31
|
+
workdir: ~/projects/acme-api
|
|
32
|
+
|
|
33
|
+
agents:
|
|
34
|
+
|
|
35
|
+
- name: driver
|
|
36
|
+
type: claude
|
|
37
|
+
command: "claude --dangerously-skip-permissions"
|
|
38
|
+
can_talk_to: ["navigator"]
|
|
39
|
+
|
|
40
|
+
first_prompt: |
|
|
41
|
+
You are the DRIVER in a pairing session. You have the keyboard.
|
|
42
|
+
|
|
43
|
+
You are working in a real repository that someone cares about. Before you
|
|
44
|
+
change anything, read enough of it to match its conventions.
|
|
45
|
+
|
|
46
|
+
Working agreement:
|
|
47
|
+
- Make one coherent change at a time, then tell the navigator what you
|
|
48
|
+
did and why, so they can review it while you continue.
|
|
49
|
+
- Run the tests before you claim something works. Paste real output.
|
|
50
|
+
- Never commit, push, or rewrite git history unless explicitly asked.
|
|
51
|
+
- If the navigator finds a real bug, fix it before moving on.
|
|
52
|
+
|
|
53
|
+
- name: navigator
|
|
54
|
+
type: codex
|
|
55
|
+
command: "codex --yolo"
|
|
56
|
+
can_talk_to: ["driver"]
|
|
57
|
+
|
|
58
|
+
first_prompt: |
|
|
59
|
+
You are the NAVIGATOR in a pairing session. You do not have the keyboard.
|
|
60
|
+
|
|
61
|
+
You read what the driver writes, in the same working tree, and you think
|
|
62
|
+
one step ahead of them. Do not edit files -- your job is to catch what
|
|
63
|
+
they cannot see while typing.
|
|
64
|
+
|
|
65
|
+
Watch for:
|
|
66
|
+
- logic that is wrong on an edge case the tests do not cover
|
|
67
|
+
- error paths that swallow failures
|
|
68
|
+
- a change that breaks an existing caller elsewhere in the repo
|
|
69
|
+
- drifting away from how the rest of this codebase does things
|
|
70
|
+
|
|
71
|
+
Report findings to the driver, citing file:line, with the concrete input
|
|
72
|
+
that goes wrong. If a change looks correct, say so briefly and move on.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Research swarm -- a small team that investigates a topic and writes it up.
|
|
3
|
+
#
|
|
4
|
+
# ./swarm.sh up -c examples/research-swarm.yaml
|
|
5
|
+
# ./swarm.sh send --to lead "Research the state of WebGPU compute shaders."
|
|
6
|
+
#
|
|
7
|
+
# Shape: hub and spoke. The lead hands out work and assembles the result; the
|
|
8
|
+
# specialists only ever report back to the lead (and to each other where it
|
|
9
|
+
# actually helps). Nobody starts working until the lead briefs them.
|
|
10
|
+
# =============================================================================
|
|
11
|
+
|
|
12
|
+
swarm:
|
|
13
|
+
name: research
|
|
14
|
+
root: ./research-workspace
|
|
15
|
+
session_prefix: "r-"
|
|
16
|
+
|
|
17
|
+
defaults:
|
|
18
|
+
type: claude
|
|
19
|
+
|
|
20
|
+
agents:
|
|
21
|
+
|
|
22
|
+
- name: lead
|
|
23
|
+
type: claude
|
|
24
|
+
command: "bash -ic 'chy3'"
|
|
25
|
+
can_talk_to: ["scout", "analyst", "writer"]
|
|
26
|
+
|
|
27
|
+
# The lead waits for the human to supply the research question.
|
|
28
|
+
in_first_prompt_append_your_task_will_be_sent_in_the_next_prompt: true
|
|
29
|
+
|
|
30
|
+
first_prompt: |
|
|
31
|
+
You are the RESEARCH LEAD.
|
|
32
|
+
|
|
33
|
+
You own the research question end to end. You do not gather sources or
|
|
34
|
+
write prose yourself -- you decompose the question, delegate, challenge
|
|
35
|
+
what comes back, and assemble the final answer.
|
|
36
|
+
|
|
37
|
+
Your team:
|
|
38
|
+
- scout: finds primary sources, docs, papers, prior art
|
|
39
|
+
- analyst: reads code and data, runs experiments, checks claims
|
|
40
|
+
- writer: turns findings into a clear written report
|
|
41
|
+
|
|
42
|
+
How to run the project:
|
|
43
|
+
1. Restate the question and split it into 2-4 concrete sub-questions.
|
|
44
|
+
2. Send each sub-question to the right specialist. Be specific about
|
|
45
|
+
what a good answer looks like and what you do NOT want.
|
|
46
|
+
3. When findings come back, look for disagreements between them. Push
|
|
47
|
+
back on anything asserted without a source or a reproduction.
|
|
48
|
+
4. Once the picture is stable, brief the writer, then review their draft.
|
|
49
|
+
5. Report the final answer to the human, with the key sources.
|
|
50
|
+
|
|
51
|
+
Never accept "it depends" as a final answer. Force a recommendation.
|
|
52
|
+
|
|
53
|
+
- name: scout
|
|
54
|
+
type: claude
|
|
55
|
+
command: "bash -ic 'chy3'"
|
|
56
|
+
can_talk_to: ["lead", "analyst"]
|
|
57
|
+
|
|
58
|
+
# Gemini has no turn-completion hook, so its output would have to be scraped
|
|
59
|
+
# from the terminal. Capturing nothing and letting it message deliberately
|
|
60
|
+
# is far cleaner. See README, "Capturing what an agent says".
|
|
61
|
+
capture: none
|
|
62
|
+
|
|
63
|
+
first_prompt: |
|
|
64
|
+
You are the SCOUT.
|
|
65
|
+
|
|
66
|
+
You find primary sources: official documentation, specifications, papers,
|
|
67
|
+
release notes, and credible prior art. You do not speculate, and you do
|
|
68
|
+
not summarise from memory -- if you did not open it, you do not cite it.
|
|
69
|
+
|
|
70
|
+
For every finding, report:
|
|
71
|
+
- the claim, in one sentence
|
|
72
|
+
- the source (URL or exact document + section)
|
|
73
|
+
- how current it is, and whether it is authoritative or hearsay
|
|
74
|
+
|
|
75
|
+
Send findings to the lead with:
|
|
76
|
+
swarm send --to lead "..."
|
|
77
|
+
|
|
78
|
+
If a claim needs code or data to verify, hand it to the analyst instead
|
|
79
|
+
of guessing. Say plainly when you could not find something.
|
|
80
|
+
|
|
81
|
+
- name: analyst
|
|
82
|
+
type: claude
|
|
83
|
+
command: "bash -ic 'chy3'"
|
|
84
|
+
can_talk_to: ["lead", "scout"]
|
|
85
|
+
|
|
86
|
+
first_prompt: |
|
|
87
|
+
You are the ANALYST.
|
|
88
|
+
|
|
89
|
+
You verify claims by running things. Given a question, write the smallest
|
|
90
|
+
program, benchmark or query that answers it, run it, and report what you
|
|
91
|
+
actually observed -- not what you expected to observe.
|
|
92
|
+
|
|
93
|
+
Rules:
|
|
94
|
+
- Show the command you ran and the output you got.
|
|
95
|
+
- If a result contradicts the scout's source, say so explicitly and
|
|
96
|
+
message both the scout and the lead.
|
|
97
|
+
- Distinguish "I measured this" from "I reason this is true".
|
|
98
|
+
- A failed experiment is a finding. Report it.
|
|
99
|
+
|
|
100
|
+
Work in your own directory. Keep scratch code; you may be asked to re-run it.
|
|
101
|
+
|
|
102
|
+
- name: writer
|
|
103
|
+
type: claude
|
|
104
|
+
command: "bash -ic 'chy3'"
|
|
105
|
+
can_talk_to: ["lead"]
|
|
106
|
+
|
|
107
|
+
# A custom folder: the report lands somewhere predictable, outside the
|
|
108
|
+
# per-agent scratch directories.
|
|
109
|
+
workdir: ./research-output
|
|
110
|
+
|
|
111
|
+
first_prompt: |
|
|
112
|
+
You are the WRITER.
|
|
113
|
+
|
|
114
|
+
You turn the lead's findings into a report in REPORT.md: an executive
|
|
115
|
+
summary a busy reader can act on, then the evidence, then the open
|
|
116
|
+
questions. Cite every non-obvious claim.
|
|
117
|
+
|
|
118
|
+
Write plainly. No filler, no "in today's fast-paced world", no bulleted
|
|
119
|
+
restatement of the question. If a finding is uncertain, say how uncertain
|
|
120
|
+
and why. When the draft is ready, tell the lead where it is.
|