Slack QA
Agent E2E recipes
Use.agents/skills/slack-e2e/SKILL.md from the checkout under test for reusable
native fixtures, Gateway replies, and runtime/config experiments. With an
existing authenticated Convex CLI that can access the QA broker:
mock-openai. Explicit flags or credential environment settings take
precedence; ordinary qa slack defaults remain unchanged. Repeat
--scenario-file for complete custom YAML flows declaring
execution.channel: slack and execution.config.agentE2e: true. Native writes
run once; positive retryCount values are rejected.
Readiness checks the actual lease’s identities, shared workspace, channel access,
Gateway connection, and advertised scopes. The full lifecycle additionally needs
driver reactions:read, reactions:write, files:read, and files:write.
The driver manifest below includes those capabilities. Existing installations
need the app owner to add missing scopes and reinstall the app before rerunning
the lifecycle. A missing scope blocks its operation and full lifecycle proof,
not basic text flows. The runner does not grant permissions or rotate credentials
to find a passing result. Bot OAuth scopes, not workspace-admin privileges,
authorize these fixture operations.
The driver uses Web API calls; the SUT alone owns Socket Mode. Stored
message/file/reaction readback proves native state, while a correlated SUT reply
proves Gateway ingress and delivery. Neither proves client rendering, human slash
commands, button clicks, Agent View, or human typing. Use the
manual client workflow
for those claims.
Cleanup captures final Gateway write receipts after process shutdown and before
temporary capture state is removed, then removes only owned fixtures before
releasing the lease. Private <scenario-id>-slack-e2e.json receipts distinguish
accepted writes, stored state, and incomplete cleanup.
Direct credential setup
Required env when--credential-source env:
OPENCLAW_QA_SLACK_CHANNEL_IDOPENCLAW_QA_SLACK_DRIVER_BOT_TOKENOPENCLAW_QA_SLACK_SUT_BOT_TOKENOPENCLAW_QA_SLACK_SUT_APP_TOKEN
OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_DIRenables visual approval checkpoints for Mantis. The adapter writes<scenario>.pending.jsonand<scenario>.resolved.json, then waits for matching.ack.jsonfiles.OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_TIMEOUT_MSoverrides the checkpoint acknowledgement timeout. The default is120000.
thread-follow-upthread-isolation
qa/scenarios/channels/slack-*.yaml):
slack-canaryslack-mention-gatingslack-mpim-app-mention-dedupe- opens a real C-prefixed group DM, verifies exactly one SUT reply after message/app-mention twin delivery, confirms a native threaded follow-up can recall that bot reply, then closes the MPIM.slack-allowlist-blockslack-channel-disabled-warning- opt-in real-Slack probe that confirms a configured disabled channel emits a structured warning without replying.slack-top-level-reply-shapeslack-restart-resumeslack-progress-commentary-true,slack-progress-commentary-false,slack-progress-commentary-omitted, andslack-progress-commentary-verbose-dedupe/slack-progress-commentary-verbose-full- opt-in real-Slack probes for independent commentary/tool-progress controls, the omitted-key legacy default, and single-delivery behavior for durable verbose progress. Theonprobe requires a safe Exec summary without command text or output; thefullprobe requires the exact stdout marker in a separate tool-output message. Both use the same command and require one commentary identity separate from the final answer. Full verbosity allows the runtime’s command metadata and one separate start summary, while requiring a unique completed-output identity. Slack may strip command-summary headers during delivery, so the exact output line, not a tool label, identifies completed output. Failures retain bounded presentation facts without raw Slack messages or platform identities, including marker formatting andsleepsummaries missing the command marker.slack-reaction-glyph-native- opt-in live message-tool reaction scenario. Instructs the agent to pass the exact✅glyph and confirms Slack storedwhite_check_markfor the SUT bot on the target message.slack-chart-presentation-native- opt-in portable chart scenario that verifies the nativedata_visualizationblock and exact accessible text.slack-table-presentation-native- opt-in portable table scenario that verifies the nativedata_tableblock, exact rows, and accessible text.slack-table-invalid-blocks-fallback- opt-in direct-transport scenario that sends a structurally readable over-limit raw table with 101 data rows plus its header through the production Slack send path, proves Slack itself returnsinvalid_blocks, and verifies the stored formatting-disabled fallback is complete and has no native data block. Scenario details keep only safe error-code, count, and boolean evidence.slack-approval-exec-native- opt-in native Slack exec approval scenario. Requests an exec approval through the gateway, verifies the Slack message has native approval buttons, resolves it, and verifies the resolved Slack update.slack-approval-plugin-native- opt-in native Slack plugin approval scenario. Enables exec and plugin approval forwarding together so plugin events are not suppressed by exec approval routing, then verifies the same pending/resolved native Slack UI path.slack-codex-approval-exec-native- opt-in Codex Guardian command approval scenario. Enables the Codex plugin in Guardian mode, routes a Slack-originated Gateway agent turn through the Codex app-server harness, waits for the native Slack plugin approval prompt forcodex, resolves it, and verifies the Codex turn finishes with the expected command-output and assistant markers.slack-codex-approval-plugin-native- opt-in Codex Guardian file approval scenario. Uses an outside-workspaceapply_patchinstruction so Codex emits the app-server file-change approval route, then verifies the same native Slack pending/resolved approval path, final assistant marker, and exact file contents before cleanup.
openai/* or codex/* --model, the
normal live model credentials, and Codex auth or API-key auth accepted by the Codex plugin.
The scenario details include the Codex app-server method, selected Codex model
key, final Codex turn status, and operation-marker verification alongside the
redacted Slack approval metadata.
Output artifacts:
qa-suite-report.mdqa-suite-summary.jsonqa-evidence.json- evidence entries for the live transport checks.approval-checkpoints/- only when Mantis setsOPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_DIR; contains checkpoint JSON, acknowledgement JSON, and pending/resolved screenshots.
Setting up the Slack workspace
The lane needs two distinct Slack apps in one workspace, plus a channel both bots are members of:channelId- theCxxxxxxxxxxid of a channel both bots have been invited to. Use a dedicated channel; the lane posts on every run.driverBotToken- bot token (xoxb-...) of the Driver app.sutBotToken- bot token (xoxb-...) of the SUT app, which must be a separate Slack app from the driver so its bot user id is distinct.sutAppToken- app-level token (xapp-...) of the SUT app withconnections:write, used by Socket Mode so the SUT app can receive events.
extensions/slack/src/setup-shared.ts:12) to the
permissions and events covered by the live Slack QA suite. For the
production-channel setup as users see it, see
Slack channel quick setup; the QA Driver/SUT
pair is intentionally separate because the lane needs two distinct bot user
ids in one workspace.
1. Create the Driver app
Go to api.slack.com/apps → Create New App →
From a manifest → pick the QA workspace, paste the following manifest,
then Install to Workspace:
xoxb-...) - that becomes
driverBotToken. The driver can read/write fixture messages, reactions, and files;
it needs neither event subscriptions nor Socket Mode.
2. Create the SUT app
Repeat Create New App → From a manifest in the same workspace. This QA app
intentionally uses a narrower version of the bundled Slack plugin’s
production manifest (extensions/slack/src/setup-shared.ts:12): reaction
scopes and events are omitted because the live Slack QA suite does not cover
reaction handling yet.
- Install to Workspace → copy the Bot User OAuth Token → that becomes
sutBotToken. - Basic Information → App-Level Tokens → Generate Token and Scopes → add
scope
connections:write→ save → copy thexapp-...value → that becomessutAppToken.
auth.test on each
token. The runtime distinguishes driver and SUT by user id; reusing one app
for both will fail mention-gating immediately.
3. Create the channel
In the QA workspace, create a channel (e.g. #openclaw-qa) and invite both
bots from inside the channel:
Cxxxxxxxxxx id from channel info → About → Channel ID - that
becomes channelId. A public channel works; if you use a private channel
both apps already have groups:history so the harness’s history reads will
still succeed.
4. Register the credentials
Two options. Use env vars for single-machine debugging (set the four
OPENCLAW_QA_SLACK_* variables and pass --credential-source env), or seed
the shared Convex pool so CI and other maintainers can lease them.
For the Convex pool, write the four fields to a JSON file:
OPENCLAW_QA_CONVEX_SITE_URL and OPENCLAW_QA_CONVEX_SECRET_MAINTAINER
exported in your shell, register and verify:
count: 1, status: "active", no lease field.
5. Verify end to end
Run the lane locally to confirm both bots can talk to each other through the
broker:
qa-suite-report.md
shows both slack-canary and slack-mention-gating at status pass. If the
lane hangs for ~90 seconds and exits with Convex credential pool exhausted for kind "slack", either the pool is empty or every row is leased - qa credentials list --kind slack --status all --json will tell you which.