Fix selected-agent chat prompt contract

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-06-16 10:02:04 +00:00
1 parent e26ae06035
commit 4ec4f78e3a
15 files changed
+227 -15

No files matched your search

@@ -614,6 +614,8 @@ describe("renderPaperclipWakePrompt", () => {
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).toContain("kind suggest_tasks, ask_user_questions, or request_confirmation");
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).toContain("confirmation:{issueId}:plan:{revisionId}");
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).toContain("Wait for acceptance before creating implementation subtasks");
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).toContain("selected-agent chat turn");
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).toContain("evidence checked");
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).toContain(
"Respect budget, pause/cancel, approval gates, and company boundaries",
);
@@ -645,6 +647,46 @@ describe("renderPaperclipWakePrompt", () => {
expect(prompt).toContain("named unblock owner/action");
});
it("adds the selected-agent chat report contract to selected-agent comment wakes", () => {
const prompt = renderPaperclipWakePrompt({
reason: "issue_commented",
issue: {
id: "issue-1",
identifier: "PAP-11116",
title: "Selected-agent chat",
status: "in_progress",
workMode: "standard",
},
selectedAgentChat: true,
targetAgentId: "11111111-1111-4111-8111-111111111111",
taskKey: "selected-agent-chat:issue-1:11111111-1111-4111-8111-111111111111",
commentWindow: {
requestedCount: 1,
includedCount: 1,
missingCount: 0,
},
comments: [
{
id: "comment-1",
body: "How is the MCP work going?",
author: { type: "user", id: "board-user-1" },
createdAt: "2026-06-14T15:30:00.000Z",
},
],
fallbackFetchNeeded: false,
});
expect(prompt).toContain("selected-agent chat: yes");
expect(prompt).toContain("selected target agent id: 11111111-1111-4111-8111-111111111111");
expect(prompt).toContain("Report, What I checked, Recommendation, Options");
expect(prompt).toContain("issues, comments, runs, documents, work products, approvals, or dashboard state");
expect(prompt).toContain("suggest_tasks");
expect(prompt).toContain("request_confirmation");
expect(prompt).toContain("ask_user_questions");
expect(prompt).toContain("Do not expose API keys");
expect(prompt).toContain("Do not end with vague `let me know` or `I will check` prose");
});
it("preserves Chinese, Japanese, and Hindi issue and comment text in scoped wake prompts", () => {
const title = "验证中文任务";
const commentBody = [
@@ -126,6 +126,7 @@ export const DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE = [
"- When you intentionally restart follow-up work on a completed assigned issue, include structured `resume: true` with the POST /api/issues/{issueId}/comments or PATCH /api/issues/{issueId} comment payload. Generic agent comments on closed issues are inert by default.",
"- For plan approval, update the plan document first, then create request_confirmation targeting the latest plan revision with idempotencyKey confirmation:{issueId}:plan:{revisionId}. Wait for acceptance before creating implementation subtasks, and create a fresh confirmation after superseding board/user comments if approval is still needed.",
"- If blocked, mark the issue blocked and name the unblock owner and action.",
"- If this wake is a selected-agent chat turn, answer as the selected real agent with a concise report, evidence checked, recommendation, and concrete Paperclip next-step options; do not stop at \"I will check\".",
"- Respect budget, pause/cancel, approval gates, and company boundaries.",
].join("\n");
@@ -427,6 +428,9 @@ type PaperclipWakeTreeHoldSummary = {
type PaperclipWakePayload = {
reason: string | null;
issue: PaperclipWakeIssue | null;
selectedAgentChat: boolean;
targetAgentId: string | null;
taskKey: string | null;
checkedOutByHarness: boolean;
dependencyBlockedInteraction: boolean;
treeHoldInteraction: boolean;
@@ -638,6 +642,9 @@ export function normalizePaperclipWakePayload(value: unknown): PaperclipWakePayl
return {
reason: asString(payload.reason, "").trim() || null,
issue: normalizePaperclipWakeIssue(payload.issue),
selectedAgentChat: asBoolean(payload.selectedAgentChat, false),
targetAgentId: asString(payload.targetAgentId, "").trim() || null,
taskKey: asString(payload.taskKey, "").trim() || null,
checkedOutByHarness: asBoolean(payload.checkedOutByHarness, false),
dependencyBlockedInteraction: asBoolean(payload.dependencyBlockedInteraction, false),
treeHoldInteraction: asBoolean(payload.treeHoldInteraction, false),
@@ -735,6 +742,26 @@ export function renderPaperclipWakePrompt(
if (normalized.issue?.priority) {
lines.push(`- issue priority: ${normalized.issue.priority}`);
}
if (normalized.selectedAgentChat) {
lines.push(
"- selected-agent chat: yes",
`- selected target agent id: ${normalized.targetAgentId ?? "unknown"}`,
);
if (normalized.taskKey) {
lines.push(`- selected-agent task key: ${normalized.taskKey}`);
}
lines.push(
"",
"Selected-agent chat response contract:",
"- You are the selected real agent answering the board/user, not a concierge or substitute persona.",
"- For status, check-in, review-help, or investigative prompts, return a concise final answer in this shape: Report, What I checked, Recommendation, Options.",
"- In `What I checked`, name the Paperclip evidence you used, such as issues, comments, runs, documents, work products, approvals, or dashboard state. If you cannot access something, say that plainly.",
"- In `Options`, propose concrete next steps backed by Paperclip work objects or interactions, such as `suggest_tasks`, `request_confirmation`, or `ask_user_questions` when a real board choice is needed.",
"- Do not expose API keys, auth-token handling, internal tool narration, or raw command/debug notes.",
"- Do not end with vague `let me know` or `I will check` prose. Either answer from available context, create/suggest real follow-up work, or report the blocker and exact owner/action.",
"",
);
}
if (normalized.issue?.workMode === "planning") {
const hasWakeComments = normalized.comments.length > 0;
const acceptedPlanContinuation =
@@ -36,6 +36,17 @@ You MUST delegate work rather than doing it yourself. When a task is assigned to
- Hire new agents when the team needs capacity
- Unblock your direct reports when they escalate
## Board conversation mode
When the board asks for status, review help, or investigation through selected-agent chat, answer as the real CEO with a concise report instead of stopping at "I will check".
- **Report** - short answer first.
- **What I checked** - name the Paperclip evidence used: issues, comments, runs, documents, work products, approvals, dashboard state, or the gap you could not access.
- **Recommendation** - one preferred next step.
- **Options** - concrete Paperclip next steps. Use `suggest_tasks`, `request_confirmation`, or `ask_user_questions` when the board has a real choice.
Do not expose auth/token handling, raw tool narration, or debug notes. Keep the CEO boundary: summarize, prioritize, unblock, create or suggest follow-up issues, and delegate implementation to reports.
## Keeping work moving
- Don't let tasks sit idle. If you delegate something, check that it is progressing.
@@ -27,6 +27,10 @@ When you wake up, follow the Paperclip skill — it contains the full heartbeat
- Leave durable progress comments — what is done, what remains, who owns the next step.
- If you need to ship a fix that touches auth, crypto, secrets, or permissions, request review from a security reviewer before merging. Bundled teams ship without a dedicated SecurityEngineer — escalate to the CEO when the company needs one hired.
## Selected-agent conversation mode
When the board asks you for status, review help, or investigation through selected-agent chat, answer as the real selected agent with: Report, What I checked, Recommendation, and Options. Name the Paperclip evidence you used, propose concrete issue-backed next steps, and use `suggest_tasks`, `request_confirmation`, or `ask_user_questions` when a real board choice is needed. Do not expose auth/token handling, raw tool narration, or debug notes, and do not end with vague "I will check" prose.
## Safety
- Never commit secrets or customer data.
@@ -24,6 +24,10 @@ When you wake up, follow the Paperclip skill — it contains the full heartbeat
If the task requires authenticated browser steps, log in with the configured QA test account. Never treat an expected login wall as a blocker until you have attempted the documented login flow.
## Selected-agent conversation mode
When the board asks you for status, review help, or investigation through selected-agent chat, answer as the real selected agent with: Report, What I checked, Recommendation, and Options. Name the Paperclip evidence you used, propose concrete issue-backed next steps, and use `suggest_tasks`, `request_confirmation`, or `ask_user_questions` when a real board choice is needed. Do not expose auth/token handling, raw tool narration, or debug notes, and do not end with vague "I will check" prose.
## Safety
- Never paste secrets, session tokens, or PII into comments or screenshots. Redact before attaching.
@@ -28,6 +28,10 @@ When you wake up, follow the Paperclip skill — it contains the full heartbeat
- Use child issues for parallel or long delegated work — do not poll agents or sessions.
- Default to small bounded code reviews. Reject "kitchen sink" PRs back to the implementer.
## Selected-agent conversation mode
When the board asks you for status, review help, or investigation through selected-agent chat, answer as the real selected agent with: Report, What I checked, Recommendation, and Options. Name the Paperclip evidence you used, propose concrete issue-backed next steps, and use `suggest_tasks`, `request_confirmation`, or `ask_user_questions` when a real board choice is needed. Do not expose auth/token handling, raw tool narration, or debug notes, and do not end with vague "I will check" prose.
## Safety
- Never commit secrets, credentials, or customer data. If you spot any in a diff, stop and escalate.
@@ -23,6 +23,10 @@ When you wake up, follow the Paperclip skill — it contains the full heartbeat
If the task requires authenticated browser steps, log in with the configured QA test account. Never treat an expected login wall as a blocker until you have attempted the documented login flow.
## Selected-agent conversation mode
When the board asks you for status, review help, or investigation through selected-agent chat, answer as the real selected agent with: Report, What I checked, Recommendation, and Options. Name the Paperclip evidence you used, propose concrete issue-backed next steps, and use `suggest_tasks`, `request_confirmation`, or `ask_user_questions` when a real board choice is needed. Do not expose auth/token handling, raw tool narration, or debug notes, and do not end with vague "I will check" prose.
## Safety
- Never paste secrets, session tokens, or PII into comments or screenshots. Redact before attaching.
@@ -28,6 +28,10 @@ When you wake up, follow the Paperclip skill — it contains the full heartbeat
- When blocked, explain the blocker and include your best guess at how to resolve it.
- If a PR has already shipped to review, push follow-up changes for review feedback unless instructed otherwise.
## Selected-agent conversation mode
When the board asks you for status, review help, or investigation through selected-agent chat, answer as the real selected agent with: Report, What I checked, Recommendation, and Options. Name the Paperclip evidence you used, propose concrete issue-backed next steps, and use `suggest_tasks`, `request_confirmation`, or `ask_user_questions` when a real board choice is needed. Do not expose auth/token handling, raw tool narration, or debug notes, and do not end with vague "I will check" prose.
## Safety
- Never commit secrets, credentials, or customer data.
+15 -15
View File
@@ -2,7 +2,7 @@
"schemaVersion": 1,
"packageName": "@paperclipai/teams-catalog",
"packageVersion": "0.1.0",
"generatedAt": "2026-06-04T18:03:41.262Z",
"generatedAt": "2026-06-14T15:09:49.563Z",
"teams": [
{
"id": "paperclipai:bundled:company-defaults:core-exec-team",
@@ -102,20 +102,20 @@
{
"path": "agents/ceo/AGENTS.md",
"kind": "agent",
"sizeBytes": 2492,
"sha256": "50f580c51807762265f09c6fe7bf32d7701d64caeb30595bfd577b2f5087c21b"
"sizeBytes": 3301,
"sha256": "28f753e81abd5a7c14a080ef1be829527c8099d3299b00465145f34cfbf924e3"
},
{
"path": "agents/cto/AGENTS.md",
"kind": "agent",
"sizeBytes": 1449,
"sha256": "596e2e9fe08d7368b3b0cfe72c2635ea80444d92a2c0414157bfb0a17773fcaf"
"sizeBytes": 1983,
"sha256": "dab4f966a6021853e0fe0afb1332ebac19a88f5868002df69c6294a3b7e88992"
},
{
"path": "agents/qa/AGENTS.md",
"kind": "agent",
"sizeBytes": 1307,
"sha256": "2a139b88b4b98516048395c569c1bc74fd31cdc2da65db410e9779b8d92c0343"
"sizeBytes": 1841,
"sha256": "16404521e74713f0cf7e1e61f1d742461499b02422997604cfca7b47603495b0"
},
{
"path": "projects/first-project/PROJECT.md",
@@ -132,7 +132,7 @@
],
"trustLevel": "markdown_only",
"compatibility": "compatible",
"contentHash": "sha256:0f20e9d56124c1dc90a1e4b128fabd863538bcc935117220f719d9620f7c89f1"
"contentHash": "sha256:8492f6d4f057427fd457b86e437e6277c622f3c3611e2e0dc37af5f565f0d290"
},
{
"id": "paperclipai:bundled:product:product-design",
@@ -343,20 +343,20 @@
{
"path": "agents/cto/AGENTS.md",
"kind": "agent",
"sizeBytes": 1499,
"sha256": "0a1a73ec9e5008056bca0a26325131ded2fcf4c4680a5014ba1e13400b32c173"
"sizeBytes": 2033,
"sha256": "0c8ff1a61c4b4a03e822f8e0a2c2b8e7e3b11b39bb99587c3891b702633a7a64"
},
{
"path": "agents/qa/AGENTS.md",
"kind": "agent",
"sizeBytes": 1223,
"sha256": "2d5738f831aa772befa3471c844a0c9e611584be668e3ec82580ca9e92dc13fc"
"sizeBytes": 1757,
"sha256": "67096c53003efb62eb3cb405a117a97905bca978d94bb7f818225dc4c7dcee82"
},
{
"path": "agents/senior-coder/AGENTS.md",
"kind": "agent",
"sizeBytes": 1413,
"sha256": "b61071518755d9e584c099ae2082c7a78448d09586093ee91393082fe10872b5"
"sizeBytes": 1947,
"sha256": "81c83d20ee9965817fe56814edc16b0b937eaf1f24dc07c0832be9e3a0b21f70"
},
{
"path": "projects/product-engineering/PROJECT.md",
@@ -373,7 +373,7 @@
],
"trustLevel": "assets",
"compatibility": "compatible",
"contentHash": "sha256:74ddeaeb11805835a4a67fc4530b048ab7f8aa1dc7d2b80acea139a933d158d3"
"contentHash": "sha256:0624e20a8b4bd14d21fc6f6775e2139455a607eb78238cee9185b9a1e8d8f096"
},
{
"id": "paperclipai:optional:content:content-machine",
@@ -0,0 +1,39 @@
import { describe, expect, it } from "vitest";
import {
loadDefaultAgentInstructionsBundle,
resolveDefaultAgentInstructionsBundleRole,
} from "../services/default-agent-instructions.js";
describe("default agent instruction bundles", () => {
it("includes the selected-agent conversation report contract in generic agent instructions", async () => {
const bundle = await loadDefaultAgentInstructionsBundle("default");
expect(bundle["AGENTS.md"]).toContain("## Selected-Agent Conversation Mode");
expect(bundle["AGENTS.md"]).toContain("Report");
expect(bundle["AGENTS.md"]).toContain("What I checked");
expect(bundle["AGENTS.md"]).toContain("Recommendation");
expect(bundle["AGENTS.md"]).toContain("Options");
expect(bundle["AGENTS.md"]).toContain("suggest_tasks");
expect(bundle["AGENTS.md"]).toContain("request_confirmation");
expect(bundle["AGENTS.md"]).toContain("ask_user_questions");
expect(bundle["AGENTS.md"]).toContain("Do not expose API keys");
expect(bundle["AGENTS.md"]).toContain("I will check");
});
it("includes a CEO-specific board conversation contract without removing delegation boundaries", async () => {
const bundle = await loadDefaultAgentInstructionsBundle("ceo");
expect(bundle["AGENTS.md"]).toContain("## Board Conversation Mode");
expect(bundle["AGENTS.md"]).toContain("not a concierge, relay, or generic chatbot");
expect(bundle["AGENTS.md"]).toContain("Report");
expect(bundle["AGENTS.md"]).toContain("What I checked");
expect(bundle["AGENTS.md"]).toContain("Options");
expect(bundle["AGENTS.md"]).toContain("Keep the CEO boundary intact");
expect(bundle["AGENTS.md"]).toContain("you do not personally do implementation work");
});
it("still resolves only CEO roles to the CEO bundle", () => {
expect(resolveDefaultAgentInstructionsBundleRole("ceo")).toBe("ceo");
expect(resolveDefaultAgentInstructionsBundleRole("engineer")).toBe("default");
});
});
@@ -27,6 +27,19 @@ You MUST delegate work rather than doing it yourself. When a task is assigned to
- Hire new agents when the team needs capacity
- Unblock your direct reports when they escalate to you
## Board Conversation Mode
Sometimes the board talks to you through an issue-backed selected-agent chat surface. In that mode you are the real CEO for the conversation, not a concierge, relay, or generic chatbot.
For status, check-in, review-help, or investigative prompts, answer with a concise final report instead of stopping at "I will check". Use this shape, compressing it when the answer is small:
- **Report** - short answer first.
- **What I checked** - name the Paperclip evidence you used: issues, comments, runs, documents, work products, approvals, dashboard state, or the specific gap you could not access.
- **Recommendation** - one preferred next step.
- **Options** - concrete Paperclip next steps the board can choose from. Use normal issue-thread interactions such as `suggest_tasks`, `request_confirmation`, or `ask_user_questions` when a real choice is needed.
Keep the CEO boundary intact: you may summarize, prioritize, unblock, decide, create/suggest follow-up issues, or ask for board confirmation, but you do not personally do implementation work that belongs to a report. Do not expose API keys, auth-token handling, raw tool/debug narration, or internal command details in the answer. Do not end with vague "let me know" or "I will check" prose.
## Keeping work moving
- Don't let tasks sit idle. If you delegate something, check that it's progressing.
@@ -15,4 +15,17 @@ You are an agent at Paperclip company.
- If someone needs to unblock you, assign or route the ticket with a comment that names the unblock owner and action.
- Respect budget, pause/cancel, approval gates, and company boundaries.
## Selected-Agent Conversation Mode
Sometimes the board or a teammate talks to you through an issue-backed selected-agent chat surface. In that mode you are the real selected agent for the conversation, not a concierge, relay, or generic chatbot.
For status, check-in, review-help, or investigative prompts, answer with a concise final report instead of stopping at "I will check". Use this shape, compressing it when the answer is small:
- **Report** - short answer first.
- **What I checked** - name the Paperclip evidence you used: issues, comments, runs, documents, work products, approvals, dashboard state, or the specific gap you could not access.
- **Recommendation** - one preferred next step.
- **Options** - concrete Paperclip next steps the board can choose from. Use normal issue-thread interactions such as `suggest_tasks`, `request_confirmation`, or `ask_user_questions` when a real choice is needed.
Do not expose API keys, auth-token handling, raw tool/debug narration, or internal command details in the answer. Do not end with vague "let me know" or "I will check" prose. Either answer from available context, create or suggest real follow-up work, or name the blocker and exact owner/action.
Do not let work sit here. You must always update your task with a comment.
+3
View File
@@ -2680,6 +2680,9 @@ export async function buildPaperclipWakePayload(input: {
workMode: issueSummary.workMode,
}
: null,
selectedAgentChat: input.contextSnapshot.selectedAgentChat === true,
targetAgentId: readNonEmptyString(input.contextSnapshot.targetAgentId),
taskKey: readNonEmptyString(input.contextSnapshot.taskKey),
childIssueSummaries: Array.isArray(input.contextSnapshot.childIssueSummaries)
? input.contextSnapshot.childIssueSummaries
: [],
+31
View File
@@ -0,0 +1,31 @@
import { describe, expect, it } from "vitest";
import { composeCeoInstructions } from "./ceo-instructions";
describe("composeCeoInstructions", () => {
it("includes the board conversation report and options contract", () => {
const instructions = composeCeoInstructions({
companyName: "Acme AI",
companyGoal: "Ship useful agent workflows",
growPath: false,
growWorkflows: "",
growPainPoints: "",
growAutomate: "",
q1: "We build workflow tools.",
q2: "Operations teams.",
q3: "Manual coordination.",
q4: "Faster execution.",
});
expect(instructions).toContain("# Board conversation contract");
expect(instructions).toContain("answer as the real CEO");
expect(instructions).toContain("Report");
expect(instructions).toContain("What I checked");
expect(instructions).toContain("Recommendation");
expect(instructions).toContain("Options");
expect(instructions).toContain("suggest_tasks");
expect(instructions).toContain("request_confirmation");
expect(instructions).toContain("ask_user_questions");
expect(instructions).toContain("Keep the CEO boundary intact");
expect(instructions).toContain("I will check");
});
});
+13
View File
@@ -52,6 +52,19 @@ ${contextLines.join("\n")}
Use this context directly when you write any work product. Do not re-ask the user for information they've already shared.
# Board conversation contract
When the board asks for a status check, review help, or an investigation, answer as the real CEO with a concise final report instead of stopping at "I will check".
Use this shape, compressing it when the answer is small:
- **Report** - short answer first.
- **What I checked** - name the Paperclip evidence you used: issues, comments, runs, documents, work products, approvals, dashboard state, or the gap you could not access.
- **Recommendation** - one preferred next step.
- **Options** - concrete Paperclip next steps the board can choose from. Use normal issue-thread interactions such as \`suggest_tasks\`, \`request_confirmation\`, or \`ask_user_questions\` when a real choice is needed.
Keep the CEO boundary intact: summarize, prioritize, unblock, decide, create or suggest follow-up issues, or ask for board confirmation, but delegate implementation work to the right report. Do not expose API keys, auth-token handling, raw tool/debug narration, or internal command details. Do not end with vague "let me know" or "I will check" prose.
# Hiring plan output format
Any time you produce a hiring plan, describe each role using the exact template below. Every role gets all seven sections. Use \`##\` for the role heading (numbered) and \`###\` for each section heading: