Files
PaperClipAI/maps/agent-access-map/chat-channels.md
T
DottaandPaperclip 2cbca4ceb0 fix: retain channel tools across task continuations (#16806)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat channels give an agent tools for its assigned task.
> - Each later run must resolve the task and its accepted requester
again.
> - Some native runs store the task in a database column without the
older JSON fields.
> - Tool discovery read only the JSON fields. GitHub calls also required
a new inbound comment.
> - This pull request uses the durable task binding and accepted request
history.
> - Later runs retain their channel tools while current access checks
still apply.

## Linked Issues or Issue Description

**What happened?**

A GitHub task can find `begin_review` on its first run, then receive an
empty tool list on a later native run. If discovery is repaired alone, a
call can still fail because the later run has no new inbound comment.
Slack and voice tool access also read the older JSON task fields.

**Expected behavior**

A later run for the same task can find and call its assigned channel
tools. The current requester, task, company, agent, endpoint, and access
rules must still allow the call. Revoked access must fail.

**Steps to reproduce**

1. Start a GitHub task and accept its linked requester.
2. Confirm that the runtime can find `begin_review`.
3. Start a later native run with `nativeIssueId`, accepted parent
identity, and no JSON task ID or new wake comment.
4. Search for `begin_review` again. Before this change, the search
returns an empty list.
5. Repair discovery alone and call `read_pull_request`. Before the
request-history fix, the call fails with no active conversation
capability.

**Paperclip version or commit**

Reproduced in source tests before this patch. The branch includes master
at `fa50cab5685b9cdbb26ad9c610cc5b6c373d3ff4`.

**Additional context**

This is a core run-binding bug. The tests use PostgreSQL and synthetic
provider responses. They do not send live reviews, Slack messages, or
phone calls.

## What Changed

- Resolve run task IDs from durable columns, with legacy JSON fields as
a fallback.
- Use the same binding in the gateway, access policy, identity service,
and channel runtime preparation.
- Recover accepted channel request history across later runs. Keep
company, task, agent, and requester boundaries.
- Recover older wake sources through verified parent runs, including
after same-user board follow-ups. Clear the board message’s own legacy
wake fallback. Keep cycle checks without a fixed limit on valid task
history.
- Retain the GitHub origin after a board comment from the same accepted
user. Skip GitHub origin lookup results from other providers.
- Keep ordinary board tools available when the requester changes. Accept
legacy user comments without an author-type field. Still reject explicit
malformed task IDs.
- Prevent a later failure reply from replacing an earlier final GitHub
answer. Recheck this rule under the publication lease.
- Rotate the native tool contract to replace retained sessions with an
older tool list.
- Add continuation, publication, revocation, and boundary tests. Update
the access and feature maps.

## Verification

- Red: the later GitHub assigned-tool search returned an empty list
before the binding fix.
- Red: the later GitHub read failed with no active conversation
capability before the request-history fix.
- Green: runtime MCP discovery, GitHub read/begin/submit review, and
response publication pass for monitor and same-user board continuations.
- Green: Slack history, retained access controls, revocation, and voice
gateway continuation pass.
- Green: 35 channel, failure-publication, legacy-origin, long-history,
and provenance tests pass. Both review findings had failing tests before
their fixes.
- Green: 107 gateway, operation-credential, identity, and provenance
tests pass. These cover both first-run CI failures without changing
their tests.
- Green: 122 runtime, discovery-policy, and native-session tests pass; 2
unrelated tests are skipped.
- Map checks and whitespace checks pass.
- Updated to master in `cfcaba22628772d7fe1fb32b57ff7031c7072781`. The
sole conflict was two tests added at the same location. Both the
continuation test and the publication 403/401 test are retained.
- Current local verification: all 179 gateway, credential,
requester-identity, access-policy, runtime-context, and session-resume
tests passed. Repository typecheck and build passed. Map and whitespace
checks passed.
- The new review regression first returned no source for a same-user
board follow-up over legacy wake metadata. After the repair, all 27
provenance and channel cases passed. The combined GitHub
discovery/read/begin/submit path and revoked access are covered.
- The broader local channel run passed 176 cases and failed four
timing/setup cases: a 15-second Slack authorization timeout,
webhook-verification polling, a Slack acknowledgement deadline, and
Discord setup polling. All four passed in isolation without source,
assertion, or deadline changes. The earlier failure record is retained;
the exact load/order cause is not established. Full CI must pass on the
latest commit.
- Current head: `7b9a08dcbc7b8140b589742f136944270b0496bb`. Repository
typecheck and build pass on this commit. Greptile completed on this
exact commit with 5/5; all four review threads are resolved. The
final-head [CI
run](https://github.com/paperclipai/paperclip/actions/runs/39278921653)
passed: 55 checks passed and 2 intentionally skipped, with no failures
or pending checks. This includes the full sharded test matrix, browser
tests, typecheck, build, and Runner verification. Results were delayed
during the [GitHub Actions
incident](https://www.githubstatus.com/incidents/8tzbpcnl75jp). An
additional unsharded local full test run has not completed; the
completed full-suite evidence is CI.
- Earlier verification: the first PR commit failed two server suites.
Those failures were fixed and verified before this update. The original
4 GiB sandbox could not complete full local typechecking or tests; the
current checkout completed typechecking and build. The full test suite
runs through the CI shards. No full local test-suite pass or live
provider delivery is claimed.

## Risks

- Request history can restore the wrong authority if its scope is too
broad. The resolver checks each accepted parent against the task,
company, agent, and requester. Tests cover invalid and cyclic history.
- The native contract change starts a new provider session for older
contracts.
- No database migration or public API schema changes are required. Each
tool call still checks live access.

## Model Used

- OpenAI Codex, GPT-6 family. The runtime does not expose the exact
deployment model ID or context-window size. The agent used reasoning,
repository tools, code edits, and local 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-19 11:20:39 -05:00

12 KiB

External chat and email conversations — agent access

Product map: External chat and email conversations.

Review date: 2026-10-12. Source commit: 58e16dbddfc9c8d0cf60867f9d9847f0feda055b. Native REST transport reconciled in this change; see the shared transport contract.

This is a source-reviewed baseline of representative operations and known gaps. Each capability needs operation-level review before its entire scope can be qualified. No live agent execution is claimed. Follow the map contract for format, permission checks, evidence and maintenance.

providers

Review: baseline.

API: present — representative operation IDs:

  • POST /api/companies/{companyId}/chat-endpoints.

Agent access: restricted — Board setup APIs; native connection request can ask for setup.

Policy: Endpoint management/identity linking requires a board user; delivery is server-owned and agent tools use scoped assignments.

Evidence: source-only — implementation at the reviewed commit above.

Verification: not-run — assert the documented agent denial with an owned test fixture; verify any listed agent request/result path separately. A delegated operation needs its own policy and access review.

Gaps: Provider installation and account enrollment are not available to an ordinary agent actor.

Speko UI reconciliation (2026-10-13): experimental voice setup uses the same board-managed endpoint boundary. Source review follows the merged voice runtime and the UI integration; live provider qualification is still separate.

identity

Review: baseline.

API: present — representative operation IDs:

  • POST /api/chat-identity-links/confirm.

Agent access: restricted — Human identity-link flow.

Policy: Endpoint management/identity linking requires a board user; delivery is server-owned and agent tools use scoped assignments.

Evidence: source-only — implementation at the reviewed commit above.

Verification: not-run — assert the documented agent denial with an owned test fixture; verify any listed agent request/result path separately. A delegated operation needs its own policy and access review.

Gaps: Identity linking requires a signed-in board user, rollout admission and provider checks at the HTTP route. Native call_api preserves these permissions.

conversation

Review: baseline.

API: present — representative operation IDs:

  • POST /api/chat-endpoints/{endpointId}/conversations/{conversationId}/publications.

Agent access: partial — Assigned-agent reply pipeline; native completion; provider tools where assigned.

Policy: Endpoint management/identity linking requires a board user; delivery is server-owned and agent tools use scoped assignments.

Evidence: source-only — implementation at the reviewed commit above.

Verification: not-run — exercise a listed permitted operation with actual agent credentials/run context; inspect its result and applicable persistence/attribution. Assert the relevant denied actor, owner, company or mode from Policy. Review the remaining operations before qualifying the whole capability.

Gaps: Normal agent replies work through server delivery. Explicit endpoint publication APIs are board management paths.

Publication, provider-reply, and form-open 403/permission errors fail the rejected operation without removing unrelated assigned channel tools. Confirmed authentication failures still put the endpoint in attention, which blocks tool admission and provider sends; connection enabled intent is retained. Known resource denials and explicit revocation keep their narrower or installation-wide stops. PostgreSQL provider fixtures verify discovery after 403 and rejection after 401, including signed installation removal after a 401; they do not establish live GitHub credential recovery.

GitHub publication recovery (2026-10-14): assigned-agent submit_review, comment, and update_comment calls reuse their run-, task-, endpoint-, and argument-bound publication on an exact retry. Fresh gateway policy and provider authority remain required. The durable worker resumes transient failures after restart and stops at its retry cap, revoked authority, or a superseded head. A pending receipt is not task completion. Source: publication service and gateway. Verification uses PostgreSQL-backed provider fixtures; this entry does not claim live provider qualification for the new retry path.

Speko browser sessions use POST /api/companies/{companyId}/voice-sessions, with GET inspection/notification and POST /{sessionId}/end operations below that collection. These routes require board identity; ordinary agent credentials cannot start a private voice session. Start and notification also require the experimental chat-connectors gate. Signed provider callbacks use the separate voice-webhook routes and their session capability. Evidence: source-only — voice routes. No live browser answer retrieval or telephone playback is established by the UI fixtures.

Slack's Require at-mention policy applies to channel messages and channel thread replies, including queued work. DMs are exempt from mention checks; endpoint availability, Allow direct messages, and sender authorization still apply. Top-level DM replies retain their linear conversation destination. Source: admission and queued run policy. Live Slack verification of this exemption remains separate from provider-fixture coverage.

Slack eyes acknowledge the authorized task/comment commit before attachment preparation or scheduler acceptance. This server-owned receipt grants no agent authority. Generation/credential fencing, durable retries and exact-source final cleanup still apply. PostgreSQL fixtures block attachments, subscription and wakeup independently to verify that none gates the reaction; live Slack latency remains a separate check. See receipt worker.

Controller-owned receipt reactions accept the SDK's empty thread timestamp for linear DMs. Channel IDs and source message timestamps remain validated. This does not add an agent tool or change sender, task, or credential authorization. The pinned SDK transport regression is covered in receipt tests; live acknowledgement speed needs a separate provider test.

Slack assignment and tool discovery bound concurrent endpoint preparation to two. Every endpoint keeps the live task, company, agent and linked-user checks; 403 denials omit only that endpoint. Preparation waits for both active checks before it returns an ordered result or propagates an error. Tool authority reads the current bot token without resolving unrelated webhook credentials. See the real-database preparation controls and batch failure controls. These local controls do not establish live Slack latency or provider access.

Native tool gateways use the durable run task binding for discovery and policy checks, with legacy JSON task fields as a fallback. GitHub and Slack follow accepted request provenance across task continuations. GitHub can retain the originating conversation after a board follow-up from the same accepted user. An inherited origin cannot cross a task, agent, company, or requester boundary. Cycle checks reject invalid history without a fixed limit on valid continuations. Endpoint settings, linked identity, tool profiles, and invocation policy still apply on each call. The native tool contract rotates older provider sessions so an empty retained catalog is not reused. PostgreSQL fixtures cover discovery, review publication, Slack reads, and revocation in channel integration and provenance controls. The voice gateway fixture also verifies durable task binding for a later personal callback invocation. Failure replies cannot replace final answers inherited from an earlier run. These fixtures do not prove live provider delivery.

Catalog authorization projection (2026-10-17): tool discovery uses the same live service-owned task, company, agent, requester, endpoint and credential checks as full authority resolution. It omits the revision digest and search-action token, which catalog descriptors do not consume. Connector assignments and governed operations retain full revision resolution; invocation policy is still checked by the gateway. Registry replacement and missing-service controls are in authority registration tests. This is a source and local-database contract; hosted latency needs live evidence.

New conversations resolve typed project/workspace defaults from their endpoint and destination under the task-creation transaction. Defaults do not authorize private sources: admission checks the linked user's authority and assigned agent. An existing conversation keeps its task binding. See creation service and defaults contract.

attachments

Review: baseline.

API: present — representative operation IDs:

  • GET /api/issues/{id}/attachments.
  • POST /api/companies/{companyId}/issues/{issueId}/attachments.

Agent access: partial — Native register_deliverable / attachment tools when admitted; agent REST; server-owned delivery.

Policy: Endpoint management/identity linking requires a board user; delivery is server-owned and agent tools use scoped assignments.

Evidence: source-only — implementation at the reviewed commit above.

Verification: not-run — exercise a listed permitted operation with actual agent credentials/run context; inspect its result and applicable persistence/attribution. Assert the relevant denied actor, owner, company or mode from Policy. Review the remaining operations before qualifying the whole capability.

Gaps: Uploading/registering is supported. Provider delivery status and board replay are separate operations.

lifecycle

Review: baseline.

API: present — representative operation IDs:

  • GET /api/chat-endpoints/{endpointId}/activity.
  • PATCH /api/chat-endpoints/{endpointId}.
  • PUT /api/chat-endpoints/{endpointId}/resources configures destination defaults.

Agent access: restricted — Board lifecycle APIs; agent requests repair when blocked.

Policy: Endpoint management/identity linking requires a board user; delivery is server-owned and agent tools use scoped assignments.

Evidence: source-only — implementation at the reviewed commit above.

Verification: not-run — assert the documented agent denial with an owned test fixture; verify any listed agent request/result path separately. A delegated operation needs its own policy and access review.

Gaps: Activity/repair/replay/disable use board endpoint access, not the agent's ability to reply.

Endpoint/destination execution defaults use the same board-only management boundary. Agents select an authorized workspace for their current task through the workspace APIs, rather than editing channel configuration.

Speko callback preferences, incoming phone configuration/approval, and call history use the company-scoped voice-callbacks, voice-phone, and voice-history routes. Their UI controls do not grant agents board authority. See voice routes; service-level caller/session permissions and real provider delivery need separate verification.

GitHub review summary headings use the bot display name. Checks remain independently scoped by GitHub App and endpoint/PR/commit identity.