@adaptic/maestro 1.1.8 → 1.5.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.
Files changed (47) hide show
  1. package/.claude/commands/init-maestro.md +304 -8
  2. package/README.md +28 -0
  3. package/bin/maestro.mjs +258 -56
  4. package/docs/guides/agents-observe-setup.md +64 -0
  5. package/docs/guides/ccxray-diagnostics.md +65 -0
  6. package/docs/guides/claude-mem-setup.md +79 -0
  7. package/docs/guides/claude-pace-setup.md +56 -0
  8. package/docs/guides/claudraband-sessions.md +98 -0
  9. package/docs/guides/clawteam-swarm.md +116 -0
  10. package/docs/guides/code-review-graph-setup.md +86 -0
  11. package/docs/guides/self-optimization-pattern.md +82 -0
  12. package/docs/guides/slack-setup.md +4 -2
  13. package/docs/guides/twilio-subaccounts-setup.md +223 -0
  14. package/docs/guides/webhook-relay-setup.md +349 -0
  15. package/package.json +2 -1
  16. package/plugins/maestro-skills/plugin.json +16 -0
  17. package/plugins/maestro-skills/skills/agents-observe.md +110 -0
  18. package/plugins/maestro-skills/skills/ccxray-diagnostics.md +91 -0
  19. package/plugins/maestro-skills/skills/claude-pace.md +61 -0
  20. package/plugins/maestro-skills/skills/code-review-graph.md +99 -0
  21. package/scaffold/CLAUDE.md +64 -0
  22. package/scaffold/config/agent.ts.example +2 -1
  23. package/scaffold/config/known-agents.json +35 -0
  24. package/scripts/daemon/classifier.mjs +264 -50
  25. package/scripts/daemon/dispatcher.mjs +109 -5
  26. package/scripts/daemon/launchd-wrapper-generic.sh +96 -0
  27. package/scripts/daemon/launchd-wrapper-slack-events.sh +37 -0
  28. package/scripts/daemon/launchd-wrapper.sh +91 -0
  29. package/scripts/daemon/lib/session-router.mjs +274 -0
  30. package/scripts/daemon/lib/session-router.test.mjs +295 -0
  31. package/scripts/daemon/prompt-builder.mjs +51 -11
  32. package/scripts/daemon/responder.mjs +234 -19
  33. package/scripts/daemon/session-lock.mjs +194 -0
  34. package/scripts/daemon/sophie-daemon.mjs +16 -2
  35. package/scripts/email-signature.html +20 -4
  36. package/scripts/local-triggers/generate-plists.sh +62 -10
  37. package/scripts/poller/imap-client.mjs +4 -2
  38. package/scripts/poller/slack-poller.mjs +104 -52
  39. package/scripts/setup/init-agent.sh +91 -1
  40. package/scripts/setup/install-dev-tools.sh +150 -0
  41. package/scripts/spawn-session.sh +21 -6
  42. package/workflows/continuous/backlog-executor.yaml +141 -0
  43. package/workflows/daily/evening-wrap.yaml +41 -1
  44. package/workflows/daily/morning-brief.yaml +17 -0
  45. package/workflows/event-driven/agent-failure-investigation.yaml +137 -0
  46. package/workflows/event-driven/pr-review.yaml +104 -0
  47. package/workflows/weekly/engineering-health.yaml +154 -0
@@ -0,0 +1,98 @@
1
+ # Claudraband Persistent Sessions Guide
2
+
3
+ Claudraband wraps Claude Code to add persistent sessions, daemon mode with an HTTP API, and programmatic session control. It turns Claude Code from an interactive TUI into a controllable backend service.
4
+
5
+ ## Why It Matters
6
+
7
+ Maestro agents spawn background sessions via `scripts/spawn-session.sh` for complex tasks. The current spawner uses `claude -p` with a timeout — fire-and-forget, no resumption, no mid-flight control. Claudraband adds:
8
+
9
+ - **Persistent sessions**: Run headless, disconnect, reconnect later
10
+ - **Daemon mode**: HTTP API for spawning and managing sessions programmatically
11
+ - **Prompt injection**: Send follow-up prompts to running sessions without restarting
12
+ - **Session lifecycle management**: List, pause, resume, and terminate sessions
13
+
14
+ This is particularly valuable for the backlog executor pattern, where long-running tasks may need mid-flight adjustments.
15
+
16
+ ## Technical Details
17
+
18
+ - TypeScript wrapper around Claude Code
19
+ - HTTP API in daemon mode (default port 7842)
20
+ - ACP server for editor integration
21
+ - Exposes a TypeScript library for custom tooling
22
+ - npx-based — zero permanent installation
23
+
24
+ ## Installation
25
+
26
+ ### Via init-agent (recommended)
27
+
28
+ If you ran `scripts/setup/init-agent.sh`, claudraband is pre-installed globally. Verify:
29
+
30
+ ```bash
31
+ npx @halfwhey/claudraband --version
32
+ ```
33
+
34
+ ### Manual
35
+
36
+ ```bash
37
+ # One-shot usage
38
+ npx @halfwhey/claudraband "your prompt here"
39
+
40
+ # Start daemon
41
+ npx @halfwhey/claudraband serve --port 7842
42
+ ```
43
+
44
+ ## Usage Patterns
45
+
46
+ ### Daemon mode (recommended for Maestro)
47
+
48
+ ```bash
49
+ # Start the daemon
50
+ npx @halfwhey/claudraband serve --port 7842
51
+
52
+ # Create a session
53
+ curl -X POST http://localhost:7842/sessions \
54
+ -H "Content-Type: application/json" \
55
+ -d '{"prompt": "Research competitor X and write a brief"}'
56
+
57
+ # List active sessions
58
+ curl http://localhost:7842/sessions
59
+
60
+ # Inject a follow-up prompt
61
+ npx @halfwhey/claudraband prompt --session <id> "also check their latest SEC filing"
62
+
63
+ # Terminate a session
64
+ curl -X DELETE http://localhost:7842/sessions/<id>
65
+ ```
66
+
67
+ ### Direct usage (quick tasks)
68
+
69
+ ```bash
70
+ npx @halfwhey/claudraband "Draft an email to the board about Q1 results"
71
+ ```
72
+
73
+ ### Integration with spawn-session.sh
74
+
75
+ `scripts/spawn-session.sh` supports an optional `MAESTRO_SESSION_BACKEND` environment variable:
76
+
77
+ - `MAESTRO_SESSION_BACKEND=claude` (default) — uses `claude -p` directly
78
+ - `MAESTRO_SESSION_BACKEND=claudraband` — uses claudraband for persistent, resumable sessions
79
+
80
+ When using the claudraband backend, sessions are registered with the daemon and can be listed, inspected, and controlled via the HTTP API.
81
+
82
+ ## Repository
83
+
84
+ - GitHub: https://github.com/halfwhey/claudraband
85
+ - License: MIT
86
+
87
+ ## Integration with Maestro
88
+
89
+ Claudraband is installed as an optional session backend. The default behaviour (`claude -p`) is unchanged. To enable claudraband:
90
+
91
+ 1. Set `MAESTRO_SESSION_BACKEND=claudraband` in your `.env`
92
+ 2. Ensure the claudraband daemon is running (started automatically by launchd if configured via init-agent)
93
+ 3. Sessions spawned by the backlog executor will use claudraband automatically
94
+
95
+ Benefits for the backlog executor:
96
+ - **Resumable tasks**: If a session times out, it can be resumed rather than restarted
97
+ - **Mid-flight control**: The orchestrator can inject follow-up prompts into running sessions
98
+ - **Session inventory**: HTTP API provides visibility into all active sessions
@@ -0,0 +1,116 @@
1
+ # ClawTeam Swarm Orchestration Guide
2
+
3
+ ClawTeam is a CLI-native swarm orchestrator that uses git worktrees, tmux, and filesystem-based messaging to run multiple coding agents in parallel. It implements a leader/worker pattern where a leader agent manages task creation, dependency chains, spawning, monitoring, and merge.
4
+
5
+ ## Why It Matters
6
+
7
+ When a coding task involves 2+ independent workstreams (e.g., frontend + backend, or multiple microservices), running agents sequentially is slow and wasteful. ClawTeam gives each agent its own git worktree — isolated branch, files, staging area, and process space — eliminating conflicts, corruption, and dependency collisions.
8
+
9
+ ## Key Capabilities
10
+
11
+ - **Leader/worker pattern**: Leader agent manages task graph; workers execute independently
12
+ - **Git worktree isolation**: Each worker gets its own worktree branch
13
+ - **Filesystem messaging**: Point-to-point and broadcast messaging between agents
14
+ - **Task dependencies**: Auto-unblocking when upstream tasks complete
15
+ - **Kanban board**: Terminal and web dashboard for monitoring
16
+ - **Multi-agent support**: Claude Code, Codex, Hermes, nanobot, OpenClaw
17
+
18
+ ## Technical Details
19
+
20
+ - CLI-native and fully automatable (no GUI required)
21
+ - tmux-based worker management
22
+ - MIT licensed
23
+ - Known gaps: task status sync can lag (needs leader-side verification), requires explicit model pinning
24
+
25
+ ## Installation
26
+
27
+ ### Via init-agent
28
+
29
+ If you ran `scripts/setup/init-agent.sh` with `MAESTRO_ENABLE_SWARM=1`, ClawTeam was cloned and configured. Verify:
30
+
31
+ ```bash
32
+ # Check ClawTeam is available
33
+ which clawteam || ls ~/ClawTeam-OpenClaw/clawteam
34
+ ```
35
+
36
+ ### Manual
37
+
38
+ ```bash
39
+ # Clone the repository
40
+ git clone https://github.com/win4r/ClawTeam-OpenClaw.git ~/ClawTeam-OpenClaw
41
+
42
+ # Ensure tmux is installed
43
+ brew install tmux # macOS
44
+ ```
45
+
46
+ ## Usage
47
+
48
+ ### Basic swarm launch
49
+
50
+ ```bash
51
+ cd ~/your-repo
52
+ clawteam start --leader claude --workers 3 --task "Implement user authentication"
53
+ ```
54
+
55
+ ### With task dependencies
56
+
57
+ ```bash
58
+ clawteam start \
59
+ --leader claude \
60
+ --task-file tasks.yaml \
61
+ --workers 4 \
62
+ --model claude-opus-4-6
63
+ ```
64
+
65
+ ### Monitoring
66
+
67
+ ```bash
68
+ # Terminal kanban
69
+ clawteam board
70
+
71
+ # Web dashboard
72
+ clawteam dashboard --port 8080
73
+ ```
74
+
75
+ ### Filesystem messaging
76
+
77
+ Workers communicate via an inbox system in the worktree root:
78
+
79
+ ```bash
80
+ # Leader sends to worker-2
81
+ echo "Priority change: focus on API endpoints first" > .clawteam/inbox/worker-2/msg-001.txt
82
+
83
+ # Worker reads inbox
84
+ cat .clawteam/inbox/self/*.txt
85
+ ```
86
+
87
+ ## Repository
88
+
89
+ - GitHub: https://github.com/win4r/ClawTeam-OpenClaw
90
+ - License: MIT
91
+
92
+ ## Integration with Maestro
93
+
94
+ ClawTeam is an optional module for coding-heavy agents. It is not required for operational agents (Chief of Staff, Legal, Communications) but is valuable for:
95
+
96
+ - **Engineering coordination agents** running parallel coding tasks
97
+ - **Platform architecture agents** implementing across multiple packages
98
+ - **Any agent** where a backlog item involves 2+ independent code changes
99
+
100
+ ### Routing rules
101
+
102
+ The backlog executor can route items to ClawTeam when:
103
+ 1. The task involves code changes to 2+ independent files/packages
104
+ 2. The task is explicitly tagged as `swarm-eligible` in the queue
105
+ 3. The agent's config has `MAESTRO_ENABLE_SWARM=1`
106
+
107
+ ### Post-merge workflow
108
+
109
+ After ClawTeam workers complete, the leader agent:
110
+ 1. Reviews all worker diffs
111
+ 2. Runs tests on each worktree branch
112
+ 3. Merges clean branches to the integration branch
113
+ 4. Produces a structured summary of changes
114
+ 5. Cleans up worktrees
115
+
116
+ This maps naturally to Maestro's session output pattern (`outputs/sessions/{id}/output.md`).
@@ -0,0 +1,86 @@
1
+ # Code-Review-Graph — Structural Knowledge Graph for Codebases
2
+
3
+ Tree-sitter-based knowledge graph mapping functions, classes, imports, and call relationships. Provides MCP tools for blast-radius analysis, review context, architecture overview, and refactor planning.
4
+
5
+ ## Why It Matters
6
+
7
+ When agents review PRs, plan refactors, or assess engineering health, they need structural understanding of the codebase — not just text search. Code-review-graph builds a persistent knowledge graph that auto-updates on file changes, providing:
8
+
9
+ - **Blast-radius analysis** — What breaks if this function changes?
10
+ - **Review context** — What other code depends on this change?
11
+ - **Architecture overview** — How do modules connect?
12
+ - **Semantic search** — Find related functions by call graph, not just name
13
+ - **Refactor planning** — Map dependencies before restructuring
14
+
15
+ ## Installation
16
+
17
+ ### Via install-dev-tools (recommended)
18
+
19
+ ```bash
20
+ ./scripts/setup/install-dev-tools.sh --tool code-review-graph
21
+ ```
22
+
23
+ ### Manual
24
+
25
+ ```bash
26
+ # Global install
27
+ npm install -g code-review-graph
28
+
29
+ # Or via npx (zero-install)
30
+ npx code-review-graph
31
+ ```
32
+
33
+ ## MCP Server Configuration
34
+
35
+ Add to your Claude Code MCP settings (`.claude/settings.json` or project-level):
36
+
37
+ ```json
38
+ {
39
+ "mcpServers": {
40
+ "code-review-graph": {
41
+ "command": "npx",
42
+ "args": ["code-review-graph", "serve", "--port", "3848"],
43
+ "env": {
44
+ "CRG_REPO_PATH": "/path/to/your/repo"
45
+ }
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ ### Build the graph for a repo
54
+
55
+ ```bash
56
+ npx code-review-graph index /path/to/repo
57
+ ```
58
+
59
+ ### Query via MCP tools (from Claude Code)
60
+
61
+ Once configured as an MCP server, Claude Code gains these tools:
62
+ - `blast_radius(file, function)` — Trace all callers and dependents
63
+ - `review_context(diff)` — Generate review context from a diff
64
+ - `architecture_overview()` — High-level module map
65
+ - `semantic_search(query)` — Find related code by structural relationships
66
+
67
+ ### Standalone CLI
68
+
69
+ ```bash
70
+ npx code-review-graph blast-radius --file src/lib/executor.js --function executeAction
71
+ npx code-review-graph overview --repo ~/maestro
72
+ ```
73
+
74
+ ## Integration with Maestro
75
+
76
+ Recommended for coding-oriented agents and workflows:
77
+ - **Engineering health checks** — Use architecture overview to assess repo structure
78
+ - **PR review agents** — Enrich review context with dependency information
79
+ - **Refactoring tasks** — Plan changes with blast-radius awareness
80
+
81
+ Optional for non-coding agents (operational, hiring, comms). Enable per-repo as needed.
82
+
83
+ ## Repository
84
+
85
+ - License: Open source
86
+ - Requires: Tree-sitter (bundled)
@@ -0,0 +1,82 @@
1
+ # Self-Optimization Pattern — AutoAgent-Inspired Framework
2
+
3
+ Standardized pattern for agents to autonomously improve their own configuration, prompts, tools, and routing via benchmark-driven iteration.
4
+
5
+ ## Origin
6
+
7
+ Derived from AutoAgent (https://github.com/kevinrgu/autoagent) and Karpathy's autoresearch pattern. Adapted for Maestro's Node.js/Claude Code stack.
8
+
9
+ ## Pattern Overview
10
+
11
+ ```
12
+ 1. Define a scoring rubric (what "better" means)
13
+ 2. Run the current configuration against test scenarios
14
+ 3. Score the results
15
+ 4. Propose a modification (prompt tweak, tool change, routing rule)
16
+ 5. Run the modification against the same scenarios
17
+ 6. Compare scores — keep if better, revert if worse
18
+ 7. Log the experiment and repeat
19
+ ```
20
+
21
+ ## Implementation in Maestro
22
+
23
+ ### Directory structure
24
+
25
+ Each agent that uses self-optimization maintains:
26
+
27
+ ```
28
+ self-optimization/
29
+ program.md # Current optimization targets and rubrics
30
+ experiments.jsonl # Log of all experiments (timestamp, change, before/after scores)
31
+ scenarios/ # Test scenarios with expected outcomes
32
+ scenario-001.yaml
33
+ scenario-002.yaml
34
+ ```
35
+
36
+ ### Scoring rubrics
37
+
38
+ Define rubrics per optimization target:
39
+
40
+ ```yaml
41
+ # self-optimization/program.md
42
+ targets:
43
+ - name: response-quality
44
+ metric: llm-as-judge score (1-10)
45
+ weight: 0.4
46
+ - name: latency
47
+ metric: seconds to first response
48
+ weight: 0.3
49
+ - name: accuracy
50
+ metric: factual correctness rate
51
+ weight: 0.3
52
+ ```
53
+
54
+ ### Experiment log format
55
+
56
+ ```jsonl
57
+ {"ts":"2026-04-18T12:00:00Z","target":"response-quality","change":"Added chain-of-thought to classifier prompt","before":6.2,"after":7.8,"kept":true}
58
+ {"ts":"2026-04-18T12:30:00Z","target":"latency","change":"Reduced context window by 40%","before":4.1,"after":2.3,"kept":true}
59
+ ```
60
+
61
+ ### When to run
62
+
63
+ - **Quarterly self-assessment** — Formal optimization cycle
64
+ - **After incidents** — Target the specific failure mode
65
+ - **Self-evolution reflection** — End-of-session check for optimization candidates
66
+
67
+ ### Safety
68
+
69
+ - All changes are logged to `logs/evolution/`
70
+ - High-risk changes (identity, permissions, external comms rules) require CEO approval
71
+ - Reverts are automatic if score degrades
72
+ - Classification follows `docs/superpowers/specs/2026-04-02-phase0-operational-foundation-design.md`
73
+
74
+ ## Applicability
75
+
76
+ This pattern is most valuable for:
77
+ - **Classifier prompts** — Improving message routing accuracy
78
+ - **Response templates** — Better quality and tone matching
79
+ - **Tool selection** — More efficient tool use per task type
80
+ - **Queue prioritisation** — Better ranking of actionable items
81
+
82
+ Not recommended for: identity configuration, compliance rules, security policies (these are fixed, not optimised).
@@ -1,8 +1,10 @@
1
1
  # Slack Setup Guide
2
2
 
3
- How to enable Slack integration for a Maestro agent: app creation, token configuration, message sending (with typing indicators), file uploads, emoji reactions, event polling, real-time events server, and Slack CDP for huddle automation.
3
+ How to enable Slack integration for a Maestro agent: dedicated app creation, token configuration, message sending (with typing indicators), file uploads, emoji reactions, real-time events via Railway relay, and Slack CDP for huddle automation.
4
4
 
5
- **Prerequisites**: Complete the [Mac Mini Bootstrap](../runbooks/mac-mini-bootstrap.md). The agent needs a Slack workspace account.
5
+ > **Hard requirement: every agent gets its own dedicated Slack app.** Do NOT share a Slack app across agents. Each app has its own bot user, signing secret, OAuth tokens, and scope set. Sharing breaks identity (messages appear as the wrong agent), confuses signature verification on the webhook relay, and prevents per-agent revocation. The init-maestro wizard creates a new app for each agent via the Slack manifest API.
6
+
7
+ **Prerequisites**: Complete the [Mac Mini Bootstrap](../runbooks/mac-mini-bootstrap.md). The agent needs a Slack workspace account with admin rights to create apps.
6
8
 
7
9
  ---
8
10
 
@@ -0,0 +1,223 @@
1
+ # Twilio Sub-Accounts Setup Guide
2
+
3
+ How to create a dedicated Twilio sub-account for each Maestro agent under a single parent Twilio account. This is required for per-agent WhatsApp segregation because the **Twilio WhatsApp Sandbox webhook is account-wide** — only one URL per Twilio account.
4
+
5
+ **Prerequisites**: A parent Twilio account already exists (the company's root account). You have its `Account SID` and `Auth Token`.
6
+
7
+ ---
8
+
9
+ ## Why sub-accounts?
10
+
11
+ Each agent runs as a separate identity (Lucas, Jacob, Sophie, etc.) and needs:
12
+
13
+ - Its own phone number (for SMS)
14
+ - Its own WhatsApp sandbox webhook URL (the constraint)
15
+ - Its own auth token (so the agent's webhook relay can verify Twilio HMAC signatures independently)
16
+ - Its own usage logs and cost attribution
17
+
18
+ Sub-accounts give you all of this while still rolling up to the parent account for billing.
19
+
20
+ | Constraint | Sharing parent account | Per-agent sub-account |
21
+ |---|---|---|
22
+ | WhatsApp sandbox webhook | One URL for ALL agents — only the latest agent's webhook works | Each agent has their own sandbox + webhook |
23
+ | Phone numbers | Mixed across agents on one account | Each agent has their own |
24
+ | Auth Token | Shared — every agent's relay can verify everything (security risk) | Per-agent token, isolated verification |
25
+ | Cost attribution | Aggregated — hard to attribute to a specific agent | Sub-account usage rolls up but is separately reportable |
26
+ | Suspension | Suspending the parent kills all agents | Suspend just the affected agent |
27
+
28
+ ---
29
+
30
+ ## 1. Create the sub-account
31
+
32
+ Run from the agent's repo (or anywhere with `TWILIO_PARENT_ACCOUNT_SID` and `TWILIO_PARENT_AUTH_TOKEN` set):
33
+
34
+ ```bash
35
+ TWILIO_PARENT_ACCOUNT_SID=AC... # parent
36
+ TWILIO_PARENT_AUTH_TOKEN=... # parent
37
+ AGENT_NAME="lucas-ferreira-adaptic" # whatever friendly name you want
38
+
39
+ curl -s -u "$TWILIO_PARENT_ACCOUNT_SID:$TWILIO_PARENT_AUTH_TOKEN" -X POST \
40
+ "https://api.twilio.com/2010-04-01/Accounts.json" \
41
+ --data-urlencode "FriendlyName=$AGENT_NAME" \
42
+ | python3 -m json.tool
43
+ ```
44
+
45
+ Capture from the response:
46
+
47
+ - `sid` — the new sub-account SID (starts with `AC...`)
48
+ - `auth_token` — the sub-account's auth token (use this for HMAC verification on the agent's webhook relay)
49
+ - `owner_account_sid` — confirms it's a child of the parent account
50
+
51
+ Save both to the agent's `.env`:
52
+
53
+ ```bash
54
+ # Lucas's dedicated Twilio sub-account
55
+ TWILIO_ACCOUNT_SID=ACf2... # the new sub-account SID
56
+ TWILIO_AUTH_TOKEN=c1da... # the new sub-account auth token
57
+
58
+ # Parent account — only used for sub-account management API calls
59
+ TWILIO_PARENT_ACCOUNT_SID=AC36...
60
+ TWILIO_PARENT_AUTH_TOKEN=af86...
61
+ ```
62
+
63
+ ---
64
+
65
+ ## 2. Buy a phone number under the sub-account
66
+
67
+ Search for available numbers:
68
+
69
+ ```bash
70
+ source .env
71
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" \
72
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/AvailablePhoneNumbers/US/Local.json?AreaCode=628&SmsEnabled=true&VoiceEnabled=true&PageSize=5"
73
+ ```
74
+
75
+ Buy one (irreversible — costs ~$1.15/mo + per-message charges):
76
+
77
+ ```bash
78
+ PHONE="+16283454599"
79
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" -X POST \
80
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/IncomingPhoneNumbers.json" \
81
+ --data-urlencode "PhoneNumber=$PHONE" \
82
+ --data-urlencode "FriendlyName=Lucas Ferreira - Adaptic"
83
+ ```
84
+
85
+ Save the returned `sid` (starts with `PN...`) to `.env` as `TWILIO_PHONE_SID`.
86
+
87
+ ### Transferring an existing number from the parent
88
+
89
+ If the agent already has a number under the parent account that you want to move to the sub-account:
90
+
91
+ ```bash
92
+ PARENT_SID="AC36..." # parent account SID
93
+ PARENT_AUTH="af86..." # parent account auth token
94
+ PHONE_SID="PN1eb30e..." # the number to move
95
+ SUBACCOUNT_SID="ACf2..." # destination sub-account
96
+
97
+ curl -s -u "$PARENT_SID:$PARENT_AUTH" -X POST \
98
+ "https://api.twilio.com/2010-04-01/Accounts/$PARENT_SID/IncomingPhoneNumbers/$PHONE_SID.json" \
99
+ --data-urlencode "AccountSid=$SUBACCOUNT_SID"
100
+ ```
101
+
102
+ The number, all its webhook configuration, and message history move to the sub-account in one API call.
103
+
104
+ ---
105
+
106
+ ## 3. Configure the SMS webhook
107
+
108
+ After the sub-account owns the number, configure the SMS webhook to point at the agent's Railway webhook relay:
109
+
110
+ ```bash
111
+ source .env
112
+ RELAY_URL="https://${AGENT_FIRSTNAME_LOWER}-webhook-relay-production.up.railway.app"
113
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" -X POST \
114
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/IncomingPhoneNumbers/$TWILIO_PHONE_SID.json" \
115
+ --data-urlencode "SmsUrl=$RELAY_URL/sms" \
116
+ --data-urlencode "SmsMethod=POST"
117
+ ```
118
+
119
+ ---
120
+
121
+ ## 4. Configure the WhatsApp sandbox
122
+
123
+ This is the whole reason we use sub-accounts. Each sub-account has its own independent WhatsApp sandbox.
124
+
125
+ **Important**: WhatsApp sandbox webhook configuration is **UI-only** — Twilio does not expose an API for this. You must use Playwright or the user must configure it manually.
126
+
127
+ 1. Log in to the Twilio Console (the sandbox UI uses a different login session than the API)
128
+ 2. **Switch to the sub-account** via the account selector top-left (the dropdown shows all sub-accounts under the parent)
129
+ 3. Navigate to: `https://console.twilio.com/us1/develop/sms/try-it-out/whatsapp-learn?frameUrl=%2Fconsole%2Fsms%2Fwhatsapp%2Flearn`
130
+ 4. Click **Sandbox settings** tab
131
+ 5. Set the inbound webhook URL: `https://{firstname}-webhook-relay-production.up.railway.app/whatsapp`
132
+ 6. Set the status callback URL: `https://{firstname}-webhook-relay-production.up.railway.app/whatsapp/status`
133
+ 7. Set both methods to HTTP POST
134
+ 8. Save
135
+
136
+ Note the **sandbox join code** shown on the page (e.g. `join follow-arm`). Users must send `join {code}` from their WhatsApp to `+1 415 523 8886` to enroll their number for testing with this agent's sandbox.
137
+
138
+ ### Production WhatsApp (post-sandbox)
139
+
140
+ For production WhatsApp (real WABA business number, not the shared sandbox number), each sub-account can register its own WABA. This requires Facebook Business verification per sub-account — Twilio provides a self-sign-up flow at https://www.twilio.com/docs/whatsapp/self-sign-up. Same pattern: each agent's sub-account → its own WABA → its own webhook URL.
141
+
142
+ ---
143
+
144
+ ## 5. Update the Railway webhook relay
145
+
146
+ The agent's relay verifies Twilio HMAC signatures using the sub-account's auth token (NOT the parent's). After creating the sub-account, update the Railway env var:
147
+
148
+ ```bash
149
+ source .env
150
+ cd services/webhook-relay
151
+ railway variables --service ${AGENT_FIRSTNAME_LOWER}-webhook-relay \
152
+ --set "TWILIO_AUTH_TOKEN=$TWILIO_AUTH_TOKEN"
153
+ railway up --service ${AGENT_FIRSTNAME_LOWER}-webhook-relay --detach
154
+ ```
155
+
156
+ Wait until `/health` reports `twilio_signature: true` again.
157
+
158
+ ---
159
+
160
+ ## 6. Add to init-maestro Phase 4
161
+
162
+ When `/init-maestro` runs Phase 4 Service Configuration, the Twilio step should:
163
+
164
+ 1. Check whether `TWILIO_PARENT_ACCOUNT_SID` is set in `.env` (from a previous agent's setup or org config)
165
+ 2. If yes: create a sub-account for this agent via the API (Step 1 above), then bypass the "buy new account" flow
166
+ 3. If no: this is the first agent in the org — use `TWILIO_ACCOUNT_SID` as both parent and main, and document that future agents will need sub-accounts under it
167
+ 4. Buy a phone number under the sub-account
168
+ 5. Configure SMS webhook → Railway
169
+ 6. (Manual or Playwright) Configure WhatsApp sandbox → Railway
170
+
171
+ ---
172
+
173
+ ## Verification
174
+
175
+ ```bash
176
+ # 1. Sub-account exists and is active
177
+ source .env
178
+ curl -s -u "$TWILIO_PARENT_ACCOUNT_SID:$TWILIO_PARENT_AUTH_TOKEN" \
179
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID.json" \
180
+ | python3 -m json.tool
181
+
182
+ # 2. Phone number is owned by the sub-account
183
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" \
184
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/IncomingPhoneNumbers.json"
185
+
186
+ # 3. SMS webhook points at Railway
187
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" \
188
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/IncomingPhoneNumbers/$TWILIO_PHONE_SID.json" \
189
+ | python3 -c "import sys,json; d=json.load(sys.stdin); print('SMS URL:', d.get('sms_url'))"
190
+
191
+ # 4. Send a test SMS using the sub-account credentials
192
+ bash scripts/send-sms.sh --to "+1...your_test_number" --body "Sub-account test from {AgentName}"
193
+
194
+ # 5. Send a WhatsApp message after joining the sandbox
195
+ bash scripts/send-whatsapp.sh --to "whatsapp:+1...your_number" --body "WhatsApp test from {AgentName}"
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Closing / suspending a sub-account
201
+
202
+ When an agent is decommissioned:
203
+
204
+ ```bash
205
+ source .env
206
+ curl -s -u "$TWILIO_PARENT_ACCOUNT_SID:$TWILIO_PARENT_AUTH_TOKEN" -X POST \
207
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID.json" \
208
+ --data-urlencode "Status=closed"
209
+ ```
210
+
211
+ Closing is irreversible. Use `Status=suspended` for temporary suspension (can be reactivated).
212
+
213
+ Before closing, decide what to do with the agent's phone number:
214
+ - Transfer back to the parent account (if you want to retain the number for re-use)
215
+ - Release it (Twilio will free up the number, you stop being charged)
216
+
217
+ ---
218
+
219
+ ## Related guides
220
+
221
+ - [Webhook Relay Setup](webhook-relay-setup.md) — How the Railway relay uses `TWILIO_AUTH_TOKEN` to verify HMAC signatures
222
+ - [Voice & SMS Setup](voice-sms-setup.md) — End-to-end SMS pipeline
223
+ - [WhatsApp Setup](whatsapp-setup.md) — Sandbox vs production WhatsApp