Quo Internal Comments Skill
What this is
The authoritative skill for Aurora posting internal thread comments in Quo (OpenPhone). Covers the full lifecycle: how a comment is triggered, how it’s formatted, how it’s posted, and what constitutes a correct internal communication.
Core infrastructure (already live)
| Component | Path | Purpose |
|---|---|---|
| Shared poster lib | workspace/scripts/lib/quo-post-comment.js | Single source of truth for HTTP POST to Quo. All agents import this. |
| Orchestrator tool | tools/quo-thread-orchestrator/tools/reply-to-thread.js | Wraps quo-post-comment; called by runner.js; handles R1 fallback |
| Runner | tools/quo-thread-orchestrator/runner.js | LLM loop (Kimi/Moonshot via Portkey). Takes a mentionRow, runs tool loop, posts reply |
| Auth | workspace/scripts/lib/quo-token.js | Auth0 Bearer token from saved browser state. Auto-refreshes. |
| API endpoint | POST https://communication.openphoneapi.com/v2/comment | Quo’s internal communication service (not the public OpenPhone API) |
Trigger modes
| Mode | Source | mentionRow.proactive_trigger |
|---|---|---|
| Reactive | Team member @mentions Aurora in a thread | false |
| Proactive | Inbound SMS arrives on a watched line | true (live 2026-05-04) |
Posting rules
- Always thread under a specific activity —
activityId=mentionRow.parent_activity_id. Never post a floating conversation-level note. - One comment per activity per run — idempotency key prevents duplicate posts on retry.
- No em-dashes —
reply-to-thread.jsscrubs—→,. Kimi occasionally outputs them. - No raw JSON in notes — runner’s
auto_reply_from_end_turnstrips code fences before posting. - No SMS fallback — if R3 fails and R1 fallback also fails, the note is NOT sent as SMS. Error logged only.
Thread resolution
Tool: quo_resolve_thread in tools/quo-thread-orchestrator/tools/quo-resolve-thread.js
OpenPhone “Done” = snooze with sentinel duration 525949200s (~16.6 yr). Endpoint:
- Resolve:
PUT https://communication.openphoneapi.com/v2/conversation/{id}/snooze{ duration: 525949200 } - Unresolve:
PUT https://communication.openphoneapi.com/v2/conversation/{id}/unsnooze{}
Aurora can call quo_resolve_thread from the orchestrator tool loop. Updates openphone_mentions.state = 'closed'.
Pending work
- Communication standards: define what Aurora says in each trigger scenario (reactive @mention, proactive inbound SMS, proactive outbound SMS)
- Filtering: which lines/conversations should trigger proactive notes vs. skip (currently all inbound on Aurora’s watched lines)
- Token expiry monitoring: alert if Auth0 refresh fails so R3 doesn’t silently degrade to R1 permanently
Retired paths (do not use)
| Script | Retired reason |
|---|---|
openphone-login-and-note.js | Playwright browser automation — superseded by R3 |
mac-post-bridge.js | SSH + Playwright to AWS Mac — R1 fallback only, auto-triggered on R3 failure |
openphone-internal-comment.js | File-queue workaround — obsolete since R3 discovered |
quo-browser-automation.js | Browser automation — superseded by R3 |
quo-watcher-c1/c2/c3/c5-*.js | Bakeoff contestants — C4 headless WS won |
quo-response-discovery.js | Network capture probe — endpoint found, retired |
quo-bakeoff-analyze.js | Bakeoff analytics — bakeoff complete |
All above files moved to workspace/scripts/_retired/quo-bakeoff-2026-04/ and workspace/scripts/workers/_retired/.
How to invoke (manual test)
# Dry run — see what Aurora would post without sending
NODE_PATH=.../node_modules DRY_RUN=true node workspace/scripts/tests/test-quo-proactive-notes.js --msg=1
# Live — post actual note to test conversation
NODE_PATH=.../node_modules DRY_RUN=false node workspace/scripts/tests/test-quo-proactive-notes.js --msg=1
# Direct API test
node -e "
const { postComment } = require('./workspace/scripts/lib/quo-post-comment');
postComment('AC_ACTIVITY_ID', 'Test note').then(r => console.log('posted:', r)).catch(e => console.error(e.message));
"References
- KB:
workspace/knowledge-base/openphone/API.md— endpoint spec, auth, body shape - Test conversation:
https://my.quo.com/inbox/PN4GfD7RX2/c/CN301c8943c2174ac68d11550bfaf6cc19 - Skill trigger registry:
CLAUDE.mdTool Trigger Conditions table