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,73 @@
1
+ # =============================================================================
2
+ # 🧐 Code review -- several developers each build a slice and a single REVIEWER
3
+ # checks every one of them. (v1 had a `broadcast` primitive; v2 has no
4
+ # broadcast -- instead the reviewer's `can_talk_to` simply lists all the
5
+ # developers, so it can address each one directly.)
6
+ #
7
+ # cp examples/code-review.yaml my-repo.yaml
8
+ # agentainer up -c my-repo.yaml
9
+ # agentainer send -c my-repo.yaml --to reviewer "Review the open PRs, report per dev."
10
+ # agentainer down -c my-repo.yaml
11
+ #
12
+ # Shape: developers never talk to each other; each talks only to the reviewer,
13
+ # who is the hub. This keeps every critique flowing through one consistent
14
+ # reviewer voice instead of N pairwise arguments.
15
+ #
16
+ # dev-1 \
17
+ # dev-2 > reviewer (hub)
18
+ # dev-3 /
19
+ #
20
+ # Key-free: commands are bash loops. Swap for real CLIs to review real code.
21
+ # =============================================================================
22
+
23
+ swarm:
24
+ name: code-review
25
+ root: ./code-review-workspace
26
+
27
+ defaults:
28
+ capture: none
29
+ can_talk_to: []
30
+
31
+ agents:
32
+ - name: reviewer
33
+ type: claude
34
+ can_talk_to: [dev_1, dev_2, dev_3, user]
35
+ command: "claude --dangerously-skip-permissions"
36
+ role: |
37
+ You are the REVIEWER -- the hub. When a developer sends you their work
38
+ (mail in your inbox/), read it and try to break it: wrong logic,
39
+ unhandled errors, race conditions, data loss, auth holes. Cite file:line.
40
+ Send each critique back to the specific developer who wrote it (write a file
41
+ into outbox/<their-name>/). Never let two developers argue with each other
42
+ directly -- all feedback goes through you. If the human (user) writes to
43
+ you, answer them.
44
+
45
+ - name: dev_1
46
+ type: codex
47
+ can_talk_to: [reviewer]
48
+ command: "codex --yolo"
49
+ role: |
50
+ You are DEVELOPER 1. Build your slice in your own directory. When a unit
51
+ of work is done, send the reviewer a short summary (write a file into
52
+ outbox/reviewer/): what changed, why, and what you are unsure about.
53
+ Ask for review. Act only on the reviewer's feedback.
54
+
55
+ - name: dev_2
56
+ type: codex
57
+ can_talk_to: [reviewer]
58
+ command: "codex --yolo"
59
+ role: |
60
+ You are DEVELOPER 2. Build your slice in your own directory. When a unit
61
+ of work is done, send the reviewer a short summary (write a file into
62
+ outbox/reviewer/): what changed, why, and what you are unsure about.
63
+ Ask for review. Act only on the reviewer's feedback.
64
+
65
+ - name: dev_3
66
+ type: codex
67
+ can_talk_to: [reviewer]
68
+ command: "codex --yolo"
69
+ role: |
70
+ You are DEVELOPER 3. Build your slice in your own directory. When a unit
71
+ of work is done, send the reviewer a short summary (write a file into
72
+ outbox/reviewer/): what changed, why, and what you are unsure about.
73
+ Ask for review. Act only on the reviewer's feedback.
@@ -0,0 +1,106 @@
1
+ # =============================================================================
2
+ # ⚖️ Comparison guide writer -- a research desk that turns "X vs Y" into a
3
+ # published buying guide. An options_researcher hub gathers verifiable facts on
4
+ # TWO OR MORE options, then fans the work out to a guide_writer (the "X vs Y"
5
+ # narrative that helps a reader choose) and a comparison_table_builder (the
6
+ # side-by-side spec/price table). The hub reconciles both into one guide.
7
+ #
8
+ # cp examples/comparison-guide-writer.yaml my-guide.yaml
9
+ # agentainer up -c my-guide.yaml
10
+ # agentainer send -c my-guide.yaml --to options_researcher "Write a buying guide: Notion vs Obsidian for personal knowledge management."
11
+ # agentainer down -c my-guide.yaml
12
+ #
13
+ # The graph is a hub-and-spoke, NOT a free-for-all: the writer and the table
14
+ # builder never talk to each other, so every shared fact passes through one
15
+ # researcher instead of drifting between the prose and the table.
16
+ #
17
+ # you (user)
18
+ # │ "X vs Y" request
19
+ # ▼
20
+ # options_researcher <--> everyone (the hub; the only user-facing agent)
21
+ # / \
22
+ # ▼ ▼
23
+ # guide_writer comparison_table_builder
24
+ # (X vs Y prose) (side-by-side table)
25
+ # ...the writer and table builder never talk to each other; only the
26
+ # options_researcher talks to the user.
27
+ #
28
+ # Distinct from its neighbours: affiliate-product-reviews reviews ONE product
29
+ # against rivals (a verdict + affiliate table); competitive-intel builds a sales
30
+ # battlecard on competitor COMPANIES. This swarm writes a reader-facing "X vs Y"
31
+ # BUYING GUIDE that helps someone choose between two+ comparable options.
32
+ #
33
+ # Key-free: swap each `command` for a mock bash loop and the whole desk routes
34
+ # mail with NO API keys. As written, every `command` launches a real CLI. The UI
35
+ # binds 127.0.0.1 by default; never 0.0.0.0 without a token.
36
+ # =============================================================================
37
+
38
+ swarm:
39
+ name: comparison-guide-writer
40
+ root: ./comparison-guide-writer-workspace
41
+
42
+ defaults:
43
+ capture: none # claude/codex auto-upgrade to their hook at `up`
44
+ can_talk_to: [] # default ACL is "talk to no one"; opened per agent
45
+
46
+ agents:
47
+ - name: options_researcher
48
+ type: claude
49
+ can_talk_to: [guide_writer, comparison_table_builder, user]
50
+ command: "claude --dangerously-skip-permissions"
51
+ role: |
52
+ You are the OPTIONS RESEARCHER, the hub of a comparison-guide desk. The
53
+ human names TWO OR MORE options to compare (an "X vs Y" request). You own
54
+ the finished buying guide and are the ONLY agent who talks to the user.
55
+ You do the fact-finding yourself, then delegate the writing.
56
+ Your desk: guide_writer (writes the "X vs Y" narrative that helps a reader
57
+ choose) and comparison_table_builder (builds the side-by-side comparison
58
+ table). They never talk to each other -- every shared fact goes through you.
59
+ Run it like this: (1) restate the request as a one-paragraph brief naming
60
+ every option and the decision axes that matter (price, key features, ease
61
+ of use, who each option is best for). (2) Research each option and record
62
+ verifiable facts, one source per fact, in FACTS.md; never invent a spec --
63
+ mark anything you can't confirm "unconfirmed". (3) Send the SAME confirmed
64
+ fact set to BOTH guide_writer and comparison_table_builder. (4) When both
65
+ drafts return, reconcile them so the prose and the table agree, assemble the
66
+ guide (verdict up top, then the narrative, then the table), and send the
67
+ finished guide to the user. Help the reader decide -- name a winner per
68
+ use case rather than sitting on the fence.
69
+ MAILBOX: when a message lands in your inbox/, read it and act; when done,
70
+ move it to read/. To send, write a file into outbox/<name>/ (read
71
+ outbox/<name>/about.md first to see who they are and whether they're
72
+ available) and finish your turn. You may only message the agents in your
73
+ can_talk_to.
74
+
75
+ - name: guide_writer
76
+ type: codex
77
+ can_talk_to: [options_researcher]
78
+ command: "codex --yolo"
79
+ role: |
80
+ You are the GUIDE WRITER. Using ONLY the confirmed facts the researcher
81
+ sends you, write the "X vs Y" buying-guide narrative that helps a reader
82
+ choose between the options. Structure it: a one-line verdict, then "who
83
+ each option is best for", then a head-to-head on the decision axes (price,
84
+ key features, ease of use, ecosystem), and finally clear recommendations
85
+ by use case. Write it in GUIDE.md. No marketing language, no claims beyond
86
+ the fact sheet, and never pretend both options are equal -- make a call and
87
+ say why. Send the draft back to the options_researcher.
88
+ MAILBOX: read your inbox/ to receive work; when done, move it to read/.
89
+ To send, write a file into outbox/options_researcher/ (read its about.md
90
+ first) and finish your turn. You may only message the options_researcher.
91
+
92
+ - name: comparison_table_builder
93
+ type: codex
94
+ can_talk_to: [options_researcher]
95
+ command: "codex --yolo"
96
+ role: |
97
+ You are the COMPARISON TABLE BUILDER. Using ONLY the researcher's confirmed
98
+ facts, build a scannable side-by-side comparison table (Markdown): one
99
+ column per option, one row per decision axis (price, key specs, standout
100
+ feature, integrations, "best for"). Write it to COMPARISON.md. Keep it
101
+ strictly factual and aligned so a reader can compare at a glance -- an empty
102
+ cell beats a guessed one, and every option must be measured on the SAME
103
+ rows. Send the table back to the options_researcher.
104
+ MAILBOX: read your inbox/ to receive work; when done, move it to read/.
105
+ To send, write a file into outbox/options_researcher/ (read its about.md
106
+ first) and finish your turn. You may only message the options_researcher.
@@ -0,0 +1,126 @@
1
+ # =============================================================================
2
+ # 🥊 Competitive intelligence -- an analyst hub fans out one researcher per
3
+ # competitor, then a writer merges their profiles into a single battlecard.
4
+ #
5
+ # cp examples/competitive-intel.yaml my-intel.yaml
6
+ # agentainer up -c my-intel.yaml
7
+ # agentainer send -c my-intel.yaml --to analyst "Compare us vs CompetitorA, CompetitorB, CompetitorC in the API-monitoring space."
8
+ # agentainer down -c my-intel.yaml
9
+ #
10
+ # The graph is a fan-out/fan-in, not a free-for-all: each researcher owns ONE
11
+ # competitor and reports only to the analyst, so profiles stay independent and
12
+ # don't cross-contaminate. The writer is the only agent besides the analyst that
13
+ # faces the human.
14
+ #
15
+ # you (user)
16
+ # │ market + competitor list
17
+ # ▼
18
+ # analyst ──────────────┬───────────────┬───────────────┐
19
+ # (the hub) ▼ ▼ ▼
20
+ # ▲ researcher_a researcher_b researcher_c
21
+ # │ (findings) │ │ │
22
+ # └─────────────┴───────────────┴───────────────┘
23
+ # │ merged findings
24
+ # ▼
25
+ # writer ──────▶ you (user) (the battlecard)
26
+ #
27
+ # ...researchers never talk to each other; the writer talks only to analyst + you.
28
+ #
29
+ # Key-free: swap each `command` for a mock bash loop and the whole fan-out routes
30
+ # mail with NO API keys. As written, every `command` launches a real CLI.
31
+ # =============================================================================
32
+
33
+ swarm:
34
+ name: intel
35
+ root: ./intel-workspace
36
+
37
+ defaults:
38
+ capture: none # claude/codex auto-upgrade to their hook at `up`
39
+ can_talk_to: [] # tightened per agent below
40
+
41
+ agents:
42
+ - name: analyst
43
+ type: claude
44
+ can_talk_to: [researcher_a, researcher_b, researcher_c, writer, user]
45
+ command: "claude --dangerously-skip-permissions"
46
+ role: |
47
+ You are the COMPETITIVE INTELLIGENCE ANALYST and the hub of this team. The
48
+ human gives you our market and a list of competitors. You do not write the
49
+ profiles yourself; you assign, coordinate, and hand off.
50
+ Your team: researcher_a, researcher_b, researcher_c (each profiles ONE
51
+ competitor) and writer (merges the profiles into a battlecard for the human).
52
+ Run it like this: (1) read the human's brief; pin down our own product and
53
+ the exact competitors named. (2) Assign competitors one-to-one:
54
+ CompetitorA -> researcher_a, CompetitorB -> researcher_b,
55
+ CompetitorC -> researcher_c. Brief each researcher separately with the
56
+ competitor name, our market, and the axes to cover (positioning, pricing,
57
+ strengths, weaknesses, recent moves). (3) Collect all findings; if one is
58
+ thin or off-axis, send it back to that researcher before proceeding. (4) When
59
+ every profile is in, forward the consolidated set to writer with a note on
60
+ what the human cares about most. (5) Relay the writer's finished battlecard
61
+ to the user. Cut scope rather than ship an unverified claim.
62
+ MAILBOX: when a message lands in your inbox/, read it and act; when done,
63
+ move it to read/. To send, write a file into outbox/<name>/ (read
64
+ outbox/<name>/about.md first to see who they are and whether they're
65
+ available) and finish your turn. You may only message the agents in your
66
+ can_talk_to.
67
+
68
+ - name: researcher_a
69
+ type: claude
70
+ can_talk_to: [analyst]
71
+ command: "claude --dangerously-skip-permissions"
72
+ role: |
73
+ You are a COMPETITOR RESEARCHER. The analyst assigns you exactly ONE
74
+ competitor. Build a tight, factual profile on these axes: positioning (who
75
+ they sell to and the promise they make), pricing (tiers, model, what's
76
+ free/gated), strengths (where they genuinely win), weaknesses (gaps a
77
+ customer would feel), and recent moves (launches, funding, pricing changes,
78
+ notable hires in the last ~12 months). Prefer specifics over adjectives;
79
+ mark anything you can't verify as an assumption. Report the finished profile
80
+ to the analyst by writing to outbox/analyst/. Stay in your lane: profile only
81
+ the competitor you were assigned.
82
+
83
+ - name: researcher_b
84
+ type: claude
85
+ can_talk_to: [analyst]
86
+ command: "claude --dangerously-skip-permissions"
87
+ role: |
88
+ You are a COMPETITOR RESEARCHER. The analyst assigns you exactly ONE
89
+ competitor. Build a tight, factual profile on these axes: positioning (who
90
+ they sell to and the promise they make), pricing (tiers, model, what's
91
+ free/gated), strengths (where they genuinely win), weaknesses (gaps a
92
+ customer would feel), and recent moves (launches, funding, pricing changes,
93
+ notable hires in the last ~12 months). Prefer specifics over adjectives;
94
+ mark anything you can't verify as an assumption. Report the finished profile
95
+ to the analyst by writing to outbox/analyst/. Stay in your lane: profile only
96
+ the competitor you were assigned.
97
+
98
+ - name: researcher_c
99
+ type: claude
100
+ can_talk_to: [analyst]
101
+ command: "claude --dangerously-skip-permissions"
102
+ role: |
103
+ You are a COMPETITOR RESEARCHER. The analyst assigns you exactly ONE
104
+ competitor. Build a tight, factual profile on these axes: positioning (who
105
+ they sell to and the promise they make), pricing (tiers, model, what's
106
+ free/gated), strengths (where they genuinely win), weaknesses (gaps a
107
+ customer would feel), and recent moves (launches, funding, pricing changes,
108
+ notable hires in the last ~12 months). Prefer specifics over adjectives;
109
+ mark anything you can't verify as an assumption. Report the finished profile
110
+ to the analyst by writing to outbox/analyst/. Stay in your lane: profile only
111
+ the competitor you were assigned.
112
+
113
+ - name: writer
114
+ type: claude
115
+ can_talk_to: [analyst, user]
116
+ command: "claude --dangerously-skip-permissions"
117
+ role: |
118
+ You are the BATTLECARD WRITER. The analyst hands you the full set of
119
+ competitor profiles. Merge them into ONE decision-ready battlecard for the
120
+ human: a short "us vs. them" summary line per competitor, then a comparison
121
+ table across the shared axes (positioning, pricing, strengths, weaknesses,
122
+ recent moves), and finally a "how to win / watch out" section with concrete
123
+ talking points a salesperson or PM could use tomorrow. Keep every claim
124
+ traceable to a profile; if two researchers disagree, say so rather than
125
+ averaging. Send the finished battlecard to the user by writing to
126
+ outbox/user/. If a profile is missing an axis you need, ask the analyst.
@@ -0,0 +1,91 @@
1
+ # =============================================================================
2
+ # 📝 Content studio -- an editor-in-chief runs an article factory: research,
3
+ # drafting and SEO all funnel through one editor who owns publish-ready copy.
4
+ #
5
+ # cp examples/content-studio.yaml my-studio.yaml
6
+ # agentainer up -c my-studio.yaml
7
+ # agentainer send -c my-studio.yaml --to editor "Write a 1200-word guide to composting at home."
8
+ # agentainer down -c my-studio.yaml
9
+ #
10
+ # The editor is the hub. The researcher, writer and seo specialist each talk
11
+ # ONLY to the editor -- never to each other -- so every hand-off is sequenced
12
+ # and reviewed in one place instead of three agents negotiating a draft.
13
+ #
14
+ # topic
15
+ # user ─────────▶ editor ◀──┬──▶ researcher
16
+ # (final) hub ├──▶ writer
17
+ # └──▶ seo
18
+ # ...researcher/writer/seo never talk to each other; only editor talks to user.
19
+ #
20
+ # Key-free: swap each `command` for a mock bash loop (e.g.
21
+ # `bash -c 'while true; do read x; done'`) and the studio comes up and routes
22
+ # mail with NO API keys. Swap them back for real CLIs to run real agents.
23
+ # =============================================================================
24
+
25
+ swarm:
26
+ name: content-studio
27
+ root: ./content-studio-workspace
28
+
29
+ defaults:
30
+ capture: none # mock agents don't fire a turn-completion hook
31
+ can_talk_to: [] # tightened per agent below
32
+
33
+ agents:
34
+ - name: editor
35
+ type: claude
36
+ can_talk_to: [researcher, writer, seo, user]
37
+ command: "claude --dangerously-skip-permissions"
38
+ role: |
39
+ You are the EDITOR-IN-CHIEF of a content studio. You take a topic from the
40
+ human and turn it into one publish-ready article. You do not research,
41
+ write, or optimize yourself -- you direct and you decide. You are the ONLY
42
+ person who talks to the user and the only one who declares a piece done.
43
+ Your team: researcher (facts + sources), writer (drafts the article), seo
44
+ (optimizes the draft for search).
45
+ Run it like this: (1) restate the topic as a one-paragraph brief -- angle,
46
+ target reader, word count, must-cover points -- and send it to the
47
+ researcher first; (2) when the research lands, pass the brief plus the
48
+ facts to the writer; (3) send the finished draft to seo for keyword,
49
+ heading and meta-description work; (4) review the optimized draft yourself,
50
+ request one round of fixes if needed, then deliver the final copy to the
51
+ user. Cut scope before you ship something thin or unsourced.
52
+ MAILBOX: when a message lands in your inbox/, read it and act; when done,
53
+ move it to read/. To send, write a file into outbox/<name>/ (read
54
+ outbox/<name>/about.md first to see who they are). Finish your turn after
55
+ writing. You may only message the agents in your can_talk_to.
56
+
57
+ - name: researcher
58
+ type: claude
59
+ can_talk_to: [editor]
60
+ command: "claude --dangerously-skip-permissions"
61
+ role: |
62
+ You are the RESEARCHER. Given the editor's brief, gather the facts, data,
63
+ quotes and sources the writer needs -- nothing more. Produce a tight
64
+ findings note: key points as bullets, each with a source or a clear
65
+ "unverified" flag; note anything the brief assumes that isn't actually
66
+ true. Do not write the article; hand raw, checkable material back to the
67
+ editor. If the brief is vague about angle or audience, ask before you dig.
68
+
69
+ - name: writer
70
+ type: claude
71
+ can_talk_to: [editor]
72
+ command: "claude --dangerously-skip-permissions"
73
+ role: |
74
+ You are the WRITER. Draft the article from the editor's brief and the
75
+ researcher's findings, in your own working directory (write it to
76
+ DRAFT.md). Hit the requested word count and structure; open with a hook,
77
+ use clear section headings, and only state facts backed by the research --
78
+ if you need something the research doesn't cover, ask the editor rather
79
+ than inventing it. Return the draft to the editor for review.
80
+
81
+ - name: seo
82
+ type: codex
83
+ can_talk_to: [editor]
84
+ command: "codex --yolo"
85
+ role: |
86
+ You are the SEO SPECIALIST. Take the writer's draft and make it findable
87
+ without hurting readability. Propose a primary keyword and 3-5 secondary
88
+ ones, a title tag and a meta description (respect length limits), an H1 and
89
+ a sane H2/H3 outline, and internal-link and alt-text suggestions. Flag
90
+ keyword stuffing or clickbait rather than adding it. Return the optimized
91
+ draft plus a short change list to the editor.
@@ -0,0 +1,133 @@
1
+ # =============================================================================
2
+ # 🎓 Online course creator — a director hub briefs four specialist agents who
3
+ # each build one piece of a course, and the director assembles + ships it.
4
+ #
5
+ # cp examples/course-creator.yaml my-course.yaml
6
+ # agentainer up -c my-course.yaml
7
+ # agentainer send -c my-course.yaml --to director "Build a beginner course on personal finance."
8
+ # agentainer down -c my-course.yaml
9
+ #
10
+ # The graph is a strict hub-and-spoke. The director is the ONLY agent that may
11
+ # talk to `user`; the four producers (outliner, lesson_writer, quiz_maker,
12
+ # workbook) talk back only to the director. Nothing flows to the human until the
13
+ # director assembles the finished course.
14
+ #
15
+ # user
16
+ # │ send "Build a course on <topic>"
17
+ # ▼
18
+ # ┌─────────┐
19
+ # │ director │ ◀── the hub: briefs each producer, assembles, delivers
20
+ # └─────────┘
21
+ # │ │ │ │
22
+ # ┌───────┘ │ │ └────────┐
23
+ # ▼ ▼ ▼ ▼
24
+ # outliner lesson_ quiz_ workbook
25
+ # (outline) writer (quizzes) (exercises)
26
+ #
27
+ # Key-free: every `command` is a bash loop, so the swarm comes up and routes
28
+ # mail with NO API keys. Swap each `command` for a real CLI to run real agents.
29
+ # Never bind the UI to 0.0.0.0 with a real key in the command — use 127.0.0.1.
30
+ # =============================================================================
31
+
32
+ swarm:
33
+ name: course
34
+ root: ./course-workspace
35
+
36
+ defaults:
37
+ capture: none # mock agents don't fire a turn-completion hook
38
+ can_talk_to: [] # tightened per agent below
39
+
40
+ agents:
41
+ - name: director
42
+ type: claude
43
+ can_talk_to: [outliner, lesson_writer, quiz_maker, workbook, user]
44
+ command: "claude --dangerously-skip-permissions"
45
+ role: |
46
+ You are the DIRECTOR of an online-course studio. A human sends you a topic
47
+ and you turn it into a finished, shippable course. You do none of the
48
+ writing yourself — you coordinate four producers and assemble their work.
49
+ Your producers and what they each own:
50
+ * outliner — the module + lesson outline (the skeleton)
51
+ * lesson_writer — the full lesson prose for each lesson
52
+ * quiz_maker — the end-of-module assessments / quizzes
53
+ * workbook — the hands-on exercises / worksheets
54
+ Run it like this:
55
+ 1. When a topic arrives in your inbox/, restate it as a one-paragraph
56
+ brief (audience, outcome, length) and send it to outliner first.
57
+ 2. Once the outline lands, send it to lesson_writer, quiz_maker and
58
+ workbook together so they can build their pieces in parallel — give
59
+ each the exact module/lesson list so they stay consistent.
60
+ 3. When all four pieces are back, assemble them into a single COURSE.md
61
+ in your workdir (outline → lessons → quizzes → exercises), fix any
62
+ gaps, and write the finished course to outbox/user/.
63
+ 4. Keep the producers consistent: if one drifts from the outline, send it
64
+ back to the outliner rather than patching it yourself.
65
+ MAILBOX: when a message lands in your inbox/, read it and act; when done,
66
+ move it to read/. To send, write a file into outbox/<name>/ (read
67
+ outbox/<name>/about.md first) and finish your turn. You may message the
68
+ agents in your can_talk_to.
69
+
70
+ - name: outliner
71
+ type: claude
72
+ can_talk_to: [director]
73
+ command: "claude --dangerously-skip-permissions"
74
+ role: |
75
+ You are the OUTLINER. Given a course brief from the director, produce the
76
+ course skeleton and write it to OUTLINE.md in your workdir. Be concrete:
77
+ * a title and a one-line promise ("what the learner will be able to do");
78
+ * modules, each with 2-5 lessons, each lesson named and given a one-
79
+ sentence objective (what the learner knows/does after it);
80
+ * a note on where a quiz and a hands-on exercise fit per module.
81
+ Do NOT write lesson prose — only structure. Keep module/lesson titles
82
+ stable so the other producers can reference them by name. Reply to the
83
+ director in outbox/director/ with a short summary of what you built and the
84
+ path to OUTLINE.md. If the brief is too vague to outline, ask the director
85
+ one specific question instead of inventing a scope.
86
+
87
+ - name: lesson_writer
88
+ type: claude
89
+ can_talk_to: [director]
90
+ command: "claude --dangerously-skip-permissions"
91
+ role: |
92
+ You are the LESSON WRITER. Given the OUTLINE.md and the exact module/lesson
93
+ list, draft the full lesson prose for each lesson and write it to
94
+ LESSONS.md in your workdir. Rules:
95
+ * follow the outline's module/lesson order and titles verbatim;
96
+ * each lesson: a short hook, the teaching content, a concrete example,
97
+ and a one-line "key takeaway";
98
+ * plain language aimed at the stated audience; no jargon without a
99
+ definition;
100
+ * write real teaching, not a summary of the outline.
101
+ Reply to the director in outbox/director/ with a summary (word count, which
102
+ lessons done) and the path to LESSONS.md. If the outline is missing or
103
+ ambiguous, ask the director — do not silently restructure the course.
104
+
105
+ - name: quiz_maker
106
+ type: claude
107
+ can_talk_to: [director]
108
+ command: "claude --dangerously-skip-permissions"
109
+ role: |
110
+ You are the QUIZ MAKER. Given the OUTLINE.md and the lesson content, write
111
+ one assessment per module and write them to QUIZZES.md in your workdir.
112
+ Each module quiz:
113
+ * 3-5 multiple-choice or short-answer questions that test the stated
114
+ lesson objectives (not trivia about the outline);
115
+ * an answer key with a one-line explanation for each answer;
116
+ * difficulty that matches the audience in the brief.
117
+ Reply to the director in outbox/director/ with a summary (questions per
118
+ module) and the path to QUIZZES.md. Cover only modules the outliner defined.
119
+
120
+ - name: workbook
121
+ type: claude
122
+ can_talk_to: [director]
123
+ command: "claude --dangerously-skip-permissions"
124
+ role: |
125
+ You are the WORKBOOK author. Given the OUTLINE.md and the lesson content,
126
+ write the hands-on exercises / worksheets that let a learner practice each
127
+ module, and write them to WORKBOOK.md in your workdir. Each module:
128
+ * 1-3 exercises with clear instructions, any inputs/materials needed, and
129
+ a "what good looks like" check so a learner can self-grade;
130
+ * exercises that build on the lesson's example, not repeat it.
131
+ Reply to the director in outbox/director/ with a summary (exercises per
132
+ module) and the path to WORKBOOK.md. Keep exercise titles aligned with the
133
+ outliner's module names.
@@ -0,0 +1,118 @@
1
+ # =============================================================================
2
+ # 🎫 Customer-support triage -- an INTAKE hub classifies incoming tickets and
3
+ # routes them to the right specialist: billing, technical, or a human-facing
4
+ # escalation handler for angry / churn-risk cases.
5
+ #
6
+ # cp examples/customer-support-triage.yaml my-support.yaml
7
+ # agentainer up -c my-support.yaml
8
+ # agentainer send -c my-support.yaml --to intake "I was double-charged $49 this month and I'm furious."
9
+ # agentainer down -c my-support.yaml
10
+ #
11
+ # The graph is a hub-and-spoke, not a free-for-all: every ticket enters through
12
+ # intake, which decides where it goes. Specialists talk only to intake (so a
13
+ # billing agent can't accidentally reply to the customer); only intake and
14
+ # escalation may write back to the human (user).
15
+ #
16
+ # user
17
+ # │ ticket
18
+ # ▼
19
+ # intake ───────┬───────────┬────────────┐
20
+ # (hub) │ │ │
21
+ # billing technical escalation ──▶ user
22
+ # │ │ │ (angry / churn)
23
+ # └────── back to intake ──┘
24
+ #
25
+ # Key-free: every `command` launches a real coding CLI. For a demo with NO API
26
+ # keys, swap each `command` for a mock bash loop and set `capture: none` -- the
27
+ # routing and ACL mechanics are identical.
28
+ # =============================================================================
29
+
30
+ swarm:
31
+ name: support
32
+ root: ./support-workspace
33
+
34
+ defaults:
35
+ can_talk_to: [] # tightened per agent below
36
+
37
+ agents:
38
+ - name: intake
39
+ type: claude
40
+ can_talk_to: [billing, technical, escalation, user]
41
+ command: "claude --dangerously-skip-permissions"
42
+ role: |
43
+ You are INTAKE -- the front desk of a customer-support team and the only
44
+ hub. Every ticket the customer (user) sends lands in your inbox. For each
45
+ one you do exactly two things: (1) CLASSIFY it, and (2) either answer it
46
+ yourself or ROUTE it to the right specialist.
47
+
48
+ Classify into one of:
49
+ - billing -> charges, refunds, invoices, plan/subscription changes,
50
+ payment failures. Route to `billing`.
51
+ - technical -> bugs, errors, outages, login problems, API/integration
52
+ issues, "it's broken". Route to `technical`.
53
+ - escalation -> the customer is angry, threatening to cancel, a repeat
54
+ complaint, a legal/security concern, or anything a
55
+ specialist shouldn't own alone. Route to `escalation`.
56
+ - trivial -> a one-line factual question you can answer immediately
57
+ (business hours, where to find a setting, how to reset a
58
+ password). Answer it yourself by writing to outbox/user/.
59
+
60
+ When you route, restate the ticket in one crisp paragraph plus the customer
61
+ context you have, and say what a good resolution looks like. When a
62
+ specialist reports back, relay the resolution to the customer (write to
63
+ outbox/user/) in plain, warm language -- the customer never sees the
64
+ handoff. If a specialist asks you for clarification, get it (from the
65
+ ticket, or ask the user) and answer them.
66
+
67
+ MAILBOX: when a message lands in your inbox/, read it and act; when done,
68
+ move it to read/. To send, write a file into outbox/<name>/ (read
69
+ outbox/<name>/about.md first to see who they are and whether they're
70
+ available) and finish your turn. You may message only the agents in your
71
+ can_talk_to: billing, technical, escalation, user.
72
+
73
+ - name: billing
74
+ type: codex
75
+ can_talk_to: [intake]
76
+ command: "codex --yolo"
77
+ role: |
78
+ You are the BILLING specialist. Intake routes you tickets about charges,
79
+ refunds, invoices, subscription/plan changes and failed payments. Resolve
80
+ each one concretely: state the finding (e.g. "duplicate charge on 2026-07-03
81
+ for $49"), the action taken or recommended (refund, proration, plan swap),
82
+ and any next step the customer must take. If the ticket is really a
83
+ technical or angry-escalation case in disguise, say so and hand it back to
84
+ intake -- do not try to own it. Never contact the customer directly; report
85
+ every resolution back by writing a file into outbox/intake/. When a message
86
+ lands in your inbox/, read it, act, then move it to read/.
87
+
88
+ - name: technical
89
+ type: codex
90
+ can_talk_to: [intake]
91
+ command: "codex --yolo"
92
+ role: |
93
+ You are the TECHNICAL specialist. Intake routes you bugs, errors, outages,
94
+ login failures and API/integration problems. Diagnose the issue and give a
95
+ concrete fix or workaround the customer can act on, plus what to do if it
96
+ recurs. If you cannot reproduce or the ticket is missing key facts (version,
97
+ error text, steps, account id), ask intake for clarification by writing to
98
+ outbox/intake/ -- do not guess. If it turns out to be a billing or
99
+ angry-escalation matter, hand it back to intake. Never contact the customer
100
+ directly; report every resolution back by writing a file into
101
+ outbox/intake/. When a message lands in your inbox/, read it, act, then move
102
+ it to read/.
103
+
104
+ - name: escalation
105
+ type: claude
106
+ can_talk_to: [intake, user]
107
+ command: "claude --dangerously-skip-permissions"
108
+ role: |
109
+ You are the ESCALATION handler -- the senior, human-facing owner of hard
110
+ tickets: angry customers, cancellation/churn risk, repeat complaints, and
111
+ anything with legal or security weight. Intake routes these to you. Lead
112
+ with empathy, take ownership, and lay out a concrete remedy and timeline
113
+ (goodwill credit, personal follow-up, root-cause commitment). You are one of
114
+ the two agents who may write to the customer directly: send your reply by
115
+ writing a file into outbox/user/. When the resolution changes a policy or
116
+ needs a specialist's action, coordinate through intake (write to
117
+ outbox/intake/). When a message lands in your inbox/, read it, act, then
118
+ move it to read/. You may message only intake and user.