The org-owned app A0BC7AT8NUD (created via the org config token) connected its Socket Mode socket but received ZERO workspace Events API events, so the clarifier never heard answers. Root cause: Socket Mode event delivery only works for WORKSPACE-LEVEL apps. Recreated from the dashboard scoped to the Sea Haven Industries workspace -> A0BCC7TTU66 (bot @agentteam2); events now deliver and the live human gate works end to end. Old org app deleted. Updates the slack/ README: new app id/bot, a hard-lesson callout (must be workspace-level, never org-owned), the real-envelope answer-matching note, and a corrected dashboard setup/update flow. |
||
|---|---|---|
| .. | ||
| agent-team-manifest.json | ||
| README.md | ||
agent-team Slack app
Dedicated Slack app backing the Plane-2 clarifier human-gate (Socket Mode).
Kept separate from the webhook-only Tech Notifications app (A0ARYQZU3KJ)
that the nightly secrev sweep uses, to isolate the two-way bot's trust surface.
| Field | Value |
|---|---|
| App name | Sea Haven agent-team |
| App ID | A0BCC7TTU66 |
| Bot | agent-team (handle @agentteam2) · user id U0BCFSJ7SUC |
| Scope | Workspace-level app, installed to Sea Haven Industries (T0A46CP6QR3) |
| Manifest | agent-team-manifest.json (source of truth) |
| Settings | https://api.slack.com/apps/A0BCC7TTU66 |
⚠️ Must be a WORKSPACE-LEVEL app (hard lesson, 2026-06-22)
Socket Mode event delivery only works for workspace-level apps. An org-owned app (one created via the Enterprise org/config token /
apps.manifest.create, even when workspace-granted with--org-workspace-grant) connects the socket but receives ZERO workspace Events API events — outboundchat.postMessageworks, but inboundmessage/app_mentionare never delivered, so the clarifier never hears answers. The first build hit exactly this with the now-deleted org appA0BC7AT8NUD. Create this app from the dashboard (api.slack.com/apps → Create New App → From manifest) and pick the workspace "Sea Haven Industries" as the dev workspace, NOT the Enterprise org. Then a normal Install to Workspace works (no org-grant dance). Do not recreate it via the org config token.
Why these scopes (verified against the code)
agent_team/transport/slack_listener.py subscribes over Socket Mode to
message, app_mention, and Block Kit block_actions; slack_live.py posts
questions via chat.postMessage. Inbound message/app_mention arrive as the
Events API envelope {"type":"event_callback","event":{...}} and a free-text
thread reply is matched to its question by thread_ts == channel_ref (see
find_open_question_by_channel_ref).
| Capability | Scope / setting | Why |
|---|---|---|
| Post clarifier questions | chat:write |
slack_live.py chat.postMessage |
| Hear thread replies | channels:history / groups:history + message.channels/message.groups |
@app.event("message") |
| Hear DM replies | im:history + message.im |
DM answer path |
| Hear @mentions | app_mentions:read + app_mention |
@app.event("app_mention") |
| Block Kit answers | interactivity.is_enabled |
@app.action(...) |
| Inbound WebSocket | socket_mode_enabled + app-level token w/ connections:write |
VPN-only box, no public HTTPS endpoint |
Inbound auth is NOT scope-based: AUTHZ-01 (AGENT_TEAM_SLACK_OWNER_IDS) gates
the sender and fails closed. Socket membership alone is never authorization.
Setup (operator, in browser — secrets never echoed)
- Create the app — api.slack.com/apps → Create New App → From an app
manifest → pick workspace "Sea Haven Industries" → paste
agent-team-manifest.json. - Install to Workspace → copy the Bot User OAuth Token (
xoxb-) →SLACK_BOT_TOKEN. - Basic Information → App-Level Tokens → Generate with scope
connections:write→SLACK_APP_TOKEN. - Channel —
/invite @agentteam2into the clarifier channel; itsC0…id →SLACK_CHANNEL_ID. - Owner allowlist —
AGENT_TEAM_SLACK_OWNER_IDS= Adam's Slack user id (U0A3SC48T47), comma-separated if more than one. Fails closed if empty.
All five land in ~/secrev.env on the box (mode 600), never shell history.
Updating the app from the manifest
Edit agent-team-manifest.json, then in the dashboard (App Manifest tab) paste
the updated manifest, or use apps.manifest.update with an app config token
scoped to the workspace app (the org config token can read/manage it as org
owner, but keep the app workspace-level — do not re-create it org-owned).