## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Slack connections let people talk to an agent with their own Paperclip permissions. > - Each bot has a saved command that starts account linking. > - The Access page explains this flow, but Slack agent turn context omitted it. > - An agent could guess the command or confuse channel membership with Paperclip access. > - This pull request gives agents the saved command and account confirmation instructions. > - People can ask the agent how to join without changing access controls. ## Linked Issues or Issue Description **What happened?** Slack agent context explained messages, tools, and questions. It did not explain how a teammate can connect an account. The saved slash command can differ from the current agent name. **Expected behavior** Give the saved bot command, such as `/research_ops connect`. The teammate runs it themselves. They sign in through a private confirmation link. A new company member must receive admin approval before account confirmation. The connection manager can copy instructions from Access → Invite people. **Steps to reproduce** 1. Configure a Slack bot with a custom slash command. 2. Rename its assigned agent. 3. Inspect a fresh or resumed Slack task prompt. Before this change, it contains no account invitation instructions or saved connect command. **Paperclip version or commit** Base: `d6df12cef69fcaf2d2fe66a393168931d5b8b4e7`. **Deployment mode** Applies to local and hosted Slack chat connections. Deterministic tests used a local isolated database. The new model probe has not run against a live Slack bot. Related work: Refs #15413 and #13638. This fixes agent guidance for their existing account-linking flow. It adds no new membership system or invitation endpoint. ## What Changed - Read only the saved public slash command from the company-scoped conversation endpoint. Supply it only to the assigned agent for Slack turns with an active or verifying connection. - Validate the command with the shared Slack configuration schema. Refer to Access → Invite people when it is missing or invalid. Never guess from the current agent name. - Explain personal account confirmation, link expiry, and company membership approval on fresh and resumed turns. Distinguish channel invitations from Paperclip access. - Add deterministic guidance regressions, a manual invitation model probe, and setup documentation. ## Verification - Passed: 63 tests in `heartbeat-context-summary.test.ts` and `heartbeat-chat-task-link.test.ts`. - Passed: four real-heartbeat regressions in `heartbeat-slack-invitation.test.ts`. They check the saved command after an agent rename, a persisted resumed session, full and compact prompts, missing-command fallback, inactive endpoints, and a different assigned agent. They also reject caller-supplied command fields and exclude other setup metadata. - Passed: the isolated `chat-channels.integration.test.ts` case `discovers a Slack connect identity without starting work or granting access`. It covers the private link, duplicate connect requests, and nonmember access requests without a membership grant. - Passed: `pnpm --filter @paperclipai/server typecheck` and `pnpm --filter @paperclipai/server build`. - Passed: `pnpm test:slack-connector --list` and `git diff --check`. - Passed: repository `pnpm -r typecheck`, `pnpm build`, and `pnpm check:token-gates`. Typecheck required local IPC access for the migration check. - Passed: final-commit CI, with 54 successful checks and two optional Storybook checks skipped. CI includes all server, chat, workspace, serialized, Runner, and browser test shards, typecheck, build, and canary dry run. - The full local `pnpm test:run` was started. It was stopped after full CI passed; it had no final local summary. The focused invitation checks passed locally. Do not count the interrupted local run as a full-suite pass. - Greptile gave the exact final commit `f37e52bde621ef7f5b2bb345074d53345f8e4ee9` a 5/5 score. Both review findings were fixed and their threads resolved. - The new `invite-person` model probe is manual. These deterministic results do not establish a live model or Slack acceptance pass. ## Risks - Model guidance cannot prove that a person joined. The existing account-linking and membership checks remain authoritative. - Legacy rows without a saved command use the Access page fallback. Invalid command text is excluded from the prompt. - The query selects only the public command. It does not expose registration secrets, tokens, or personal confirmation links. - No schema changes, new provider requests, permission grants, or telemetry changes. ## Model Used - OpenAI GPT-6 through Codex. The exact backend variant and context window are not exposed in this session. Used reasoning, repository inspection, code editing, and test execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
Slack connector behavior checks
Keep Slack-specific guidance and acceptance probes next to the connector.
Production per-turn guidance is in ../agent-guidance.ts;
individual action descriptions are in
packages/shared/src/slack-tools.ts.
Coverage and gaps
cases.json defines twelve neutral user prompts with fixtures,
independent expected outcomes, required evidence, and related deterministic
regressions. These are manual model acceptance probes, not registered Runner
or Product E2E workflows. Running the regressions does not run those prompts,
invoke a model, or contact Slack. Each linked regression covers part of the
contract; its pass does not establish the probe's complete outcome.
| Feature | Guidance to preserve | Acceptance probe |
|---|---|---|
| Choice questions and forms | Use saved Paperclip questions; Slack controls answer and resume the same task. | choice-question, question-form |
| Files | Current-chat artifact handoff; explicit uploads elsewhere use an existing attachment. Verify delivery. | file-reply |
| Mentions and replies | A bare mention starts a real conversation; unmentioned thread replies continue it. | thread-followup |
| Search and history | Use authorized sources and real permalinks; disclose bounded coverage. | search-coverage |
| Private research | Honor source/destination restrictions, including files. | private-source |
| Posts, reactions, pins, bookmarks | Ordinary replies are delivered automatically; explicit actions use assigned tools. | explicit-post-and-reaction |
| Uncertain writes | Keep the operation identity and inspect delivery; never resend with a new key. | uncertain-write |
| Destructive changes and invitations | Honor the saved action policy and approval decision. | approval-decline |
| Canvases and lists | Use advertised capabilities; explain plan/scope limitations without inventing success. | canvas-list-availability |
| Task links | Use the server-provided public URL. | task-link |
| People joining | Give the saved bot command, personal confirmation flow, and company-access approval. Channel invitations do not grant Paperclip access. | invite-person |
Pins, bookmarks, channel topics, invitations, list edits, and channel creation
have tool descriptions and transport fixtures but no dedicated model probe here
yet. Those provider channel invitations are distinct from the invite-person
account-linking guidance probe. The canvas probe does not qualify list editing. Automatic app creation,
OAuth, setup navigation, and installation recovery are a separate onboarding
surface covered by the existing setup and browser tests.
Run deterministic regressions
From the repository root:
pnpm test:slack-connector --list
pnpm test:slack-connector --case choice-question
pnpm test:slack-connector
The selector runs existing Vitest files; it adds no grader or parallel eval
framework. Local HTTP/database fixtures may need normal development permissions.
It deliberately omits chat-channels.integration.test.ts, which requires an
isolated migrated database. Never point that suite at a live test-drive database.
With a disposable database supplied, run the supplementary integration checks:
PAPERCLIP_TEST_DATABASE_URL=<disposable-database-url> pnpm exec vitest run server/src/__tests__/chat-channels.integration.test.ts -t 'refreshes Slack tool guidance|provides assigned Slack tools|binds Slack tools to the admitted linked request'
The catalog records additional large-suite fixture locations for write, approval, lifecycle, and canvas/list behavior. Select their exact test names from that file when investigating those features.
Run a model acceptance probe
Use an isolated Paperclip company and explicitly authorized Slack workspace and destinations. Seed synthetic content and record the expected result before starting. Send the case's neutral prompt through the real conversation, retain the required evidence, and grade actual provider state rather than agent prose. For questions, answer through Slack and observe the continuation. For files, download and inspect the delivered bytes. Inject uncertain-write faults only through a controlled provider fixture.
Record the Paperclip revision, case/version, model and adapter, legacy/native runtime, effective tool policies, fixture identity, run/task/interaction/action IDs, timestamps, actual provider result, sanitized evidence, and cost when available. Distinguish model failure, product failure, fixture failure, authentication/permission failure, and infrastructure failure. A missing evidence item is unverified, not a pass. Never retain tokens or private customer content in the evidence.
The attended zoo-question test on 2026-10-07 exercised legacy codex_local
(gpt-5.6-sol) with real Slack choices, saved answer, same-task continuation,
and a delivered correct answer. Its task was
34d0ce26-0040-4689-a97c-f76d975abeaf; the question message was
1791402669.801139 and the final reply was 1791402744.785019 in the authorized
test DM. It does not qualify every case or native runtime.
The 2026-10-08 acceptance record attempted the ten remaining cases through Carlos: five passed, two failed, and three were partly verified. It includes sanitized durable evidence, invalid attempts, runtime qualification limits, and the controlled uncertain-write boundary. These results do not constitute a fully passing campaign.
To automate these probes, extend the canonical
tests/runner-e2e Product E2E
catalog and evidence/grading path. Runner-only protocol cases belong in the
separate paperclip-evals repository. Follow
doc/evals.md; no Slack model campaign is
registered or launched by this folder.