Files
PaperClipAI/server/src/services/connectors/slack/evals
DottaandPaperclip 71af2fbc3b fix(slack): teach agents how people connect their accounts (#15576)
## 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>
2026-10-08 10:28:14 -05:00
..

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.