@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.
- package/.claude/commands/init-maestro.md +304 -8
- package/README.md +28 -0
- package/bin/maestro.mjs +258 -56
- package/docs/guides/agents-observe-setup.md +64 -0
- package/docs/guides/ccxray-diagnostics.md +65 -0
- package/docs/guides/claude-mem-setup.md +79 -0
- package/docs/guides/claude-pace-setup.md +56 -0
- package/docs/guides/claudraband-sessions.md +98 -0
- package/docs/guides/clawteam-swarm.md +116 -0
- package/docs/guides/code-review-graph-setup.md +86 -0
- package/docs/guides/self-optimization-pattern.md +82 -0
- package/docs/guides/slack-setup.md +4 -2
- package/docs/guides/twilio-subaccounts-setup.md +223 -0
- package/docs/guides/webhook-relay-setup.md +349 -0
- package/package.json +2 -1
- package/plugins/maestro-skills/plugin.json +16 -0
- package/plugins/maestro-skills/skills/agents-observe.md +110 -0
- package/plugins/maestro-skills/skills/ccxray-diagnostics.md +91 -0
- package/plugins/maestro-skills/skills/claude-pace.md +61 -0
- package/plugins/maestro-skills/skills/code-review-graph.md +99 -0
- package/scaffold/CLAUDE.md +64 -0
- package/scaffold/config/agent.ts.example +2 -1
- package/scaffold/config/known-agents.json +35 -0
- package/scripts/daemon/classifier.mjs +264 -50
- package/scripts/daemon/dispatcher.mjs +109 -5
- package/scripts/daemon/launchd-wrapper-generic.sh +96 -0
- package/scripts/daemon/launchd-wrapper-slack-events.sh +37 -0
- package/scripts/daemon/launchd-wrapper.sh +91 -0
- package/scripts/daemon/lib/session-router.mjs +274 -0
- package/scripts/daemon/lib/session-router.test.mjs +295 -0
- package/scripts/daemon/prompt-builder.mjs +51 -11
- package/scripts/daemon/responder.mjs +234 -19
- package/scripts/daemon/session-lock.mjs +194 -0
- package/scripts/daemon/sophie-daemon.mjs +16 -2
- package/scripts/email-signature.html +20 -4
- package/scripts/local-triggers/generate-plists.sh +62 -10
- package/scripts/poller/imap-client.mjs +4 -2
- package/scripts/poller/slack-poller.mjs +104 -52
- package/scripts/setup/init-agent.sh +91 -1
- package/scripts/setup/install-dev-tools.sh +150 -0
- package/scripts/spawn-session.sh +21 -6
- package/workflows/continuous/backlog-executor.yaml +141 -0
- package/workflows/daily/evening-wrap.yaml +41 -1
- package/workflows/daily/morning-brief.yaml +17 -0
- package/workflows/event-driven/agent-failure-investigation.yaml +137 -0
- package/workflows/event-driven/pr-review.yaml +104 -0
- 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,
|
|
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
|
-
**
|
|
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
|