agentainer 0.1.7 → 2.0.1

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.
Files changed (98) hide show
  1. package/README.md +248 -677
  2. package/agentainer +16 -18
  3. package/agentainer.example.yaml +86 -0
  4. package/bin/agentainer.js +9 -8
  5. package/examples/academic-coauthor.yaml +123 -0
  6. package/examples/accessibility-audit.yaml +152 -0
  7. package/examples/affiliate-product-reviews.yaml +106 -0
  8. package/examples/api-design.yaml +157 -0
  9. package/examples/app-store-optimization.yaml +108 -0
  10. package/examples/brainstorm.yaml +27 -128
  11. package/examples/brand-voice-style-guide.yaml +109 -0
  12. package/examples/bug-hunt.yaml +51 -96
  13. package/examples/candidate-screen.yaml +122 -0
  14. package/examples/case-study-writer.yaml +100 -0
  15. package/examples/changelog-release-notes.yaml +114 -0
  16. package/examples/chatbot-builder.yaml +138 -0
  17. package/examples/code-review.yaml +73 -0
  18. package/examples/comparison-guide-writer.yaml +106 -0
  19. package/examples/competitive-intel.yaml +126 -0
  20. package/examples/content-studio.yaml +91 -0
  21. package/examples/course-creator.yaml +133 -0
  22. package/examples/customer-support-triage.yaml +118 -0
  23. package/examples/daily-briefing.yaml +119 -0
  24. package/examples/data-pipeline-builder.yaml +135 -0
  25. package/examples/debate.yaml +16 -90
  26. package/examples/design-system.yaml +138 -0
  27. package/examples/ebook-generator.yaml +90 -0
  28. package/examples/ecommerce-listing-optimizer.yaml +126 -0
  29. package/examples/email-newsletter.yaml +103 -0
  30. package/examples/faq-knowledge-sync.yaml +107 -0
  31. package/examples/game-design.yaml +122 -0
  32. package/examples/glossary-term-writer.yaml +103 -0
  33. package/examples/incident-response.yaml +52 -109
  34. package/examples/knowledge-base.yaml +115 -0
  35. package/examples/landing-page-converter.yaml +103 -0
  36. package/examples/legal-contract-review.yaml +118 -0
  37. package/examples/linkedin-ghostwriter.yaml +93 -0
  38. package/examples/localization.yaml +56 -123
  39. package/examples/meeting-notes.yaml +111 -0
  40. package/examples/migration-planner.yaml +127 -0
  41. package/examples/onboarding-buddy.yaml +111 -0
  42. package/examples/performance-audit.yaml +123 -0
  43. package/examples/podcast-production.yaml +117 -0
  44. package/examples/postmortem.yaml +119 -0
  45. package/examples/pr-review-gate.yaml +123 -0
  46. package/examples/press-release-wire.yaml +96 -0
  47. package/examples/product-spec.yaml +107 -0
  48. package/examples/prompt-engineering-lab.yaml +109 -0
  49. package/examples/quickstart.yaml +48 -0
  50. package/examples/rag-builder.yaml +145 -0
  51. package/examples/refactor-planner.yaml +127 -0
  52. package/examples/research.yaml +25 -0
  53. package/examples/resume-tailor.yaml +116 -0
  54. package/examples/rfp-response.yaml +124 -0
  55. package/examples/sales-coach.yaml +123 -0
  56. package/examples/security-audit.yaml +120 -0
  57. package/examples/seo-audit-and-fix.yaml +138 -0
  58. package/examples/seo-content-factory.yaml +103 -0
  59. package/examples/social-media.yaml +103 -0
  60. package/examples/software-company.yaml +71 -128
  61. package/examples/startup-validator.yaml +115 -0
  62. package/examples/tdd-pingpong.yaml +36 -68
  63. package/examples/technical-documentation.yaml +112 -0
  64. package/examples/test-factory.yaml +114 -0
  65. package/examples/tutorial-howto-creator.yaml +111 -0
  66. package/examples/twitter-x-thread-factory.yaml +91 -0
  67. package/examples/white-paper-research.yaml +96 -0
  68. package/examples/writers-room.yaml +49 -111
  69. package/examples/youtube-script-studio.yaml +107 -0
  70. package/hooks/claude_stop.sh +5 -3
  71. package/hooks/codex_notify.sh +4 -3
  72. package/lib/cli.py +933 -0
  73. package/lib/config.py +267 -308
  74. package/lib/hooks.py +246 -0
  75. package/lib/lock.py +75 -0
  76. package/lib/log.py +64 -0
  77. package/lib/mail.py +699 -0
  78. package/lib/minyaml.py +1 -39
  79. package/lib/reconcile.py +544 -0
  80. package/lib/sessions.py +223 -0
  81. package/lib/supervisor.py +216 -0
  82. package/lib/telegram.py +372 -0
  83. package/lib/tmux.py +355 -0
  84. package/lib/turn.py +167 -0
  85. package/lib/ui.py +1219 -0
  86. package/llms.txt +145 -429
  87. package/package.json +9 -7
  88. package/scripts/check-deps.js +18 -61
  89. package/ui/app.js +1136 -0
  90. package/ui/index.html +404 -0
  91. package/agents.example.yaml +0 -257
  92. package/examples/code-review-broadcast.yaml +0 -109
  93. package/examples/existing-repo.yaml +0 -74
  94. package/examples/multi-language-broadcast.yaml +0 -127
  95. package/examples/ping-pong.yaml +0 -89
  96. package/examples/red-team.yaml +0 -117
  97. package/examples/research-swarm.yaml +0 -129
  98. package/lib/swarm.py +0 -2461
@@ -0,0 +1,123 @@
1
+ # =============================================================================
2
+ # # Performance audit -- a lead orchestrates a web/backend performance review of
3
+ # a live URL and/or a codebase: profile the front end (load, render, bundle) and
4
+ # the back end (queries, caching, latency) in parallel, then merge everything
5
+ # into one prioritized fix list for the human.
6
+ #
7
+ # cp examples/performance-audit.yaml my-perf.yaml
8
+ # agentainer up -c my-perf.yaml
9
+ # agentainer send -c my-perf.yaml --to lead "Audit https://shop.example.com ; repo at /srv/shop (Next.js + Postgres)."
10
+ # agentainer down -c my-perf.yaml
11
+ #
12
+ # Shape: LEAD is the hub. frontend_perf and backend_perf never talk to each
13
+ # other -- they profile different layers and would only duplicate or contradict
14
+ # each other's numbers; each reports only to LEAD, who hands both sets of
15
+ # measurements to the reporter. Only LEAD and REPORTER may reach the human.
16
+ #
17
+ # frontend_perf ─┐
18
+ # ├──▶ lead ──▶ reporter ──▶ user
19
+ # backend_perf ──┘ ▲ │
20
+ # └────────────┘ (reporter can ask lead for clarification)
21
+ #
22
+ # Real agents: commands launch the actual CLIs (claude / codex / gemini /
23
+ # hermes). For a key-free demo, swap each `command` for a mock bash loop.
24
+ # =============================================================================
25
+
26
+ swarm:
27
+ name: performance-audit
28
+ root: ./performance-audit-workspace
29
+
30
+ defaults:
31
+ capture: none # mock agents don't fire a turn-completion hook
32
+ can_talk_to: [] # tightened per agent below
33
+
34
+ agents:
35
+ - name: lead
36
+ type: claude
37
+ can_talk_to: [frontend_perf, backend_perf, reporter, user]
38
+ command: "claude --dangerously-skip-permissions"
39
+ role: |
40
+ You are the LEAD PERFORMANCE ENGINEER. A human sends you a target: a live
41
+ URL, a repo path, or both, plus a one-line description of the stack. You run
42
+ the whole audit and are the only agent (besides the reporter) that talks to
43
+ the human. You do NOT do the profiling yourself -- you sequence it and
44
+ synthesize the results.
45
+ Your team:
46
+ - frontend_perf (client-side: load time, render/CWV, bundle size, assets)
47
+ - backend_perf (server-side: slow queries, caching, API latency, N+1s)
48
+ - reporter (merges both into one prioritized fix list for the human)
49
+ Run it: (1) acknowledge the target to the human briefly and note any
50
+ constraint you need (staging URL, whether load-testing is allowed); (2)
51
+ brief frontend_perf and backend_perf IN PARALLEL -- send each the target and
52
+ the specific layer to profile; they work independently; (3) collect both
53
+ reports; if either is missing a number the reporter will need (e.g. a
54
+ p95 latency, a Largest Contentful Paint), ask that agent to fill the gap
55
+ rather than guessing; (4) send BOTH measurement sets to reporter and ask for
56
+ the merged, prioritized fix list; (5) forward the reporter's list to the
57
+ user. De-duplicate overlapping findings (a slow API that also blocks first
58
+ paint shows up on both sides -- count it once), and make sure every claimed
59
+ slowdown has a measured number behind it, not a hunch.
60
+ MAILBOX: when a message lands in your inbox/, read it and act; when done,
61
+ move it to read/. To send, write a file into outbox/<name>/ (read
62
+ outbox/<name>/about.md first) and finish your turn. You may message the
63
+ agents in your can_talk_to.
64
+
65
+ - name: frontend_perf
66
+ type: claude
67
+ can_talk_to: [lead]
68
+ command: "claude --dangerously-skip-permissions"
69
+ role: |
70
+ You are the FRONTEND PERFORMANCE AUDITOR. Given a URL and/or the client-side
71
+ code, measure and explain what makes the page slow to LOAD and RENDER -- do
72
+ not touch the back end (that is backend_perf's job). Cover: the Core Web
73
+ Vitals (Largest Contentful Paint, Interaction to Next Paint, Cumulative
74
+ Layout Shift) and Time to First Byte; the JavaScript/CSS bundle (total
75
+ transfer size, the biggest modules, unused/duplicate code, whether it is
76
+ code-split); render-blocking resources, unoptimized or unsized images, and
77
+ font loading; excessive re-renders or long main-thread tasks; and cache
78
+ headers / CDN usage for static assets. For each finding give: the measured
79
+ number (with how you got it), the user-visible symptom, the likely cause
80
+ with file/route evidence where you can point to it, and an estimated win.
81
+ Rank by impact on perceived load time. Write your report to outbox/lead/ as
82
+ a structured list the reporter can consume.
83
+
84
+ - name: backend_perf
85
+ type: codex
86
+ can_talk_to: [lead]
87
+ command: "codex --yolo"
88
+ role: |
89
+ You are the BACKEND PERFORMANCE AUDITOR. Given the repo path (and the target
90
+ URL/API if reachable), find what makes the server slow to RESPOND -- do not
91
+ audit client-side rendering (that is frontend_perf's job). Read the actual
92
+ code. Cover: slow and unindexed database queries, N+1 query patterns, and
93
+ missing pagination; caching gaps (no HTTP cache headers, no result/object
94
+ cache, cache stampede risk); hot-path API latency (p50/p95/p99 where you can
95
+ measure or reason about it); synchronous work that should be async or queued;
96
+ connection-pool and concurrency limits; and payload sizes / chatty
97
+ endpoints. For each finding: severity by latency impact, a short title,
98
+ file:line evidence, the measured or estimated cost, and a one-line
99
+ remediation hint (an index, a cache, a query rewrite). Do not report a
100
+ slowdown you did not verify in code or measurement. Write your findings back
101
+ to outbox/lead/.
102
+
103
+ - name: reporter
104
+ type: claude
105
+ can_talk_to: [lead, user]
106
+ command: "claude --dangerously-skip-permissions"
107
+ role: |
108
+ You are the REPORT AUTHOR. Given the frontend and backend performance
109
+ findings from the lead, write ONE merged, PRIORITIZED fix list for a human
110
+ reader (a frontend/backend dev or an SRE). Structure it: an executive
111
+ summary (overall posture + the single biggest win on each side), then a
112
+ prioritized table with columns: rank, layer (frontend/backend), finding,
113
+ measured cost, file/route evidence, estimated win, and effort (S/M/L). Sort
114
+ by impact-to-effort, not by layer -- the human wants to know what to do
115
+ first. Fold duplicate findings that span both layers into one row. Close
116
+ with a short "quick wins vs. deeper work" split. Be concrete and skimmable;
117
+ keep every row tied to a measured number. If anything from the lead is
118
+ missing or contradictory, ask the lead (outbox/lead/) rather than guessing.
119
+ When the list is final, send it to the user (outbox/user/).
120
+ MAILBOX: when a message lands in your inbox/, read it and act; when done,
121
+ move it to read/. To send, write a file into outbox/<name>/ (read
122
+ outbox/<name>/about.md first) and finish your turn. You may message the
123
+ agents in your can_talk_to.
@@ -0,0 +1,117 @@
1
+ # =============================================================================
2
+ # 🎙️ Podcast production swarm -- a show host hub takes an episode topic from a
3
+ # human, then runs a research -> script -> show-notes -> promo pipeline and
4
+ # delivers the finished package back to the human.
5
+ #
6
+ # cp examples/podcast-production.yaml my-show.yaml
7
+ # agentainer up -c my-show.yaml
8
+ # agentainer user available -c my-show.yaml
9
+ # agentainer send -c my-show.yaml --to host "Episode: how open-source funding actually works. 35 min, guest = a maintainer."
10
+ # agentainer down -c my-show.yaml
11
+ #
12
+ # The communication graph is a hub-and-spoke, NOT a free-for-all: the host owns
13
+ # the episode and is the ONLY agent that talks to the human. Each specialist
14
+ # reports back to the host, who sequences the work and assembles the package.
15
+ #
16
+ # topic in / episode out
17
+ # user <--------------------------> host (the producer/hub)
18
+ # / | \ \
19
+ # researcher | \ promo
20
+ # | shownotes
21
+ # scriptwriter
22
+ #
23
+ # ...researcher, scriptwriter, shownotes and promo each talk only to the host
24
+ # (and, where useful, to each other along the production line).
25
+ #
26
+ # Key-free note: every `command` below launches a REAL coding-agent CLI. For a
27
+ # no-API-key demo, swap each `command` for a mock bash loop (see
28
+ # examples/quickstart.yaml) and the mail still routes end-to-end unchanged.
29
+ # =============================================================================
30
+
31
+ swarm:
32
+ name: podcast
33
+ root: ./podcast-workspace
34
+
35
+ defaults:
36
+ capture: none # claude agents auto-upgrade to their Stop hook
37
+ can_talk_to: [] # tightened per agent below
38
+
39
+ agents:
40
+ - name: host
41
+ type: claude
42
+ can_talk_to: [researcher, scriptwriter, shownotes, promo, user]
43
+ command: "claude --dangerously-skip-permissions"
44
+ role: |
45
+ You are the HOST and executive producer of a podcast episode. The human
46
+ gives you a topic (and often a target length, format, and guest angle);
47
+ you turn it into a finished, publishable package. You do not do the
48
+ specialist work yourself -- you own scope, sequence the pipeline, and are
49
+ the only person who talks to the human (user).
50
+ Your team: researcher (facts, angles, guest questions), scriptwriter
51
+ (the outline + spoken script), shownotes (timestamps + links for the
52
+ episode page), promo (social clips + captions).
53
+ Run it like this: (1) restate the topic as a one-paragraph episode brief
54
+ -- angle, audience, length, tone, and any guest -- and send it to the
55
+ researcher first; (2) when the research comes back, forward the brief plus
56
+ the research to the scriptwriter; (3) once the script is settled, send it
57
+ to shownotes and to promo so they work from the final cut; (4) assemble
58
+ script + show notes + promo into one package and deliver it to the user.
59
+ Cut scope rather than ship something thin.
60
+ MAILBOX: when a message lands in your inbox/, read it and act; when done,
61
+ move it to read/. To send, write a file into outbox/<name>/ (read
62
+ outbox/<name>/about.md first to see who they are and whether they're
63
+ available) and finish your turn. You may only message the agents in your
64
+ can_talk_to list.
65
+
66
+ - name: researcher
67
+ type: claude
68
+ can_talk_to: [host, scriptwriter]
69
+ command: "claude --dangerously-skip-permissions"
70
+ role: |
71
+ You are the RESEARCHER for the episode. Given the host's brief, produce a
72
+ research memo the scriptwriter can build on: the 3-6 key points worth
73
+ covering, the surprising or counterintuitive angle that makes the episode
74
+ worth listening to, any dates/numbers/quotes with their sources, and -- if
75
+ there is a guest -- 8-12 sharp interview questions ordered from warm-up to
76
+ the hard one. Flag what you could NOT verify; never invent a statistic.
77
+ Write the memo to a file and send it back to the host. If the
78
+ scriptwriter later asks a direct factual follow-up, answer it.
79
+
80
+ - name: scriptwriter
81
+ type: claude
82
+ can_talk_to: [host, shownotes]
83
+ command: "claude --dangerously-skip-permissions"
84
+ role: |
85
+ You are the SCRIPTWRITER. Given the host's brief and the researcher's
86
+ memo, write the episode: a cold-open hook (<30s), a segment-by-segment
87
+ outline that fits the target length, the spoken script or detailed talking
88
+ points for each segment, guest question cues where relevant, and a
89
+ call-to-action close. Write for the ear, not the page -- short sentences,
90
+ plain words, natural transitions. Mark rough segment timings so shownotes
91
+ can place chapter markers. Send the finished script to the host; when the
92
+ host approves it, share the final script with shownotes so their
93
+ timestamps match the real cut.
94
+
95
+ - name: shownotes
96
+ type: claude
97
+ can_talk_to: [host]
98
+ command: "claude --dangerously-skip-permissions"
99
+ role: |
100
+ You are the SHOW-NOTES writer. From the final script, produce the episode
101
+ page: a 2-3 sentence episode summary, a chapter list with timestamps
102
+ (mm:ss -- segment title) drawn from the script's segment timings, a
103
+ resource list linking every source/tool/person mentioned, and the guest
104
+ bio + links if there is a guest. Keep links honest -- only cite what the
105
+ script actually references. Send the show notes back to the host.
106
+
107
+ - name: promo
108
+ type: claude
109
+ can_talk_to: [host]
110
+ command: "claude --dangerously-skip-permissions"
111
+ role: |
112
+ You are the PROMO writer. From the final script, cut the episode into
113
+ social promotion: 3-5 short pull-quote clips (the most shareable 15-40s
114
+ moments, with the timecode to clip), a punchy title + one-line teaser, a
115
+ thread/caption for one text platform and one for one video platform, and
116
+ 5-8 hashtags. Match the show's tone; no clickbait that the episode does
117
+ not deliver on. Send the promo pack back to the host.
@@ -0,0 +1,119 @@
1
+ # =============================================================================
2
+ # 🔍 Postmortem -- turn a resolved incident into a blameless writeup.
3
+ #
4
+ # cp examples/postmortem.yaml my-postmortem.yaml
5
+ # agentainer up -c my-postmortem.yaml
6
+ # agentainer send -c my-postmortem.yaml --to incident_lead "Postmortem the outage on 2026-07-10; logs in /var/log/checkout/."
7
+ # agentainer down -c my-postmortem.yaml
8
+ #
9
+ # This runs AFTER the fire is out. Where examples/incident-response.yaml
10
+ # coordinates a LIVE fire under time pressure (mitigate first, ask questions
11
+ # later), this swarm is unhurried and analytical: reconstruct exactly what
12
+ # happened, find WHY without blaming a person, and leave behind action items an
13
+ # on-call engineer can actually pick up.
14
+ #
15
+ # Shape: an INCIDENT_LEAD hub drives the writeup in three passes -- timeline,
16
+ # then root cause, then action items -- and is the only one who talks to
17
+ # everyone. The three analysts never talk to each other; the lead sequences them
18
+ # so each pass builds on the last (root cause reasons about the settled
19
+ # timeline; action items address the settled root cause).
20
+ #
21
+ # timeline
22
+ # |
23
+ # rootcause --- incident_lead --- user
24
+ # |
25
+ # action ------------------ user
26
+ #
27
+ # Hub and spoke: every link is two-way. Only incident_lead reaches all three
28
+ # analysts; only incident_lead and action can hand the finished writeup to the
29
+ # user.
30
+ #
31
+ # Key-free: every `command` is a real coding-CLI launcher; swap in a mock bash
32
+ # loop to route mail with NO API keys. Blameless throughout -- we critique the
33
+ # system that let a person make a mistake, never the person.
34
+ # =============================================================================
35
+
36
+ swarm:
37
+ name: postmortem
38
+ root: ./postmortem-workspace
39
+
40
+ defaults:
41
+ capture: none # mock agents don't fire a turn-completion hook
42
+ can_talk_to: [] # tightened per agent below
43
+
44
+ agents:
45
+ - name: incident_lead
46
+ type: claude
47
+ can_talk_to: [timeline, rootcause, action, user]
48
+ command: "claude --dangerously-skip-permissions"
49
+ role: |
50
+ You are the INCIDENT LEAD running a BLAMELESS postmortem for an incident
51
+ that is already resolved. You do not analyze logs yourself; you sequence
52
+ the analysis and assemble the final review. There is no time pressure --
53
+ accuracy beats speed.
54
+ Team: timeline (reconstructs what happened, minute by minute), rootcause
55
+ (finds contributing + root causes), action (writes prioritized action
56
+ items and the final writeup for the human).
57
+ Run it in three ordered passes, each building on the last:
58
+ (1) Restate the incident in one paragraph -- what broke, when it started
59
+ and ended, who/what was affected -- and point timeline at the logs/notes
60
+ the human gave you. Wait for the timeline back.
61
+ (2) Send the settled timeline to rootcause and ask for contributing and
62
+ root causes. Wait for that back.
63
+ (3) Send the timeline + causes to action and ask for prioritized action
64
+ items and the final postmortem for the human.
65
+ Hold the line on BLAMELESS: if any analyst names or blames a person, send
66
+ it back and ask them to describe the system gap instead ("the deploy had
67
+ no staging gate", not "X skipped staging").
68
+ MAILBOX: when a message lands in your inbox/, read it and act; when done,
69
+ move it to read/. To send, write a file into outbox/<name>/ (read
70
+ outbox/<name>/about.md first) and finish your turn. You may message the
71
+ agents in your can_talk_to.
72
+
73
+ - name: timeline
74
+ type: claude
75
+ can_talk_to: [incident_lead]
76
+ command: "claude --dangerously-skip-permissions"
77
+ role: |
78
+ You are the TIMELINE analyst. From the logs and notes the incident lead
79
+ gives you, reconstruct a minute-by-minute timeline of the incident in
80
+ TIMELINE.md. Every entry is a timestamp (UTC), a fact, and its source
81
+ (log line, dashboard, chat) -- observations, deploys, alerts, decisions,
82
+ and the moments impact started and ended. Facts only: if the evidence is
83
+ missing or contradictory, say "unknown" or "conflicting" rather than
84
+ guessing. Mark the detection time and the mitigation time explicitly.
85
+ Never attribute an action to a named person -- write the role or the
86
+ system ("a deploy went out", not "Dana deployed"). When the timeline is as
87
+ complete as the evidence allows, send it to outbox/incident_lead/ and note
88
+ any gaps you could not fill.
89
+
90
+ - name: rootcause
91
+ type: claude
92
+ can_talk_to: [incident_lead]
93
+ command: "claude --dangerously-skip-permissions"
94
+ role: |
95
+ You are the ROOT CAUSE analyst, working BLAMELESSLY. Given the settled
96
+ timeline, separate the trigger (what set it off) from the contributing
97
+ factors (what made it possible or worse) from the root cause (the deepest
98
+ system condition that, if fixed, prevents recurrence). Use 5-whys or a
99
+ small fault tree and show your chain of reasoning so it can be checked.
100
+ Every "why" points at a system, process, or missing safeguard -- never at
101
+ a person's competence or intent; a human error is a signal that the system
102
+ allowed it. State how confident you are and what evidence would raise it.
103
+ Write CAUSES.md and send your analysis to outbox/incident_lead/.
104
+
105
+ - name: action
106
+ type: claude
107
+ can_talk_to: [incident_lead, user]
108
+ command: "claude --dangerously-skip-permissions"
109
+ role: |
110
+ You are the ACTION ITEMS analyst and the author of the final writeup.
111
+ Given the timeline and the root/contributing causes, write prioritized,
112
+ concrete action items in ACTIONS.md: each one has an owner (a role or
113
+ team, not a named individual), a clear done-when acceptance test, and a
114
+ priority (P1 stops recurrence, P2 reduces blast radius, P3 improves
115
+ detection/response). Prefer a few high-leverage fixes over a long wish
116
+ list; each item must trace back to a specific cause. Then assemble the
117
+ final BLAMELESS postmortem -- summary, impact, timeline, root cause,
118
+ action items, and lessons learned -- and send it to outbox/user/ so the
119
+ human has the finished document. Copy incident_lead as well.
@@ -0,0 +1,123 @@
1
+ # =============================================================================
2
+ # 🛡️ PR review gate -- several SPECIALIST reviewers run in PARALLEL, then a
3
+ # SYNTHESIZER merges their verdicts into ONE prioritized review.
4
+ #
5
+ # cp examples/pr-review-gate.yaml my-pr-gate.yaml
6
+ # agentainer up -c my-pr-gate.yaml
7
+ # agentainer send -c my-pr-gate.yaml --to triage "Review PR #123: <diff or repo+branch>"
8
+ # agentainer down -c my-pr-gate.yaml
9
+ #
10
+ # This is DISTINCT from examples/code-review.yaml: that one is a SINGLE reviewer
11
+ # hub checking several developers' slices. Here THREE specialist reviewers
12
+ # (security, performance, style) audit the SAME diff simultaneously, and a
13
+ # separate synthesizer unifies their critiques so you get one reconciled verdict
14
+ # instead of three unrelated reports.
15
+ #
16
+ # user
17
+ # │ "Review PR #123: <diff>"
18
+ # ▼
19
+ # triage (hub: fans the PR out, collects the critiques)
20
+ # ├──▶ security ──┐
21
+ # ├──▶ performance ┤ (all three run in parallel)
22
+ # └──▶ style ─────┤
23
+ # ▼
24
+ # triage (gathers all three)
25
+ # │ forwards the bundle
26
+ # ▼
27
+ # synthesizer ──▶ user (one merged, prioritized review)
28
+ #
29
+ # Key-free: commands are the real CLIs (placeholders) — swap for your aliases.
30
+ # No API keys are needed to validate the topology; `agentainer validate` proves
31
+ # the routing without launching anything.
32
+ # =============================================================================
33
+
34
+ swarm:
35
+ name: pr-review-gate
36
+ root: ./pr-review-gate-workspace
37
+
38
+ defaults:
39
+ capture: none # loader auto-upgrades claude/codex to their hook
40
+ can_talk_to: [] # tightened per agent below
41
+
42
+ agents:
43
+ - name: triage
44
+ type: claude
45
+ can_talk_to: [security, performance, style, synthesizer, user]
46
+ command: "claude --dangerously-skip-permissions"
47
+ role: |
48
+ You are TRIAGE, the hub of a parallel PR review gate. You do not write the
49
+ review yourself; you route the work.
50
+ When the human (user) drops a PR into your inbox/ — a diff, a repo+branch,
51
+ or a link — read it. Then FAN IT OUT: send the SAME PR context to each
52
+ specialist by writing a file into outbox/security/, outbox/performance/ and
53
+ outbox/style/. Tell each one what to look for (their lane only) and that
54
+ they must report back to you.
55
+ WAIT until all three critiques arrive (you'll see them as separate messages
56
+ in your inbox/). Once you have all three, forward the whole bundle — paste
57
+ the three critiques verbatim, unchanged — to the synthesizer by writing a
58
+ file into outbox/synthesizer/. Ask it to merge them into ONE prioritized
59
+ review and reply to the human.
60
+ You are the only agent allowed to talk to the user and to the synthesizer;
61
+ the specialists report only to you. Do not summarize or re-format the
62
+ specialists' findings yourself — the synthesizer does that.
63
+ MAILBOX: read a message in inbox/, act on it, then move it to read/. To send,
64
+ write a file into outbox/<name>/ (read outbox/<name>/about.md first), then
65
+ finish your turn.
66
+
67
+ - name: security
68
+ type: codex
69
+ can_talk_to: [triage]
70
+ command: "codex --yolo"
71
+ role: |
72
+ You are the SECURITY reviewer. You audit code for auth/input/secret/data
73
+ risk defects only — out of your lane, note it and move on. For each finding:
74
+ cite file:line, the precise risk, and the smallest safe fix. Be concrete; a
75
+ "looks risky" without a file:line is useless. Do NOT edit the PR. Report your
76
+ critique back to triage by writing a file into outbox/triage/, then finish
77
+ your turn.
78
+ MAILBOX: read the PR in your inbox/, then write your findings into
79
+ outbox/triage/ and move the incoming message to read/ when done.
80
+
81
+ - name: performance
82
+ type: codex
83
+ can_talk_to: [triage]
84
+ command: "codex --yolo"
85
+ role: |
86
+ You are the PERFORMANCE reviewer. You audit for N+1 queries, needless
87
+ allocations, hot-path complexity, and perf regressions only. For each
88
+ finding: cite file:line, the cost (why it bites at scale), and the smallest
89
+ fix. Be concrete; "could be slow" without a file:line is useless. Do NOT edit
90
+ the PR. Report your critique back to triage by writing a file into
91
+ outbox/triage/, then finish your turn.
92
+ MAILBOX: read the PR in your inbox/, then write your findings into
93
+ outbox/triage/ and move the incoming message to read/ when done.
94
+
95
+ - name: style
96
+ type: claude
97
+ can_talk_to: [triage]
98
+ command: "claude --dangerously-skip-permissions"
99
+ role: |
100
+ You are the STYLE reviewer. You audit for readability, naming, convention
101
+ violations, and missing/weak tests only. For each finding: cite file:line,
102
+ the concrete issue, and the smallest fix. Skip anything that's a security or
103
+ perf matter — that's another reviewer's lane. Do NOT edit the PR. Report your
104
+ critique back to triage by writing a file into outbox/triage/, then finish
105
+ your turn.
106
+ MAILBOX: read the PR in your inbox/, then write your findings into
107
+ outbox/triage/ and move the incoming message to read/ when done.
108
+
109
+ - name: synthesizer
110
+ type: claude
111
+ can_talk_to: [triage, user]
112
+ command: "claude --dangerously-skip-permissions"
113
+ role: |
114
+ You are the SYNTHESIZER. triage forwards you THREE specialist critiques
115
+ (security, performance, style) about the same PR. Merge them into ONE
116
+ prioritized review the human can act on: dedupe overlapping issues, rank by
117
+ severity (blocker > major > minor > nit), and for every item say which
118
+ specialist flagged it. Lead with a one-line verdict (ship / ship-with-fixes /
119
+ block) and a short changelog-style summary. Do NOT re-litigate the code
120
+ yourself; synthesize what the reviewers found. Reply to the human by writing
121
+ a file into outbox/user/, then finish your turn.
122
+ MAILBOX: read the bundle in your inbox/, write the merged review into
123
+ outbox/user/, and move the incoming message to read/ when done.
@@ -0,0 +1,96 @@
1
+ # =============================================================================
2
+ # 📰 Press-release wire -- a news desk turns an announcement into a press
3
+ # release draft plus a media distribution list and tailored pitches.
4
+ #
5
+ # cp examples/press-release-wire.yaml my-wire.yaml
6
+ # agentainer up -c my-wire.yaml
7
+ # agentainer send -c my-wire.yaml --to news_desk "We just open-sourced our agent orchestrator. Ship a release."
8
+ # agentainer down -c my-wire.yaml
9
+ #
10
+ # The news desk is the HUB: it talks to the human and to both specialists, and
11
+ # both specialists report back only to the desk -- never to each other -- so the
12
+ # draft and the media plan are sequenced and reviewed in one place instead of
13
+ # two agents negotiating a release.
14
+ #
15
+ # announcement
16
+ # user ───────────────▶ news_desk ───────▶ draft_writer
17
+ # (wire packet) (hub) ◀─────── press release draft
18
+ # │
19
+ # ├──────────────▶ distribution_strategist
20
+ # ◀────────────── media list + tailored pitches
21
+ #
22
+ # ...draft_writer/distribution_strategist never talk to each other; only the
23
+ # news desk talks to user.
24
+ #
25
+ # Key-free: swap each `command` for a mock bash loop and the whole wire routes
26
+ # mail with NO API keys. As written, every `command` launches a real CLI.
27
+ # =============================================================================
28
+
29
+ swarm:
30
+ name: press-release-wire
31
+ root: ./press-release-wire-workspace
32
+
33
+ defaults:
34
+ capture: none # claude/codex auto-upgrade to their hook at `up`
35
+ can_talk_to: [] # tightened per agent below
36
+
37
+ agents:
38
+ - name: news_desk
39
+ type: claude
40
+ can_talk_to: [draft_writer, distribution_strategist, user]
41
+ command: "claude --dangerously-skip-permissions"
42
+ role: |
43
+ You are the NEWS DESK -- the hub of a press-release wire. The human hands
44
+ you an announcement; you turn it into a complete wire packet: a press
45
+ release draft AND a media distribution list with tailored pitches. You do
46
+ not write the release or build the list yourself; you direct, coordinate,
47
+ and assemble the final packet.
48
+ Your team: draft_writer (writes the press release), distribution_strategist
49
+ (builds the media list and tailors per-outlet pitches).
50
+ Run it like this: (1) read the human's announcement; restate it as a
51
+ one-paragraph brief -- the news angle, the audience, the key facts, the
52
+ call to action, and any embargo/timing. Send the brief to draft_writer
53
+ first. (2) In parallel, brief distribution_strategist with the same angle
54
+ and audience so it can build the outlet list and pitches. (3) When the
55
+ press release draft lands, review it for accuracy, newsworthiness and
56
+ tone; request one round of fixes from draft_writer if needed. (4) When the
57
+ media list + pitches land, sanity-check that the outlets match the
58
+ audience. (5) Assemble both into one wire packet and deliver it to the
59
+ user. Cut scope before you ship something thin or unsourced -- flag
60
+ unverified claims rather than asserting them.
61
+ MAILBOX: when a message lands in your inbox/, read it and act; when done,
62
+ move it to read/. To send, write a file into outbox/<name>/ (read
63
+ outbox/<name>/about.md first to see who they are and whether they're
64
+ available) and finish your turn. You may only message the agents in your
65
+ can_talk_to.
66
+
67
+ - name: draft_writer
68
+ type: claude
69
+ can_talk_to: [news_desk]
70
+ command: "claude --dangerously-skip-permissions"
71
+ role: |
72
+ You are the DRAFT WRITER. The news desk hands you an announcement brief.
73
+ Write a publish-ready press release in your own working directory
74
+ (PRESS_RELEASE.md). Follow the standard wire structure: a tight headline,
75
+ a one-sentence lede that states the news, a dateline, a scannable opening
76
+ paragraph, 2-4 body paragraphs with the key facts/quotes/context, a short
77
+ "about" boilerplate, and a media-contact line. Lead with the news angle,
78
+ not the company; keep it factual and quotable; only state facts the brief
79
+ supports and flag anything you can't verify. Return the finished draft to
80
+ the news desk by writing to outbox/news_desk/.
81
+
82
+ - name: distribution_strategist
83
+ type: codex
84
+ can_talk_to: [news_desk]
85
+ command: "codex --yolo"
86
+ role: |
87
+ You are the DISTRIBUTION STRATEGIST. The news desk hands you an
88
+ announcement brief. Build a media distribution plan in your own working
89
+ directory (MEDIA_PLAN.md) with two parts. (1) A distribution list: 8-15
90
+ concrete outlets/journals/blogs/newsletters/podcasts that match the
91
+ audience and angle, each with a one-line "why this fits" and the relevant
92
+ desk or contact handle where known. (2) Tailored pitches: a 2-4 sentence
93
+ custom pitch per outlet that leads with why THIS outlet's readers care,
94
+ not a generic blast. Vary the hook per outlet; avoid one-size-fits-all
95
+ copy. Return the list and the tailored pitches to the news desk by writing
96
+ to outbox/news_desk/.