From d6bb71f3241a0925155c59351f6a8d9a2f874bea Mon Sep 17 00:00:00 2001 From: dotta Date: Fri, 20 Mar 2026 07:42:36 -0500 Subject: [PATCH] Add default agent instructions bundle Co-Authored-By: Paperclip --- .../src/__tests__/agent-skills-routes.test.ts | 24 +++++++++++++++++++ .../src/onboarding-assets/default/AGENTS.md | 3 +++ server/src/routes/agents.ts | 9 ++++--- .../services/default-agent-instructions.ts | 5 ++++ 4 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 server/src/onboarding-assets/default/AGENTS.md diff --git a/server/src/__tests__/agent-skills-routes.test.ts b/server/src/__tests__/agent-skills-routes.test.ts index eb71a082..bb3dd17b 100644 --- a/server/src/__tests__/agent-skills-routes.test.ts +++ b/server/src/__tests__/agent-skills-routes.test.ts @@ -369,6 +369,30 @@ describe("agent skill routes", () => { ); }); + it("materializes the bundled default instruction set for non-CEO agents with no prompt template", async () => { + const res = await request(createApp()) + .post("/api/companies/company-1/agents") + .send({ + name: "Engineer", + role: "engineer", + adapterType: "claude_local", + adapterConfig: {}, + }); + + expect(res.status, JSON.stringify(res.body)).toBe(201); + expect(mockAgentInstructionsService.materializeManagedBundle).toHaveBeenCalledWith( + expect.objectContaining({ + id: "11111111-1111-4111-8111-111111111111", + role: "engineer", + adapterType: "claude_local", + }), + expect.objectContaining({ + "AGENTS.md": expect.stringContaining("Keep the work moving until it's done."), + }), + { entryFile: "AGENTS.md", replaceExisting: false }, + ); + }); + it("includes canonical desired skills in hire approvals", async () => { const db = createDb(true); diff --git a/server/src/onboarding-assets/default/AGENTS.md b/server/src/onboarding-assets/default/AGENTS.md new file mode 100644 index 00000000..2f84898a --- /dev/null +++ b/server/src/onboarding-assets/default/AGENTS.md @@ -0,0 +1,3 @@ +You are an agent at Paperclip company. + +Keep the work moving until it's done. If you need QA to review it, ask them. If you need your boss to review it, ask them. If someone needs to unblock you, assign them the ticket with a comment asking for what you need. Don't let work just sit here. You must always update your task with a comment. diff --git a/server/src/routes/agents.ts b/server/src/routes/agents.ts index 13d374c6..b568216c 100644 --- a/server/src/routes/agents.ts +++ b/server/src/routes/agents.ts @@ -56,7 +56,10 @@ import { import { DEFAULT_CURSOR_LOCAL_MODEL } from "@paperclipai/adapter-cursor-local"; import { DEFAULT_GEMINI_LOCAL_MODEL } from "@paperclipai/adapter-gemini-local"; import { ensureOpenCodeModelConfiguredAndAvailable } from "@paperclipai/adapter-opencode-local/server"; -import { loadDefaultAgentInstructionsBundle } from "../services/default-agent-instructions.js"; +import { + loadDefaultAgentInstructionsBundle, + resolveDefaultAgentInstructionsBundleRole, +} from "../services/default-agent-instructions.js"; export function agentRoutes(db: Db) { const DEFAULT_INSTRUCTIONS_PATH_KEYS: Record = { @@ -432,8 +435,8 @@ export function agentRoutes(db: Db) { const promptTemplate = typeof adapterConfig.promptTemplate === "string" ? adapterConfig.promptTemplate : ""; - const files = agent.role === "ceo" && promptTemplate.trim().length === 0 - ? await loadDefaultAgentInstructionsBundle("ceo") + const files = promptTemplate.trim().length === 0 + ? await loadDefaultAgentInstructionsBundle(resolveDefaultAgentInstructionsBundleRole(agent.role)) : { "AGENTS.md": promptTemplate }; const materialized = await instructions.materializeManagedBundle( agent, diff --git a/server/src/services/default-agent-instructions.ts b/server/src/services/default-agent-instructions.ts index 68ed2734..4278d833 100644 --- a/server/src/services/default-agent-instructions.ts +++ b/server/src/services/default-agent-instructions.ts @@ -1,6 +1,7 @@ import fs from "node:fs/promises"; const DEFAULT_AGENT_BUNDLE_FILES = { + default: ["AGENTS.md"], ceo: ["AGENTS.md", "HEARTBEAT.md", "SOUL.md", "TOOLS.md"], } as const; @@ -20,3 +21,7 @@ export async function loadDefaultAgentInstructionsBundle(role: DefaultAgentBundl ); return Object.fromEntries(entries); } + +export function resolveDefaultAgentInstructionsBundleRole(role: string): DefaultAgentBundleRole { + return role === "ceo" ? "ceo" : "default"; +}