@adaptic/maestro 1.1.7 → 1.4.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.
- package/.claude/commands/init-maestro.md +502 -260
- package/README.md +47 -2
- package/bin/maestro.mjs +1 -1
- 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/email-setup.md +399 -0
- package/docs/guides/media-generation-setup.md +349 -0
- package/docs/guides/outbound-governance-setup.md +438 -0
- package/docs/guides/pdf-generation-setup.md +315 -0
- package/docs/guides/poller-daemon-setup.md +550 -0
- package/docs/guides/rag-context-setup.md +459 -0
- package/docs/guides/self-optimization-pattern.md +82 -0
- package/docs/guides/slack-setup.md +350 -0
- package/docs/guides/twilio-subaccounts-setup.md +223 -0
- package/docs/guides/voice-sms-setup.md +698 -0
- package/docs/guides/webhook-relay-setup.md +349 -0
- package/docs/guides/whatsapp-setup.md +282 -0
- package/docs/runbooks/mac-mini-bootstrap.md +21 -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/caller-id-map.yaml +46 -0
- 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/media-generation/README.md +2 -0
- package/scripts/pdf-generation/README.md +2 -0
- package/scripts/poller/imap-client.mjs +4 -2
- package/scripts/poller/slack-poller.mjs +126 -59
- package/scripts/poller/trigger.mjs +12 -1
- 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
|
@@ -297,7 +297,7 @@ Do NOT modify these sections (keep them exactly as they are, except for agent na
|
|
|
297
297
|
- product-leader: product roadmap, user research, feature delivery, product-market fit, design system
|
|
298
298
|
- operations-leader: process automation, operational efficiency, fund operations, organisational design, vendor management
|
|
299
299
|
|
|
300
|
-
### Sub-agent 4: Update package.json and
|
|
300
|
+
### Sub-agent 4: Update package.json, scripts, and identity-baked content
|
|
301
301
|
|
|
302
302
|
**Instruction to sub-agent:**
|
|
303
303
|
|
|
@@ -307,9 +307,57 @@ Do NOT modify these sections (keep them exactly as they are, except for agent na
|
|
|
307
307
|
- Variable names like `SOPHIE_AI_DIR` -> `{UPPER_FIRSTNAME}_AI_DIR`
|
|
308
308
|
- Path references like `/Users/sophie/sophie-ai` -> `/Users/{lowercase-firstname}/{repoSlug}`
|
|
309
309
|
- LaunchD labels like `ai.adaptic.sophie-` -> `ai.adaptic.{lowercase-firstname}-`
|
|
310
|
+
- Pronouns: if the new agent's gender differs from the scaffolding template, update he/she/him/her/his/hers/himself/herself across system prompts, comments, and documentation. Be surgical — do NOT change pronouns inside generic regex patterns or third-party detection logic.
|
|
310
311
|
|
|
311
312
|
3. **LaunchD plists** in `scripts/local-triggers/plists/` -- Update labels and paths in all `.plist` files.
|
|
312
313
|
|
|
314
|
+
4. **Identity-baked content rewrites (CRITICAL — full overwrites, not grep-replace).** These files contain the agent's outbound identity (name, title, email, phone, signature) and MUST be fully rewritten with the new agent's values. Do not rely on grep-replace alone — read each file, then OVERWRITE it with content that uses these exact values:
|
|
315
|
+
|
|
316
|
+
- `firstName + lastName` (e.g., "Lucas Ferreira")
|
|
317
|
+
- `title` (e.g., "VP, Regulatory & Licensing")
|
|
318
|
+
- `email` (e.g., "lucas@adaptic.ai")
|
|
319
|
+
- `phone` (e.g., "+61 478 964 324" — use the spaced pretty form for human-facing display, the E.164 form for code)
|
|
320
|
+
- `companyName` (e.g., "Adaptic.ai")
|
|
321
|
+
- `companyAddress` (use the company's primary office address — typically Adaptic's DIFC office unless explicitly different)
|
|
322
|
+
|
|
323
|
+
**Files to rewrite:**
|
|
324
|
+
|
|
325
|
+
a. **`scripts/email-signature.html`** — The HTML signature appended to all outbound emails by `send-email.sh` and the Python send scripts. Must contain: name (bold, 14px), title (grey, 13px), Adaptic logo (`https://adaptic.ai/logo.png`), email, phone, company address line, full confidentiality disclaimer footer. Pattern matches the template in `~/maestro/scripts/email-signature.html` — use placeholders {{AGENT_NAME}}, {{AGENT_TITLE}}, {{AGENT_EMAIL}}, {{AGENT_PHONE}}, {{COMPANY_ADDRESS}} and substitute them.
|
|
326
|
+
|
|
327
|
+
b. **`scripts/email-signature-mehran.html`** — Principal's signature block (used by `send-email-as-mehran.py` or equivalent send-as-principal scripts). Update with the principal's values: `principal.fullName`, `principal.title`, `principal.email`. If the principal doesn't have a phone in config/agent.ts, omit the phone line.
|
|
328
|
+
|
|
329
|
+
c. **`scripts/send-email.sh`** — Hardcoded `From:` header and inline signature fallback. Update both. The From header should be in the form `"Lucas Ferreira" <lucas@adaptic.ai>`.
|
|
330
|
+
|
|
331
|
+
d. **`scripts/send-email-threaded.py`** — `USER`, `From` header construction, inline signature, argparse description. All must reflect the new agent.
|
|
332
|
+
|
|
333
|
+
e. **`scripts/send-email-with-attachment.py`** — Same as above.
|
|
334
|
+
|
|
335
|
+
f. **`scripts/pdf-generation/build-document.mjs`** — Default `author` value (used in PDF metadata) and the help text describing the default. Set to the new agent's full name.
|
|
336
|
+
|
|
337
|
+
g. **`scripts/pdf-generation/templates/memo.latex`** — Footer line "Prepared by ... Chief of Staff" — replace with "Prepared by {fullName}, {title}".
|
|
338
|
+
|
|
339
|
+
h. **`scripts/daemon/responder.mjs` `FALLBACK_PREAMBLE`** — System prompt that introduces the agent to Claude. Identity intro line must reference the new agent. Preserve the operational rules.
|
|
340
|
+
|
|
341
|
+
i. **`scripts/daemon/prompt-builder.mjs` `FALLBACK_PREAMBLE`** — Same treatment.
|
|
342
|
+
|
|
343
|
+
j. **`scripts/daemon/classifier.mjs` `SYSTEM_PROMPT`** — Identity intro line. Preserve everything else.
|
|
344
|
+
|
|
345
|
+
k. **`scripts/huddle/huddle-server.mjs` `HUDDLE_SYSTEM_PROMPT`** — Voice agent identity line.
|
|
346
|
+
|
|
347
|
+
l. **`scripts/spawn-session.sh`** — Sub-session bootstrap prompt that names the agent.
|
|
348
|
+
|
|
349
|
+
m. **`scripts/continuous-monitor.sh`** — Channel monitor agent prompt.
|
|
350
|
+
|
|
351
|
+
n. **`scripts/llm_email_dedup.py`, `scripts/comms-monitor.sh`, `scripts/archive-email.sh`, `scripts/poller/gmail-poller.mjs`, `scripts/poller/imap-client.mjs`** — Hardcoded `LUCAS_EMAIL`/`USER`/`gmail_user` constants. Set to the new agent's email.
|
|
352
|
+
|
|
353
|
+
o. **`scripts/{firstname}-inbox-poller.py`** — Rename file from `sophie-inbox-poller.py` (or current scaffolding name) to `{firstname}-inbox-poller.py`. Update internal `LUCAS_EMAIL` constant. Update any plist references to the new filename.
|
|
354
|
+
|
|
355
|
+
p. **`scripts/rag-indexer.py`, `scripts/user-context-search.py`** — Author docstring at the top. Set to the new agent's full name.
|
|
356
|
+
|
|
357
|
+
q. **`scripts/validate-outbound.py`** — Three test/regex references to "Sophie Nguyen" or `lookup_entity("Sophie Nguyen")`. Replace with the new agent's full name. Leave the generic third-party pronoun regex (around line 1007) UNCHANGED — it's a detector, not an identity reference.
|
|
358
|
+
|
|
359
|
+
**Verification step**: After rewrites, run `grep -rn "sophie@adaptic\|Sophie Nguyen\|Chief of Staff" scripts/ docs/business-synthesis/executive-operating-model.md 2>&1` and confirm only intentional peer references remain (Sophie Nguyen as a real Chief of Staff peer, NOT as the agent's own outbound identity). Report any remaining matches you couldn't safely auto-resolve so the main agent can decide.
|
|
360
|
+
|
|
313
361
|
### Sub-agent 5: Update agent definitions
|
|
314
362
|
|
|
315
363
|
**Instruction to sub-agent:**
|
|
@@ -436,359 +484,556 @@ If yes, run:
|
|
|
436
484
|
sudo ./scripts/setup/configure-macos.sh
|
|
437
485
|
```
|
|
438
486
|
|
|
439
|
-
|
|
487
|
+
### Step 4: External SSD configuration (REQUIRED if /Volumes/{name}-SSD is mounted)
|
|
440
488
|
|
|
441
|
-
|
|
489
|
+
The maestro daemon and its launchd-spawned trigger jobs should write all runtime data — Claude Code per-cwd temp dirs, daemon logs, state, outputs, memory, knowledge — to an external SSD when one is available. This keeps the internal disk free for macOS and avoids wear on the system disk.
|
|
442
490
|
|
|
443
|
-
|
|
491
|
+
**Two macOS hurdles need to be cleared before the SSD redirect actually works for launchd-spawned processes:**
|
|
444
492
|
|
|
445
|
-
|
|
446
|
-
- Twilio WhatsApp sandbox configuration (if TWILIO_ACCOUNT_SID is in .env)
|
|
447
|
-
- Cloudflare tunnel creation (via `cloudflared` CLI if installed)
|
|
448
|
-
- ElevenLabs voice clone setup (via API if ELEVENLABS_API_KEY is in .env)
|
|
449
|
-
- Railway service deployment (via `railway` CLI if installed)
|
|
493
|
+
#### 4a. Enable file ownership on the volume
|
|
450
494
|
|
|
451
|
-
|
|
452
|
-
- Slack app creation and token generation
|
|
453
|
-
- Gmail app password generation
|
|
454
|
-
- Twilio phone number purchase
|
|
455
|
-
- Parsec account login (first time only)
|
|
495
|
+
By default, external volumes have Owners disabled, which makes file permissions advisory rather than enforced. The daemon's wrapper writes per-agent log files, and that requires real owners.
|
|
456
496
|
|
|
457
|
-
|
|
497
|
+
Detect the SSD and enable owners:
|
|
498
|
+
|
|
499
|
+
```bash
|
|
500
|
+
SSD_VOLUME=""
|
|
501
|
+
for v in /Volumes/*-SSD /Volumes/*SSD* /Volumes/maestro-data; do
|
|
502
|
+
if [ -d "$v" ] && [ "$v" != "/Volumes/Macintosh HD" ]; then SSD_VOLUME="$v"; break; fi
|
|
503
|
+
done
|
|
458
504
|
|
|
505
|
+
if [ -n "$SSD_VOLUME" ]; then
|
|
506
|
+
# Tell the user we found an SSD and need sudo to enable owners
|
|
507
|
+
echo "Found external SSD at $SSD_VOLUME — enabling file ownership."
|
|
508
|
+
echo "Please run this in your terminal (it needs sudo):"
|
|
509
|
+
echo " sudo diskutil enableOwnership \"$SSD_VOLUME\""
|
|
510
|
+
echo "Reply 'done' when complete."
|
|
511
|
+
fi
|
|
459
512
|
```
|
|
460
|
-
Let's set up Slack integration.
|
|
461
513
|
|
|
462
|
-
|
|
463
|
-
same workspace. Each agent needs its own bot token and user token, but they
|
|
464
|
-
can share the same app configuration.
|
|
514
|
+
Wait for the user to confirm. Then verify:
|
|
465
515
|
|
|
466
|
-
|
|
467
|
-
|
|
516
|
+
```bash
|
|
517
|
+
diskutil info "$SSD_VOLUME" | grep "Owners" | grep -q "Enabled" && echo "OK" || echo "FAIL"
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
#### 4b. Grant Full Disk Access to bash and node (TCC)
|
|
468
521
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
5. Install the app to your workspace
|
|
484
|
-
6. Copy the Bot User OAuth Token (xoxb-...)
|
|
485
|
-
7. Copy the User OAuth Token (xoxp-...)
|
|
486
|
-
|
|
487
|
-
For Slack Events API (real-time messages instead of polling):
|
|
488
|
-
8. Under "Event Subscriptions", enable events
|
|
489
|
-
9. Set Request URL to your Cloudflare tunnel URL + /slack/events
|
|
490
|
-
10. Subscribe to bot events: message.channels, message.groups, message.im,
|
|
491
|
-
app_mention, reaction_added
|
|
492
|
-
11. Copy the Signing Secret from "Basic Information"
|
|
522
|
+
Even with owners enabled, **macOS TCC blocks launchd-spawned processes from writing to /Volumes/ unless the binary has Full Disk Access**. This is the single most common cause of "Operation not permitted" errors when you run a daemon under launchd that tries to write to an external volume.
|
|
523
|
+
|
|
524
|
+
You cannot grant Full Disk Access programmatically without disabling SIP (which is unsafe). The user must do this via System Settings UI:
|
|
525
|
+
|
|
526
|
+
```
|
|
527
|
+
1. Open System Settings → Privacy & Security → Full Disk Access
|
|
528
|
+
2. Click the + button
|
|
529
|
+
3. Press Cmd+Shift+G to "Go to Folder", then enter:
|
|
530
|
+
/bin/bash
|
|
531
|
+
Press Enter, select 'bash', click Open
|
|
532
|
+
4. Click + again, then:
|
|
533
|
+
/usr/bin/node OR ~/.nvm/versions/node/v24.11.1/bin/node
|
|
534
|
+
(whichever node binary the wrapper uses)
|
|
535
|
+
5. Make sure both toggles are ON
|
|
493
536
|
|
|
494
|
-
|
|
495
|
-
Bot token (xoxb-...):
|
|
496
|
-
User token (xoxp-...):
|
|
497
|
-
Signing secret (optional):
|
|
537
|
+
The toggles take effect immediately. No restart needed.
|
|
498
538
|
```
|
|
499
539
|
|
|
500
|
-
|
|
540
|
+
After the user confirms, test that launchd can now write to the SSD:
|
|
501
541
|
|
|
502
|
-
|
|
542
|
+
```bash
|
|
543
|
+
cat > /tmp/ssd-tcc-test.plist <<EOF
|
|
544
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
545
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
546
|
+
<plist version="1.0">
|
|
547
|
+
<dict>
|
|
548
|
+
<key>Label</key><string>ai.adaptic.ssd-tcc-test</string>
|
|
549
|
+
<key>ProgramArguments</key><array>
|
|
550
|
+
<string>/bin/bash</string><string>-c</string>
|
|
551
|
+
<string>touch "$SSD_VOLUME/.tcc-test" && echo "ok=$?" > /tmp/ssd-tcc-result.log || echo "fail=$?" > /tmp/ssd-tcc-result.log</string>
|
|
552
|
+
</array>
|
|
553
|
+
<key>RunAtLoad</key><true/>
|
|
554
|
+
</dict>
|
|
555
|
+
</plist>
|
|
556
|
+
EOF
|
|
557
|
+
launchctl load /tmp/ssd-tcc-test.plist
|
|
558
|
+
sleep 2
|
|
559
|
+
cat /tmp/ssd-tcc-result.log
|
|
560
|
+
launchctl unload /tmp/ssd-tcc-test.plist
|
|
561
|
+
rm -f "$SSD_VOLUME/.tcc-test"
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
If you see `ok=0`, TCC is configured correctly and the daemon can use the SSD. If you see `fail=1`, TCC is still blocking — repeat the System Settings step and make sure the toggles are ON.
|
|
565
|
+
|
|
566
|
+
#### 4c. Set up SSD layout and symlinks
|
|
503
567
|
|
|
504
|
-
|
|
568
|
+
```bash
|
|
569
|
+
AGENT_NAME="$(grep firstName config/agent.ts | head -1 | sed 's/.*[\x27\"]\([a-zA-Z]*\)[\x27\"].*/\1/' | tr A-Z a-z)"
|
|
570
|
+
SSD_AGENT_ROOT="$SSD_VOLUME/maestro/$AGENT_NAME"
|
|
571
|
+
mkdir -p "$SSD_AGENT_ROOT"/{state,outputs,memory,knowledge,claude-tmp,logs,tmp}
|
|
572
|
+
|
|
573
|
+
# Symlink runtime data dirs from the agent repo to the SSD.
|
|
574
|
+
# IMPORTANT: do NOT symlink logs/ — launchd's StandardErrorPath cannot follow
|
|
575
|
+
# symlinks to external volumes. The daemon's wrapper writes its own log file
|
|
576
|
+
# directly to the SSD via shell redirection (see launchd-wrapper.sh).
|
|
577
|
+
for d in state outputs memory knowledge; do
|
|
578
|
+
if [ -d "$d" ] && [ ! -L "$d" ]; then
|
|
579
|
+
rsync -a "$d/" "$SSD_AGENT_ROOT/$d/"
|
|
580
|
+
rm -rf "$d"
|
|
581
|
+
ln -sfn "$SSD_AGENT_ROOT/$d" "$d"
|
|
582
|
+
fi
|
|
583
|
+
done
|
|
505
584
|
|
|
585
|
+
# Create internal-disk logs/ as a real directory (NOT a symlink)
|
|
586
|
+
mkdir -p logs/{daemon,polling,workflows,sessions,audit,security,evolution,huddle,infra,monitor,phone,sms,whatsapp,email,launchd,cloudflared}
|
|
506
587
|
```
|
|
507
|
-
Let's set up Gmail.
|
|
508
588
|
|
|
509
|
-
|
|
510
|
-
(The poller connects via IMAP — not OAuth — so app passwords are simpler.)
|
|
589
|
+
The wrapper scripts (`scripts/daemon/launchd-wrapper.sh` and `launchd-wrapper-generic.sh`) handle the runtime side: they detect the SSD, set `CLAUDE_CODE_TMPDIR`, and redirect daemon stdout/stderr to a log file on the SSD. They gracefully fall back to internal-disk paths if the SSD isn't writable (e.g. if TCC isn't granted yet).
|
|
511
590
|
|
|
512
|
-
|
|
513
|
-
2. Enable 2-Factor Authentication if not already enabled
|
|
514
|
-
3. Go to https://myaccount.google.com/apppasswords
|
|
515
|
-
4. Generate an app password for "Mail" on "Mac"
|
|
516
|
-
5. Copy the 16-character password (no spaces)
|
|
591
|
+
#### 4d. Verify
|
|
517
592
|
|
|
518
|
-
|
|
593
|
+
```bash
|
|
594
|
+
# Daemon should now be writing to the SSD log file
|
|
595
|
+
launchctl unload ~/Library/LaunchAgents/ai.adaptic.${AGENT_NAME}-daemon.plist
|
|
596
|
+
launchctl load ~/Library/LaunchAgents/ai.adaptic.${AGENT_NAME}-daemon.plist
|
|
597
|
+
sleep 4
|
|
598
|
+
ls -la "$SSD_AGENT_ROOT/logs/daemon/" | tail -5
|
|
599
|
+
ls -la "$SSD_AGENT_ROOT/state/inbox/" | tail -5
|
|
519
600
|
```
|
|
520
601
|
|
|
521
|
-
|
|
602
|
+
You should see the daemon log file growing and inbox directories populating. If you don't, repeat steps 4a–4b (most often it's TCC).
|
|
522
603
|
|
|
523
|
-
|
|
524
|
-
```
|
|
525
|
-
Does {principalName} want this agent to monitor their inbox too?
|
|
526
|
-
If yes, generate an app password for {principalEmail} using the same steps above.
|
|
604
|
+
## Phase 4: Autonomous Service Configuration
|
|
527
605
|
|
|
528
|
-
|
|
529
|
-
```
|
|
606
|
+
This phase sets up all third-party integrations **autonomously**. Use Playwright MCP for web-based setup (Slack API portal, Twilio Console, Google Account, ElevenLabs, Deepgram) and Bash for local scripts. Only ask the user for input when genuinely required (existing credentials, 2FA codes, payment authorisation).
|
|
530
607
|
|
|
531
|
-
|
|
608
|
+
**Tooling:**
|
|
609
|
+
- **Playwright MCP** (`mcp__plugin_playwright_playwright__browser_navigate`, `browser_click`, `browser_fill_form`, `browser_snapshot`, etc.) for all web UI interactions
|
|
610
|
+
- **Bash** for local scripts, CLI tools, file writes, service starts
|
|
611
|
+
- If a web UI requires authentication the agent doesn't have, ask the user to log in via `! open <url>` then resume automation once they confirm they're logged in
|
|
532
612
|
|
|
533
|
-
|
|
613
|
+
**Implementation guides**: Each service has a detailed guide in `docs/guides/`. Follow the guide's steps exactly during setup. Reference the guide's troubleshooting section if something fails.
|
|
534
614
|
|
|
535
|
-
|
|
536
|
-
Does this agent need phone/SMS/WhatsApp capabilities? (yes/no)
|
|
537
|
-
```
|
|
615
|
+
### Step 0: Ask what services this agent needs
|
|
538
616
|
|
|
539
|
-
If yes:
|
|
540
617
|
```
|
|
541
|
-
|
|
542
|
-
1. Sign up at https://www.twilio.com/ (or use existing account)
|
|
543
|
-
2. From the Console dashboard, copy:
|
|
544
|
-
- Account SID (starts with AC...)
|
|
545
|
-
- Auth Token
|
|
546
|
-
3. Buy a phone number: Console → Phone Numbers → Buy a Number
|
|
547
|
-
- Select a number with SMS + Voice capabilities
|
|
548
|
-
- Copy the phone number (E.164 format, e.g., +15551234567)
|
|
549
|
-
- Copy the Phone SID (starts with PN...)
|
|
618
|
+
Which services does this agent need? Select all that apply:
|
|
550
619
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
620
|
+
[1] Slack (messaging, events, typing indicators)
|
|
621
|
+
[2] Gmail (email send/receive via IMAP/SMTP)
|
|
622
|
+
[3] Twilio SMS (inbound/outbound text messaging)
|
|
623
|
+
[4] Twilio WhatsApp (inbound/outbound WhatsApp)
|
|
624
|
+
[5] Voice / Huddle (Deepgram STT + ElevenLabs TTS)
|
|
625
|
+
[6] Cloudflare Tunnels (public webhook URLs — needed if 3/4/5 selected)
|
|
626
|
+
[7] Gemini / Veo (AI image + video generation)
|
|
627
|
+
[8] All of the above
|
|
628
|
+
[9] Minimal (Slack + Gmail only)
|
|
557
629
|
|
|
558
|
-
|
|
559
|
-
```
|
|
560
|
-
Would you like me to configure the Twilio WhatsApp sandbox automatically? (yes/no)
|
|
630
|
+
Which? (comma-separated numbers, or "all" / "minimal")
|
|
561
631
|
```
|
|
562
632
|
|
|
563
|
-
|
|
633
|
+
Then execute each selected service. For services with existing credentials, ask the user to paste them. For new accounts, drive the web UI via Playwright.
|
|
634
|
+
|
|
635
|
+
### Step 1: Slack — per `docs/guides/slack-setup.md`
|
|
636
|
+
|
|
637
|
+
**If user has existing tokens:** ask for xoxb- and xoxp- tokens, write to `.env`.
|
|
638
|
+
|
|
639
|
+
**If creating new app — execute via Playwright:**
|
|
640
|
+
|
|
641
|
+
1. `browser_navigate` to `https://api.slack.com/apps`
|
|
642
|
+
2. `browser_snapshot` to check auth — if not logged in, ask user: `! open https://api.slack.com/apps` and log in, then resume
|
|
643
|
+
3. Click "Create New App" → "From scratch"
|
|
644
|
+
4. `browser_fill_form` with app name "Maestro - {AgentFirstName}", select workspace
|
|
645
|
+
5. Navigate to OAuth & Permissions
|
|
646
|
+
6. Add Bot Token Scopes: `chat:write`, `chat:write.customize`, `channels:read`, `channels:history`, `groups:read`, `groups:history`, `im:read`, `im:history`, `im:write`, `users:read`, `users:read.email`, `reactions:read`, `reactions:write`, `files:read`, `files:write`
|
|
647
|
+
7. Add User Token Scopes: `channels:history`, `groups:history`, `im:history`, `search:read`, `chat:write`
|
|
648
|
+
8. Click "Install to Workspace" → authorize
|
|
649
|
+
9. Extract Bot User OAuth Token (xoxb-...) and User OAuth Token (xoxp-...) from the page
|
|
650
|
+
10. Navigate to Basic Information → extract Signing Secret
|
|
651
|
+
11. Write `SLACK_BOT_TOKEN`, `SLACK_USER_TOKEN`, `SLACK_SIGNING_SECRET` to `.env`
|
|
652
|
+
|
|
653
|
+
**Verify:**
|
|
654
|
+
```bash
|
|
655
|
+
source .env && curl -s -H "Authorization: Bearer $SLACK_USER_TOKEN" https://slack.com/api/auth.test | python3 -c "import json,sys; d=json.load(sys.stdin); print('Slack OK: ' + d.get('user','') if d.get('ok') else 'FAIL: ' + d.get('error',''))"
|
|
656
|
+
```
|
|
564
657
|
|
|
565
|
-
### Step
|
|
658
|
+
### Step 2: Gmail — per `docs/guides/email-setup.md`
|
|
566
659
|
|
|
660
|
+
Gmail app passwords require 2FA interaction — ask user:
|
|
567
661
|
```
|
|
568
|
-
|
|
569
|
-
|
|
662
|
+
Gmail setup: Please generate an app password:
|
|
663
|
+
1. Go to https://myaccount.google.com/apppasswords (or I can open it for you)
|
|
664
|
+
2. Generate a password for "Mail" on "Mac"
|
|
665
|
+
3. Paste the 16-character password here:
|
|
570
666
|
```
|
|
571
667
|
|
|
572
|
-
|
|
668
|
+
After receiving the password:
|
|
669
|
+
1. Write `GMAIL_APP_PASSWORD` to `.env`
|
|
670
|
+
2. If monitoring principal's inbox, ask for secondary password → `SECONDARY_GMAIL_APP_PASSWORD`
|
|
671
|
+
3. Install msmtp: `brew install msmtp 2>/dev/null || true`
|
|
672
|
+
4. Write `~/.msmtprc` per guide § 1.4, set `chmod 600 ~/.msmtprc`
|
|
673
|
+
|
|
674
|
+
**Verify:**
|
|
675
|
+
```bash
|
|
676
|
+
source .env && python3 -c "import imaplib,os; m=imaplib.IMAP4_SSL('imap.gmail.com'); m.login('${AGENT_EMAIL}', os.environ['GMAIL_APP_PASSWORD']); print('IMAP OK'); m.logout()"
|
|
573
677
|
```
|
|
574
|
-
Cloudflare tunnel options:
|
|
575
678
|
|
|
576
|
-
|
|
577
|
-
cloudflared tunnel --url http://localhost:3100
|
|
679
|
+
### Step 3: Twilio (SMS + WhatsApp) — per `docs/guides/voice-sms-setup.md`, `docs/guides/whatsapp-setup.md`
|
|
578
680
|
|
|
579
|
-
|
|
580
|
-
cloudflared tunnel create {agent-name}
|
|
581
|
-
cloudflared tunnel route dns {agent-name} {agent-name}.yourdomain.com
|
|
681
|
+
**If user has credentials:** ask for Account SID, Auth Token, Phone Number → write to `.env`.
|
|
582
682
|
|
|
583
|
-
|
|
683
|
+
**If creating new account — execute via Playwright:**
|
|
584
684
|
|
|
585
|
-
|
|
586
|
-
|
|
685
|
+
1. `browser_navigate` to `https://www.twilio.com/console`
|
|
686
|
+
2. `browser_snapshot` — if not logged in, ask user to log in via `! open https://www.twilio.com/login`
|
|
687
|
+
3. Once authenticated, extract Account SID and Auth Token from Console dashboard
|
|
688
|
+
4. Navigate to Phone Numbers → Buy a Number → search for SMS+Voice number in preferred country
|
|
689
|
+
5. **Ask user to confirm the purchase** (payment authorisation)
|
|
690
|
+
6. After purchase, extract phone number (E.164) and Phone SID
|
|
691
|
+
7. Write `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN`, `TWILIO_PHONE_NUMBER`, `TWILIO_PHONE_SID` to `.env`
|
|
587
692
|
|
|
588
|
-
|
|
589
|
-
|
|
693
|
+
**If SMS selected:** Configure webhook per guide:
|
|
694
|
+
1. Navigate to Twilio Console → Phone Numbers → Active Numbers → select number
|
|
695
|
+
2. Under Messaging → "A message comes in" → Webhook POST → `{tunnel_url}/sms`
|
|
696
|
+
3. Enable geo-permissions: navigate to Messaging → Settings → Geo Permissions → enable needed countries
|
|
590
697
|
|
|
591
|
-
|
|
698
|
+
**If WhatsApp selected:** Configure sandbox per guide:
|
|
699
|
+
1. `browser_navigate` to `https://console.twilio.com/us1/develop/sms/try-it-out/whatsapp-learn`
|
|
700
|
+
2. Under Sandbox Settings → set webhook URL to `{tunnel_url}/whatsapp` POST
|
|
701
|
+
3. Set Status Callback to `{tunnel_url}/whatsapp/status` POST
|
|
702
|
+
4. Note and report the sandbox join keyword to the user
|
|
703
|
+
5. Write `WHATSAPP_MODE=sandbox`, `WHATSAPP_PORT=3002` to `.env`
|
|
592
704
|
|
|
593
|
-
|
|
594
|
-
|
|
705
|
+
### Step 4: Webhook Relay (Railway) — per `docs/guides/webhook-relay-setup.md`
|
|
706
|
+
|
|
707
|
+
**This is the canonical pattern. Do NOT use Cloudflare Tunnels for new agents** — they were a transitional approach. Each agent gets its own Railway-deployed webhook relay. The local Mac mini polls the relay every 5 seconds and never needs an inbound tunnel.
|
|
708
|
+
|
|
709
|
+
The relay handles:
|
|
710
|
+
- `POST /slack/events` — Slack Events API (HMAC verified via SLACK_SIGNING_SECRET)
|
|
711
|
+
- `POST /sms` — Twilio SMS inbound (HMAC verified via TWILIO_AUTH_TOKEN)
|
|
712
|
+
- `POST /whatsapp` — Twilio WhatsApp inbound
|
|
713
|
+
- `POST /whatsapp/status` — Twilio WhatsApp delivery status
|
|
714
|
+
- `GET /events`, `/sms/messages`, `/whatsapp/messages` — drained by Mac mini poller
|
|
715
|
+
- `GET /health` — service status
|
|
716
|
+
|
|
717
|
+
**Source code** is already in the repo at `services/webhook-relay/` (copied from the maestro framework). It's a ~250-line Node 20 HTTP server, no dependencies, deployable straight to Railway.
|
|
718
|
+
|
|
719
|
+
**Prerequisites:**
|
|
720
|
+
- Railway CLI installed: `brew install railway 2>/dev/null || true`
|
|
721
|
+
- User must run `railway login` once (interactive — opens browser)
|
|
722
|
+
- User must have admin rights in the company's Railway workspace (e.g., "Adaptic")
|
|
723
|
+
|
|
724
|
+
**Deploy steps (run from the agent's repo root):**
|
|
725
|
+
|
|
726
|
+
```bash
|
|
727
|
+
# 1. Create the project in the company's Railway workspace
|
|
728
|
+
cd services/webhook-relay
|
|
729
|
+
railway init --name {firstname-lower}-webhook-relay --workspace {Company}
|
|
730
|
+
|
|
731
|
+
# 2. Add the service and deploy
|
|
732
|
+
railway up --service {firstname-lower}-webhook-relay --detach
|
|
733
|
+
|
|
734
|
+
# 3. Generate a public domain
|
|
735
|
+
railway domain --service {firstname-lower}-webhook-relay
|
|
736
|
+
# Captures: https://{firstname-lower}-webhook-relay-production.up.railway.app
|
|
737
|
+
|
|
738
|
+
# 4. Set env vars (must include the agent's own SLACK_SIGNING_SECRET and TWILIO_AUTH_TOKEN)
|
|
739
|
+
source ../../.env
|
|
740
|
+
railway variables --service {firstname-lower}-webhook-relay \
|
|
741
|
+
--set "SLACK_SIGNING_SECRET=$SLACK_SIGNING_SECRET" \
|
|
742
|
+
--set "TWILIO_AUTH_TOKEN=$TWILIO_AUTH_TOKEN" \
|
|
743
|
+
--set "PUBLIC_HOSTNAME={firstname-lower}-webhook-relay-production.up.railway.app" \
|
|
744
|
+
--set "BUFFER_TTL_MS=600000" \
|
|
745
|
+
--set "MAX_BUFFER_SIZE=1000"
|
|
746
|
+
|
|
747
|
+
# 5. Trigger redeploy so the running container picks up the new env vars
|
|
748
|
+
railway up --service {firstname-lower}-webhook-relay --detach
|
|
749
|
+
|
|
750
|
+
# 6. Wait until /health returns slack_signature: true and twilio_signature: true
|
|
751
|
+
for i in 1 2 3 4 5 6 7 8 9 10 11 12; do
|
|
752
|
+
RESP=$(curl -sf -m 5 https://{firstname-lower}-webhook-relay-production.up.railway.app/health)
|
|
753
|
+
if echo "$RESP" | grep -q '"slack_signature":true' && echo "$RESP" | grep -q '"twilio_signature":true'; then
|
|
754
|
+
echo "Relay live with signature verification"
|
|
755
|
+
break
|
|
756
|
+
fi
|
|
757
|
+
sleep 10
|
|
758
|
+
done
|
|
595
759
|
```
|
|
596
760
|
|
|
597
|
-
|
|
761
|
+
**Configure external services to point at the relay:**
|
|
762
|
+
|
|
763
|
+
```bash
|
|
764
|
+
# Twilio SMS webhook (uses Twilio API directly, no UI)
|
|
765
|
+
RELAY_URL="https://{firstname-lower}-webhook-relay-production.up.railway.app"
|
|
766
|
+
curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" -X POST \
|
|
767
|
+
"https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/IncomingPhoneNumbers/$TWILIO_PHONE_SID.json" \
|
|
768
|
+
--data-urlencode "SmsUrl=$RELAY_URL/sms" --data-urlencode "SmsMethod=POST"
|
|
598
769
|
```
|
|
599
|
-
Voice setup requires:
|
|
600
|
-
1. ElevenLabs API key (for text-to-speech)
|
|
601
|
-
→ Sign up at https://elevenlabs.io/
|
|
602
|
-
→ Copy your API key from Profile → API Keys
|
|
603
|
-
|
|
604
|
-
2. Deepgram API key (for speech-to-text)
|
|
605
|
-
→ Sign up at https://deepgram.com/
|
|
606
|
-
→ Copy your API key from Console → API Keys
|
|
607
770
|
|
|
608
|
-
|
|
609
|
-
→ This will be installed by the audio setup script
|
|
771
|
+
For **Slack Events Subscription**: use Playwright to update via the App Manifest editor (more reliable than the events page). Navigate to `https://app.slack.com/app-settings/{TEAM_ID}/{APP_ID}/app-manifest`, read the JSON via the CodeMirror instance, add this block to `settings`, and click Save Changes:
|
|
610
772
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
773
|
+
```json
|
|
774
|
+
"event_subscriptions": {
|
|
775
|
+
"request_url": "https://{firstname-lower}-webhook-relay-production.up.railway.app/slack/events",
|
|
776
|
+
"bot_events": [
|
|
777
|
+
"app_mention",
|
|
778
|
+
"message.channels",
|
|
779
|
+
"message.groups",
|
|
780
|
+
"message.im",
|
|
781
|
+
"message.mpim"
|
|
782
|
+
]
|
|
783
|
+
}
|
|
614
784
|
```
|
|
615
785
|
|
|
616
|
-
|
|
786
|
+
After save, navigate to the Event Subscriptions page and check for the yellow "Click here to verify" button — click it. Then **reinstall the app** at `https://api.slack.com/apps/{APP_ID}/install-on-team` so the new event scopes activate.
|
|
787
|
+
|
|
788
|
+
For **Twilio WhatsApp sandbox**: this requires a per-agent Twilio sub-account (see Phase 4 Step 3.5). Cannot share with other agents because the sandbox webhook is account-wide.
|
|
617
789
|
|
|
618
|
-
|
|
790
|
+
**Update local poll script:**
|
|
619
791
|
|
|
792
|
+
```bash
|
|
793
|
+
# Edit scripts/poll-slack-events.sh and scripts/comms-monitor.sh
|
|
794
|
+
# Set EVENTS_URL to https://{firstname-lower}-webhook-relay-production.up.railway.app/events
|
|
620
795
|
```
|
|
621
|
-
Any additional services to configure?
|
|
622
|
-
1. OpenAI API key (supplemental model access)
|
|
623
|
-
2. Gemini API key (media generation)
|
|
624
|
-
3. Greptile API key (code search)
|
|
625
|
-
4. Done — skip remaining
|
|
626
796
|
|
|
627
|
-
|
|
797
|
+
**Install the launchd job that polls the relay every 5 seconds:**
|
|
798
|
+
|
|
799
|
+
```bash
|
|
800
|
+
cat > scripts/local-triggers/plists/ai.adaptic.{firstname-lower}-poll-relay.plist <<EOF
|
|
801
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
802
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
803
|
+
<plist version="1.0">
|
|
804
|
+
<dict>
|
|
805
|
+
<key>Label</key><string>ai.adaptic.{firstname-lower}-poll-relay</string>
|
|
806
|
+
<key>ProgramArguments</key><array>
|
|
807
|
+
<string>/bin/bash</string>
|
|
808
|
+
<string>{REPO_ROOT}/scripts/poll-slack-events.sh</string>
|
|
809
|
+
</array>
|
|
810
|
+
<key>WorkingDirectory</key><string>{REPO_ROOT}</string>
|
|
811
|
+
<key>StartInterval</key><integer>5</integer>
|
|
812
|
+
<key>RunAtLoad</key><true/>
|
|
813
|
+
<key>StandardOutPath</key><string>{REPO_ROOT}/logs/polling/poll-relay-stdout.log</string>
|
|
814
|
+
<key>StandardErrorPath</key><string>{REPO_ROOT}/logs/polling/poll-relay-stderr.log</string>
|
|
815
|
+
</dict>
|
|
816
|
+
</plist>
|
|
817
|
+
EOF
|
|
818
|
+
cp scripts/local-triggers/plists/ai.adaptic.{firstname-lower}-poll-relay.plist ~/Library/LaunchAgents/
|
|
819
|
+
launchctl load ~/Library/LaunchAgents/ai.adaptic.{firstname-lower}-poll-relay.plist
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
**Add the relay URL block to `.env`:**
|
|
823
|
+
|
|
824
|
+
```bash
|
|
825
|
+
cat >> .env <<EOF
|
|
826
|
+
|
|
827
|
+
# ─── RAILWAY WEBHOOK RELAY ──────────────────────────────────────────────────
|
|
828
|
+
WEBHOOK_RELAY_URL=https://{firstname-lower}-webhook-relay-production.up.railway.app
|
|
829
|
+
WEBHOOK_RELAY_SLACK_EVENTS=https://{firstname-lower}-webhook-relay-production.up.railway.app/slack/events
|
|
830
|
+
WEBHOOK_RELAY_SMS_INBOUND=https://{firstname-lower}-webhook-relay-production.up.railway.app/sms
|
|
831
|
+
WEBHOOK_RELAY_WHATSAPP_INBOUND=https://{firstname-lower}-webhook-relay-production.up.railway.app/whatsapp
|
|
832
|
+
WEBHOOK_RELAY_POLL_EVENTS=https://{firstname-lower}-webhook-relay-production.up.railway.app/events
|
|
833
|
+
WEBHOOK_RELAY_POLL_SMS=https://{firstname-lower}-webhook-relay-production.up.railway.app/sms/messages
|
|
834
|
+
WEBHOOK_RELAY_POLL_WHATSAPP=https://{firstname-lower}-webhook-relay-production.up.railway.app/whatsapp/messages
|
|
835
|
+
EOF
|
|
628
836
|
```
|
|
629
837
|
|
|
630
|
-
|
|
838
|
+
**End-to-end test:**
|
|
631
839
|
|
|
632
|
-
|
|
840
|
+
1. Have Lucas (or any user) send a Slack message to a channel where the bot is a member, OR @-mention the bot in a public channel
|
|
841
|
+
2. Within ~5 seconds, the local Mac mini should fetch the buffered event and write a YAML file to `state/inbox/slack/`
|
|
842
|
+
3. The inbox processor picks it up and routes it
|
|
843
|
+
4. Verify `railway logs --service {firstname-lower}-webhook-relay` shows `[slack] buffered ...`
|
|
633
844
|
|
|
634
|
-
|
|
845
|
+
### Step 5: Voice / Huddle — per `docs/guides/voice-sms-setup.md` § 5
|
|
635
846
|
|
|
847
|
+
**API keys** — if user has them, paste directly. Otherwise, drive signup via Playwright:
|
|
848
|
+
|
|
849
|
+
1. **ElevenLabs**: `browser_navigate` to `https://elevenlabs.io/` → sign up or log in → navigate to Profile → API Keys → extract key
|
|
850
|
+
2. **Deepgram**: `browser_navigate` to `https://console.deepgram.com/` → sign up or log in → navigate to API Keys → create and extract key
|
|
851
|
+
3. Write `ELEVENLABS_API_KEY`, `DEEPGRAM_API_KEY` to `.env`
|
|
852
|
+
|
|
853
|
+
**Local setup:**
|
|
636
854
|
```bash
|
|
637
|
-
|
|
855
|
+
bash scripts/huddle/setup-audio.sh # Install BlackHole, sox, verify
|
|
856
|
+
cd scripts/huddle && npm install && cd ../.. # Install huddle Node.js deps
|
|
857
|
+
bash scripts/huddle/launch-slack.sh # Launch Slack with CDP
|
|
638
858
|
```
|
|
639
859
|
|
|
640
|
-
|
|
860
|
+
### Step 6: Media Generation — per `docs/guides/media-generation-setup.md`
|
|
641
861
|
|
|
642
|
-
|
|
862
|
+
1. If user has Gemini key, paste directly. Otherwise: `browser_navigate` to `https://aistudio.google.com/apikey` → extract or create key
|
|
863
|
+
2. Write `GEMINI_API_KEY` to `.env`
|
|
643
864
|
|
|
644
|
-
|
|
865
|
+
### Step 7: Additional Keys
|
|
645
866
|
|
|
646
|
-
|
|
867
|
+
Prompt for any remaining optional keys: `OPENAI_API_KEY`, `GREPTILE_API_KEY`. Write to `.env` or skip.
|
|
647
868
|
|
|
648
|
-
|
|
649
|
-
# {repoName}
|
|
869
|
+
## Phase 5: Subsystem Implementation & Verification
|
|
650
870
|
|
|
651
|
-
**
|
|
871
|
+
After credentials are configured, this phase **autonomously implements and verifies** every subsystem by following each implementation guide's setup and test steps. This ensures the agent is actually operational — not just configured with API keys.
|
|
652
872
|
|
|
653
|
-
|
|
873
|
+
**Execution:** Spawn parallel background agents for independent subsystems. Report results as a verification matrix. Do NOT proceed to Phase 6 until all selected subsystems pass (or user explicitly accepts failures).
|
|
654
874
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
875
|
+
Tell the user:
|
|
876
|
+
```
|
|
877
|
+
Credentials configured. Now I'll set up and verify each subsystem end-to-end.
|
|
878
|
+
This runs autonomously — I'll report results when complete.
|
|
879
|
+
```
|
|
658
880
|
|
|
659
|
-
|
|
660
|
-
{companyDescription}. {firstName} runs 24/7 on a dedicated Mac mini ({machineName}),
|
|
661
|
-
using Claude Code as the reasoning engine and orchestrating 30+ specialist sub-agents.
|
|
881
|
+
### 5.1 Outbound Governance — `docs/guides/outbound-governance-setup.md`
|
|
662
882
|
|
|
663
|
-
|
|
664
|
-
{describe autonomy level based on archetype}.
|
|
883
|
+
Verify FIRST — all send scripts depend on this.
|
|
665
884
|
|
|
666
|
-
|
|
885
|
+
1. Verify hooks registered in `.claude/settings.json` (PreToolUse for block-mcp-slack-send and pre-send-audit, PostToolUse for post-action-log, Stop for session-end-log)
|
|
886
|
+
2. `chmod +x scripts/hooks/*.sh`
|
|
887
|
+
3. Test dedup: generate key → acquire → verify CLAIMED → cleanup
|
|
888
|
+
4. Test validate-outbound.py runs without crash
|
|
889
|
+
5. Test disclosure_assessment.py runs without crash
|
|
667
890
|
|
|
668
|
-
|
|
669
|
-
For executive-operator: comms management, briefs, hiring, strategic execution, etc.
|
|
670
|
-
For technical-leader: code review, architecture decisions, engineering health, etc.
|
|
671
|
-
For compliance-officer: regulatory tracking, filing management, audit readiness, etc.
|
|
672
|
-
Tailor to the specific responsibilities gathered in Phase 1.}
|
|
891
|
+
### 5.2 Email — `docs/guides/email-setup.md`
|
|
673
892
|
|
|
674
|
-
|
|
893
|
+
1. Test IMAP connectivity (if GMAIL_APP_PASSWORD set)
|
|
894
|
+
2. Verify msmtp config exists: `test -f ~/.msmtprc`
|
|
895
|
+
3. Verify email signature files: `test -f scripts/email-signature.html`
|
|
896
|
+
4. `chmod +x scripts/send-email.sh`
|
|
675
897
|
|
|
676
|
-
|
|
898
|
+
### 5.3 Slack — `docs/guides/slack-setup.md`
|
|
677
899
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
- **Tier 4**: Decision Log, Risk Register, Knowledge Base
|
|
900
|
+
1. Test token: `curl -s -H "Authorization: Bearer $SLACK_USER_TOKEN" https://slack.com/api/auth.test`
|
|
901
|
+
2. Verify slack-send.sh uses xoxp- token (not xoxb-)
|
|
902
|
+
3. Verify typing indicator exists: `test -f scripts/slack-typing.mjs`
|
|
903
|
+
4. Verify MCP block hook: `test -f scripts/hooks/block-mcp-slack-send.sh`
|
|
683
904
|
|
|
684
|
-
|
|
905
|
+
### 5.4 SMS & WhatsApp — `docs/guides/voice-sms-setup.md`, `docs/guides/whatsapp-setup.md`
|
|
685
906
|
|
|
686
|
-
|
|
907
|
+
1. Verify `config/caller-id-map.yaml` exists and has principal with `access_level: ceo`
|
|
908
|
+
2. Start SMS handler, verify health: `curl http://localhost:3001/health`
|
|
909
|
+
3. Start WhatsApp handler, verify health: `curl http://localhost:3002/health`
|
|
910
|
+
4. `chmod +x scripts/send-sms.sh scripts/send-whatsapp.sh`
|
|
687
911
|
|
|
688
|
-
|
|
689
|
-
Health check: npm run healthcheck
|
|
690
|
-
Emergency stop: npm run emergency-stop
|
|
912
|
+
### 5.5 Voice / Huddle — `docs/guides/voice-sms-setup.md` § 5
|
|
691
913
|
|
|
692
|
-
|
|
914
|
+
1. `bash scripts/huddle/setup-audio.sh --check`
|
|
915
|
+
2. Verify huddle deps: `test -d scripts/huddle/node_modules`
|
|
916
|
+
3. Verify Deepgram + ElevenLabs keys are set
|
|
693
917
|
|
|
694
|
-
|
|
695
|
-
- **Scheduled**: {morningBrief time} brief, midday sweep, {eveningWrap time} wrap, weekly cycles
|
|
696
|
-
- **Proactive**: Backlog executor every 10 min, parallel agent execution
|
|
918
|
+
### 5.6 Poller & Daemon — `docs/guides/poller-daemon-setup.md`
|
|
697
919
|
|
|
698
|
-
|
|
920
|
+
1. Run poller once: `timeout 30 node scripts/poller/index.mjs`
|
|
921
|
+
2. Verify daemon entry point: `head -5 scripts/daemon/maestro-daemon.mjs`
|
|
922
|
+
3. Verify plists generated: `ls scripts/local-triggers/plists/*.plist | wc -l`
|
|
923
|
+
4. Test emergency stop: `touch .emergency-stop` → run trigger → verify blocked → `rm .emergency-stop`
|
|
924
|
+
5. Verify watchdog: `bash scripts/watchdog/memory-watchdog.sh --check`
|
|
699
925
|
|
|
700
|
-
|
|
701
|
-
|---------|---------|
|
|
702
|
-
| npm run daemon | Start the main orchestrator |
|
|
703
|
-
| npm run healthcheck | Verify all subsystems |
|
|
704
|
-
| npm run emergency-stop | Halt all operations |
|
|
705
|
-
| npm run resume | Resume after emergency stop |
|
|
706
|
-
| npm run upgrade | Pull latest Maestro framework |
|
|
707
|
-
| claude "/init-maestro" | Reconfigure agent identity |
|
|
926
|
+
### 5.7 RAG & Context — `docs/guides/rag-context-setup.md`
|
|
708
927
|
|
|
709
|
-
|
|
928
|
+
1. Build search index: `python3 scripts/rag-indexer.py --full`
|
|
929
|
+
2. Verify docs indexed: `python3 scripts/rag-indexer.py --stats`
|
|
930
|
+
3. Test search: `python3 scripts/user-context-search.py --user unknown --query "adaptic" --max-results 1`
|
|
931
|
+
4. Run test suite if available: `bash scripts/test-rag-search.sh`
|
|
710
932
|
|
|
711
|
-
|
|
712
|
-
- executive-operator: broad autonomy with escalation for legal/financial commitments
|
|
713
|
-
- technical-leader: autonomous on technical decisions, escalates on budget/headcount
|
|
714
|
-
- compliance-officer: conservative, escalates on submissions and interpretations
|
|
715
|
-
- etc.}
|
|
933
|
+
### 5.8 PDF Generation — `docs/guides/pdf-generation-setup.md`
|
|
716
934
|
|
|
717
|
-
|
|
935
|
+
1. `pandoc --version`
|
|
936
|
+
2. Check XeLaTeX: `xelatex --version 2>/dev/null || ~/Library/TinyTeX/bin/universal-darwin/xelatex --version 2>/dev/null`
|
|
937
|
+
3. Generate test PDF:
|
|
938
|
+
```bash
|
|
939
|
+
echo "# Test\nGenerated by init-maestro." > /tmp/init-test.md
|
|
940
|
+
node scripts/pdf-generation/build-document.mjs --input /tmp/init-test.md --template memo --output /tmp/init-test.pdf
|
|
941
|
+
test -f /tmp/init-test.pdf && echo "PDF OK"
|
|
942
|
+
rm -f /tmp/init-test.md /tmp/init-test.pdf
|
|
943
|
+
```
|
|
718
944
|
|
|
719
|
-
|
|
720
|
-
```
|
|
945
|
+
### 5.9 Media Generation — `docs/guides/media-generation-setup.md`
|
|
721
946
|
|
|
722
|
-
|
|
947
|
+
1. Verify Gemini key set
|
|
948
|
+
2. List specs: `node scripts/media-generation/generate-assets.mjs --list`
|
|
949
|
+
3. Verify client loads: `node -e "import('./scripts/media-generation/gemini-image-client.mjs').then(() => console.log('OK'))"`
|
|
723
950
|
|
|
724
|
-
|
|
951
|
+
### 5.10 Verification Summary
|
|
725
952
|
|
|
726
|
-
|
|
953
|
+
Print results:
|
|
727
954
|
|
|
728
955
|
```
|
|
729
|
-
|
|
956
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
957
|
+
║ SUBSYSTEM VERIFICATION RESULTS ║
|
|
958
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
959
|
+
║ ║
|
|
960
|
+
║ Outbound Governance ✅ PASS hooks, dedup, validation ║
|
|
961
|
+
║ Email (Gmail) ✅ PASS IMAP, SMTP, signatures ║
|
|
962
|
+
║ Slack ✅ PASS tokens, send, typing ║
|
|
963
|
+
║ SMS (Twilio) ✅ PASS handler, send, caller-id ║
|
|
964
|
+
║ WhatsApp ⏭️ SKIP not selected ║
|
|
965
|
+
║ Voice / Huddle ⏭️ SKIP not selected ║
|
|
966
|
+
║ Poller & Daemon ✅ PASS poller, plists, watchdog ║
|
|
967
|
+
║ RAG & Context ✅ PASS index built, search works ║
|
|
968
|
+
║ PDF Generation ✅ PASS pandoc + xelatex OK ║
|
|
969
|
+
║ Media Generation ⏭️ SKIP not selected ║
|
|
970
|
+
║ ║
|
|
971
|
+
║ Overall: 7/7 selected subsystems PASS ║
|
|
972
|
+
║ ║
|
|
973
|
+
║ Guides: docs/guides/ (for detailed testing & troubleshoot) ║
|
|
974
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
730
975
|
```
|
|
731
976
|
|
|
732
|
-
If
|
|
977
|
+
If any subsystem FAILS: diagnose via the guide's troubleshooting section, attempt one fix, re-run check. If still failing, report failure with specific error and ask user whether to continue or abort.
|
|
978
|
+
|
|
979
|
+
## Phase 6: Generate Agent README
|
|
980
|
+
|
|
981
|
+
Generate a comprehensive README.md for this agent's repository. This describes THIS specific agent, not the Maestro framework.
|
|
982
|
+
|
|
983
|
+
Include all of the following sections populated with gathered values:
|
|
984
|
+
|
|
985
|
+
1. **Title and tagline**: `{fullName} — Autonomous {title} for {company}`
|
|
986
|
+
2. **Who is {firstName}?**: 3-4 sentence description of role, reporting line, autonomy level
|
|
987
|
+
3. **Capabilities**: 8-12 bullet points based on archetype and responsibilities
|
|
988
|
+
4. **Architecture**: 5-tier model with role-specific domain controllers
|
|
989
|
+
5. **Subsystem Status**: Include the Phase 5 verification matrix
|
|
990
|
+
6. **Operating Modes**: Reactive (polling), Scheduled (triggers), Proactive (backlog)
|
|
991
|
+
7. **Commands**: npm run daemon, healthcheck, emergency-stop, resume, upgrade
|
|
992
|
+
8. **Implementation Guides**: Table linking to all 10 guides in `docs/guides/`
|
|
993
|
+
9. **Communication Governance**: Based on archetype autonomy model
|
|
994
|
+
|
|
995
|
+
Write to repo root as `README.md`.
|
|
996
|
+
|
|
997
|
+
## Phase 7: Create GitHub Repository
|
|
998
|
+
|
|
999
|
+
Ask the user whether they want to create a GitHub repo:
|
|
733
1000
|
|
|
734
1001
|
```
|
|
735
|
-
|
|
736
|
-
1. GitHub organization or username? (default: adapticai)
|
|
737
|
-
2. Repository name? (default: {repoName}, e.g., "jacob-ai")
|
|
738
|
-
3. Visibility: private (recommended) or public? (default: private)
|
|
1002
|
+
Would you like me to create a GitHub repository for this agent? (yes/no)
|
|
739
1003
|
```
|
|
740
1004
|
|
|
741
|
-
|
|
742
|
-
```bash
|
|
743
|
-
gh repo create {org}/{repoName} --private --description "{fullName} — Autonomous {title} for {company} (powered by Maestro)"
|
|
744
|
-
```
|
|
1005
|
+
If yes: ask for org/username (default: adapticai), repo name (default: {repoName}), visibility (default: private). Then:
|
|
745
1006
|
|
|
746
|
-
After creating the repo, set up git and push:
|
|
747
1007
|
```bash
|
|
1008
|
+
gh repo create {org}/{repoName} --private --description "{fullName} — Autonomous {title} for {company} (powered by Maestro)"
|
|
748
1009
|
git remote add origin https://github.com/{org}/{repoName}.git
|
|
749
1010
|
git add -A
|
|
750
1011
|
git commit -m "Initialize {fullName} as {title} — powered by @adaptic/maestro"
|
|
751
1012
|
git push -u origin main
|
|
752
1013
|
```
|
|
753
1014
|
|
|
754
|
-
|
|
1015
|
+
## Phase 8: Final Verification
|
|
755
1016
|
|
|
756
|
-
|
|
1017
|
+
### Step 1: Grep for stale agent references
|
|
757
1018
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
### Step 1: Grep for old agent references
|
|
761
|
-
|
|
762
|
-
Search critical files for any remaining references to the old agent's first name (case-insensitive). Check:
|
|
763
|
-
- CLAUDE.md
|
|
764
|
-
- config/agent.ts
|
|
765
|
-
- config/environment.yaml
|
|
766
|
-
- config/contacts.yaml
|
|
767
|
-
- config/priorities.yaml
|
|
768
|
-
- package.json
|
|
769
|
-
- All files in schedules/triggers/
|
|
770
|
-
- All agent.md files in agents/
|
|
771
|
-
|
|
772
|
-
Report any stragglers and fix them.
|
|
1019
|
+
Search critical files for old agent name (case-insensitive): CLAUDE.md, config/agent.ts, config/*.yaml, package.json, schedules/triggers/*.md, agents/*/agent.md. Fix any stragglers.
|
|
773
1020
|
|
|
774
1021
|
### Step 2: Validate config/agent.ts
|
|
775
1022
|
|
|
776
|
-
Read
|
|
1023
|
+
Read and verify valid TypeScript, all fields populated with new values.
|
|
777
1024
|
|
|
778
|
-
### Step 3:
|
|
1025
|
+
### Step 3: Health check
|
|
779
1026
|
|
|
780
1027
|
```bash
|
|
781
1028
|
npm run healthcheck
|
|
782
1029
|
```
|
|
783
1030
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
### Step 4: Summary
|
|
787
|
-
|
|
788
|
-
Print a completion summary:
|
|
1031
|
+
### Step 4: Completion Summary
|
|
789
1032
|
|
|
790
1033
|
```
|
|
791
|
-
|
|
1034
|
+
═══════════════════════════════════════════════════════════════
|
|
1035
|
+
MAESTRO INITIALIZATION COMPLETE
|
|
1036
|
+
═══════════════════════════════════════════════════════════════
|
|
792
1037
|
|
|
793
1038
|
Agent: {fullName}, {title}
|
|
794
1039
|
Archetype: {archetype}
|
|
@@ -796,41 +1041,38 @@ Maestro initialization complete.
|
|
|
796
1041
|
Principal: {principalName}
|
|
797
1042
|
Machine: {machineName}
|
|
798
1043
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
- agents/{agent-slug}/agent.md (+ 30 other agent definitions)
|
|
806
|
-
- schedules/triggers/ (13 trigger prompts)
|
|
1044
|
+
Identity (Phase 2): ✅ 8 parallel agents rewrote repo
|
|
1045
|
+
Infrastructure (Phase 3): ✅ {N} launchd triggers installed
|
|
1046
|
+
Services (Phase 4): ✅ {list configured services}
|
|
1047
|
+
Subsystems (Phase 5): {include verification matrix}
|
|
1048
|
+
README (Phase 6): ✅ Agent-specific README generated
|
|
1049
|
+
GitHub (Phase 7): {repo URL or "skipped"}
|
|
807
1050
|
|
|
808
|
-
|
|
809
|
-
- {N} launchd triggers installed
|
|
810
|
-
- Global Claude Code settings configured
|
|
811
|
-
- .env file created {with/without API keys}
|
|
1051
|
+
─────────────────────────────────────────────────────────
|
|
812
1052
|
|
|
813
|
-
|
|
1053
|
+
Next steps:
|
|
1054
|
+
1. Start the daemon: npm run daemon
|
|
1055
|
+
2. Monitor logs: tail -f logs/daemon/$(date +%Y-%m-%d)-sessions.jsonl
|
|
1056
|
+
3. Test a message: Send a Slack DM to {firstName}
|
|
814
1057
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
2. Check daemons: launchctl list | grep adaptic
|
|
818
|
-
3. Health check: npm run healthcheck
|
|
819
|
-
4. Start daemon: npm run daemon
|
|
1058
|
+
Implementation guides: docs/guides/
|
|
1059
|
+
═══════════════════════════════════════════════════════════════
|
|
820
1060
|
```
|
|
821
1061
|
|
|
822
|
-
## Guidelines for the Wizard
|
|
1062
|
+
## Guidelines for the Wizard
|
|
823
1063
|
|
|
824
1064
|
- Be warm and professional. This is a setup experience, not an interrogation.
|
|
825
|
-
- Offer sensible defaults wherever possible.
|
|
826
|
-
-
|
|
827
|
-
-
|
|
828
|
-
-
|
|
829
|
-
-
|
|
830
|
-
-
|
|
1065
|
+
- Offer sensible defaults wherever possible.
|
|
1066
|
+
- Always confirm before executing identity changes (Phase 2). Service configuration (Phase 4) and verification (Phase 5) execute autonomously after the user selects services.
|
|
1067
|
+
- Sub-agents MUST run in parallel (`run_in_background: true`).
|
|
1068
|
+
- **Autonomous execution is the default.** Only ask for input when you cannot proceed without it (credentials, 2FA, payment). Everything else — web UI navigation, script execution, file writes, verification — you do yourself.
|
|
1069
|
+
- **Use Playwright MCP** for web UIs: Slack API portal, Twilio Console, Google Account, ElevenLabs, Deepgram, Gemini.
|
|
1070
|
+
- **Use Bash** for local operations: scripts, installs, service starts, tests.
|
|
1071
|
+
- If Playwright fails (auth wall, CAPTCHA), fall back to asking user to do that specific step via `! open <url>`, then resume.
|
|
831
1072
|
|
|
832
1073
|
## Error Handling
|
|
833
1074
|
|
|
834
|
-
- If a sub-agent fails, report which one
|
|
835
|
-
- If the
|
|
836
|
-
- If
|
|
1075
|
+
- If a sub-agent fails, report which one and offer to retry.
|
|
1076
|
+
- If a Phase 5 subsystem verification fails, diagnose using the guide's troubleshooting section, attempt one fix, re-run. If still failing, report with specific error and ask whether to continue.
|
|
1077
|
+
- If user aborts mid-wizard, exit cleanly.
|
|
1078
|
+
- If config/agent.ts unreadable, suggest `npx @adaptic/maestro create` first.
|