From 9dcf1e5c430454615a8bef3dfb4c4a5f18d6982e Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Sun, 8 Nov 2026 05:13:56 -0600 Subject: [PATCH] fix(chat): tell chat agents a task they cannot find may be private (#20027) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - People talk to agents in chat, and the chat agent acts with the agent's own access > - Tasks can be private, and an agent cannot see a private task unless it has access > - The chat guidance did not tell the agent this, so a hidden task looked like a missing task > - The agent then searched through many other tools, endpoints and files, and the turn ran out before it answered > - This pull request adds one paragraph of chat guidance: a task the agent cannot find may be private, stop searching, and tell the person how to share it > - The benefit is a fast, honest answer that keeps the privacy boundary and gives the person a real next step ## Linked Issues or Issue Description **What happened** A person asked a chat agent to summarize a private task in the same company. The agent has no access to that task, so search returned nothing. The agent kept searching for about five minutes (tasks, documents, activity, chats, files, API catalog) and did not reply before the turn limit. **Expected behavior** The agent says that this chat cannot see the task, possibly because it is private. It does not search for a way around the boundary or guess the content. It tells the person that they can share the task with the agent from the task's sharing controls, or paste the parts they want. **Steps to reproduce** 1. In an authenticated instance, create a private task with you as the responsible user. 2. Do not share it with the CEO agent. 3. Open a chat with the CEO and ask: "Summarize the private acquisition task for me here." 4. Watch the run: the agent searches repeatedly and does not answer in a reasonable time. ## What Changed - `server/src/services/agent-conversations.ts`: add a chat guidance paragraph. It says that private tasks are hidden from the agent's searches and lookups, that a task it cannot find may be private, that it must not search further or guess, and that the person can share the task from its sharing controls or paste the content. - `server/src/__tests__/agent-conversations.test.ts`: add a regression test for the new guidance. ## Verification - `pnpm exec vitest run server/src/__tests__/agent-conversations.test.ts` passes (50 tests). - Chat eval `access.private-resource` (runner-opencode), cherry-picked onto the eval branch: before the change, the agent searched for 4.5 minutes with no reply and the cell timed out. After the change, the run took 39 seconds and passed. The reply: "I can't see a private acquisition task from this chat. ... it's likely private or not shared with me. If you want a summary, open that task and share it with me from its sharing controls, or paste the relevant details here". ## Risks - Low risk. This is prompt guidance only. No API or permission behavior changes. - An agent can stop searching early for an open task that a vague query did not match. The guidance limits this to a task that one search does not find, and the agent still tells the person what it could not find. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - Anthropic Claude Opus 5.5 (`claude-opus-5-5`), tool use and code execution in Claude Code. ## 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 - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 --- server/src/__tests__/agent-conversations.test.ts | 5 +++++ server/src/services/agent-conversations.ts | 2 ++ 2 files changed, 7 insertions(+) diff --git a/server/src/__tests__/agent-conversations.test.ts b/server/src/__tests__/agent-conversations.test.ts index 5d76736fa37..deb40dbbd72 100644 --- a/server/src/__tests__/agent-conversations.test.ts +++ b/server/src/__tests__/agent-conversations.test.ts @@ -1057,6 +1057,11 @@ describe("chat prompt policy", () => { const prompt = buildPaperclipTaskMarkdown({ issue: { id: "chat", identifier: null, title: "Chat", workMode: "ask", conversationAgentId: "agent" } }); expect(prompt).toContain("//issues/"); }); + it("treats a same-company task the agent cannot find as possibly private instead of searching for a way in", () => { + expect(AGENT_CHAT_DIRECTIVE).toContain("A private task is hidden from you unless you have access to it"); + expect(AGENT_CHAT_DIRECTIVE).toContain("it may be private rather than missing. Do not search for it further"); + expect(AGENT_CHAT_DIRECTIVE).toContain("share it with you from its sharing controls"); + }); it("tells chat agents to keep every listed task linked, and where a long list goes", () => { expect(AGENT_CHAT_DIRECTIVE).toContain("write each task identifier in full"); expect(AGENT_CHAT_DIRECTIVE).toContain("a range such as RUN-12–14 links only its first task"); diff --git a/server/src/services/agent-conversations.ts b/server/src/services/agent-conversations.ts index 66e0f6ee97a..659289ef873 100644 --- a/server/src/services/agent-conversations.ts +++ b/server/src/services/agent-conversations.ts @@ -120,6 +120,8 @@ A person's own display name and avatar belong to their account, and only they ca This conversation and your credentials belong to one company. A task identifier whose prefix differs from this conversation's prefix belongs to another company or to none, and you cannot read it here, even when the person can open it themselves: a lookup that is not found does not mean the task does not exist. Do not search for it further, guess its content or copy anything from it. Say that this chat can only work in this company, and that to use that task the person can switch to its company and open a chat there. Link the task at //issues/, taking the prefix from the identifier the person gave; this is the one link that does not use this conversation's prefix. +Tasks and projects in this company can be private. A private task is hidden from you unless you have access to it: your searches, lists and direct lookups leave it out or return not found, even when the person who asks can open it. So when the person refers to a task in this company that one search does not find, especially one they call private, it may be private rather than missing. Do not search for it further through other tools, endpoints, files or activity records, and do not guess its content. Say that this chat cannot see that task, possibly because it is private, and that if they want you to work on it they can open the task and share it with you from its sharing controls, or paste the parts they want here. + For status updates, distinguish recorded task status from active execution and verified progress. Read the latest relevant comments and run outcome before explaining a blocker or claiming work is underway. Use the advertised API tools for another task's details when needed. A completed dependency does not prove a block is stale; report the assignee's recorded reason. Agent configuration may be redacted: an empty configuration object without configuration-read permission does not prove settings are disabled or at their defaults. If the evidence is unavailable, say what you could verify and what remains unknown rather than guessing or recommending a status change. Keep discussion here and leave the conversation available for the next message. Link handed-off tasks in your reply; do not make this conversation blocked by their completion or wait for them. Paperclip will bring completed handed-off tasks back as a new input here so you can explain the result and link it without another user message. After creating an assigned task, let its own run execute the work; do not create its deliverables or change its execution status from this chat. Reply normally and end your turn; Paperclip manages the conversation waiting state. Do not change its status, create a review confirmation just to finish a reply, mark it complete, or poll for another reply. An accepted plan authorizes handoff to execution tasks, never implementation on this conversation. Honor normal approvals. Ask mode is non-mutating. Plan mode supports research and writing/revising the plan; hand off for execution only through the normal authorized workflow.`;