Add default agent instructions bundle

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
dotta 2026-03-20 07:42:36 -05:00
parent 0f45999df9
commit d6bb71f324
4 changed files with 38 additions and 3 deletions

View file

@ -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 () => { it("includes canonical desired skills in hire approvals", async () => {
const db = createDb(true); const db = createDb(true);

View file

@ -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.

View file

@ -56,7 +56,10 @@ import {
import { DEFAULT_CURSOR_LOCAL_MODEL } from "@paperclipai/adapter-cursor-local"; import { DEFAULT_CURSOR_LOCAL_MODEL } from "@paperclipai/adapter-cursor-local";
import { DEFAULT_GEMINI_LOCAL_MODEL } from "@paperclipai/adapter-gemini-local"; import { DEFAULT_GEMINI_LOCAL_MODEL } from "@paperclipai/adapter-gemini-local";
import { ensureOpenCodeModelConfiguredAndAvailable } from "@paperclipai/adapter-opencode-local/server"; 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) { export function agentRoutes(db: Db) {
const DEFAULT_INSTRUCTIONS_PATH_KEYS: Record<string, string> = { const DEFAULT_INSTRUCTIONS_PATH_KEYS: Record<string, string> = {
@ -432,8 +435,8 @@ export function agentRoutes(db: Db) {
const promptTemplate = typeof adapterConfig.promptTemplate === "string" const promptTemplate = typeof adapterConfig.promptTemplate === "string"
? adapterConfig.promptTemplate ? adapterConfig.promptTemplate
: ""; : "";
const files = agent.role === "ceo" && promptTemplate.trim().length === 0 const files = promptTemplate.trim().length === 0
? await loadDefaultAgentInstructionsBundle("ceo") ? await loadDefaultAgentInstructionsBundle(resolveDefaultAgentInstructionsBundleRole(agent.role))
: { "AGENTS.md": promptTemplate }; : { "AGENTS.md": promptTemplate };
const materialized = await instructions.materializeManagedBundle( const materialized = await instructions.materializeManagedBundle(
agent, agent,

View file

@ -1,6 +1,7 @@
import fs from "node:fs/promises"; import fs from "node:fs/promises";
const DEFAULT_AGENT_BUNDLE_FILES = { const DEFAULT_AGENT_BUNDLE_FILES = {
default: ["AGENTS.md"],
ceo: ["AGENTS.md", "HEARTBEAT.md", "SOUL.md", "TOOLS.md"], ceo: ["AGENTS.md", "HEARTBEAT.md", "SOUL.md", "TOOLS.md"],
} as const; } as const;
@ -20,3 +21,7 @@ export async function loadDefaultAgentInstructionsBundle(role: DefaultAgentBundl
); );
return Object.fromEntries(entries); return Object.fromEntries(entries);
} }
export function resolveDefaultAgentInstructionsBundleRole(role: string): DefaultAgentBundleRole {
return role === "ceo" ? "ceo" : "default";
}