From a51758399af5be208cbf68dc9d0eb539ea549865 Mon Sep 17 00:00:00 2001 From: HiranoMasaaki Date: Sun, 15 Feb 2026 15:00:27 +0000 Subject: [PATCH 1/3] refactor: simplify meta instruction and remove duplicate delegate description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce token waste and attention dilution by trimming redundant meta instruction (~30 lines → ~6 lines) and removing getDelegateRules which duplicated delegate.description already provided via tool definitions in DelegateSkillManager. Co-Authored-By: Claude Opus 4.6 --- .../src/messages/instruction-message.ts | 59 ++----------------- packages/runtime/src/messages/message.test.ts | 56 ++---------------- .../runtime/src/state-machine/states/init.ts | 2 +- 3 files changed, 11 insertions(+), 106 deletions(-) diff --git a/packages/runtime/src/messages/instruction-message.ts b/packages/runtime/src/messages/instruction-message.ts index 1374a20a..f54f5406 100644 --- a/packages/runtime/src/messages/instruction-message.ts +++ b/packages/runtime/src/messages/instruction-message.ts @@ -4,65 +4,32 @@ import { dedent } from "ts-dedent" function getMetaInstruction(startedAt: number): string { return dedent` - IMPORTANT: - Based on the user's initial message, you must determine what needs to be done. - You must iterate through hypothesis and verification to fulfill the task. - YOU MUST CONTINUE TO CALL TOOLS UNTIL THE TASK IS COMPLETE. - If you do not call tools, the task will be considered complete, and the agent loop will end. + Call tools iteratively to complete the user's task. + When the task is complete, or when you cannot help, call attemptCompletion. + Call attemptCompletion ONLY as a tool call — do not include any text response with it. - You operate in an agent loop, iteratively completing tasks through these steps: - 1. Analyze Events: Understand user needs and current state through the event stream, focusing on the latest user messages and execution results - 2. Select Tools: Choose the next tool call based on current state, task planning, relevant knowledge, and available data APIs - 3. Wait for Execution: The selected tool action will be executed by the sandbox environment with new observations added to the event stream - 4. Iterate: Choose only one tool call per iteration, patiently repeat the above steps until task completion - 5. Notify Task Completion: Call attemptCompletion ONLY - do NOT include any text response with this tool call - 6. Generate Final Results: AFTER attemptCompletion returns, you will be prompted to produce a final result in a SEPARATE response - - Conditions for ending the agent loop: - If any of the following apply, **immediately call the attemptCompletion tool**. - When the agent loop must end, calling any tool other than attemptCompletion is highly dangerous. - Under all circumstances, strictly follow this rule. - - When the task is complete - - When the user's request is outside your expertise - - When the user's request is unintelligible - - Rules for requests outside your area of expertise: - - Tell your area of expertise to the user in final results - - Environment information: - - Current time is ${new Date(startedAt).toISOString()} - - Current working directory is ${process.cwd()} + Environment: + - Current time: ${new Date(startedAt).toISOString()} + - Working directory: ${process.cwd()} ` } export function createInstructionMessage( expert: Expert, - experts: Record, startedAt: number, ): InstructionMessage { const instruction = dedent` You are Perstack, an AI expert that tackles tasks requested by users by utilizing all available tools. - (The following information describes your nature and role as an AI, the mechanisms of the AI system, and other meta-cognitive aspects.) - ${getMetaInstruction(startedAt)} --- - (The following describes the objective, steps, rules, etc. regarding your expert task.) ${expert.instruction} --- - (The following is an overview of each skill and the rules for calling tools.) ${getSkillRules(expert)} - - --- - (The following is an overview of each delegate expert and the rules for calling tools.) - - You can delegate tasks to the following experts by calling delegate expert name as a tool: - - ${getDelegateRules(expert, experts)} ` return { type: "instructionMessage", @@ -92,17 +59,3 @@ function getSkillRules(expert: Expert): string { }, "" as string) } -function getDelegateRules(expert: Expert, experts: Record): string { - return expert.delegates.reduce((acc, delegateExpertName) => { - const delegate = experts[delegateExpertName] - if (!delegate) { - return acc - } - return dedent` - ${acc} - - About "${delegate.name}": - ${delegate.description} - `.trim() - }, "" as string) -} diff --git a/packages/runtime/src/messages/message.test.ts b/packages/runtime/src/messages/message.test.ts index 54b8d4ca..97042f9d 100644 --- a/packages/runtime/src/messages/message.test.ts +++ b/packages/runtime/src/messages/message.test.ts @@ -514,7 +514,7 @@ describe("@perstack/messages: instruction-message", () => { runtime: ["local" as const], minRuntimeVersion: "v1.0" as const, } - const result = createInstructionMessage(expert, {}, startedAt) + const result = createInstructionMessage(expert, startedAt) expect(result.type).toBe("instructionMessage") expect(result.cache).toBe(true) expect(result.contents[0].type).toBe("textPart") @@ -545,7 +545,7 @@ describe("@perstack/messages: instruction-message", () => { runtime: ["local" as const], minRuntimeVersion: "v1.0" as const, } - const result = createInstructionMessage(expert, {}, startedAt) + const result = createInstructionMessage(expert, startedAt) expect(result.contents[0].text).toContain("Always use this skill carefully.") expect(result.contents[0].text).toContain('"test-skill" skill rules:') }) @@ -573,58 +573,10 @@ describe("@perstack/messages: instruction-message", () => { runtime: ["local" as const], minRuntimeVersion: "v1.0" as const, } - const result = createInstructionMessage(expert, {}, startedAt) + const result = createInstructionMessage(expert, startedAt) expect(result.contents[0].text).not.toContain('"test-skill" skill rules:') }) - it("includes delegate rules when delegate exists", () => { - const expert = { - key: "test-expert", - name: "Test Expert", - version: "1.0.0", - instruction: "Test instruction", - skills: {}, - delegates: ["delegate-expert"], - tags: [], - runtime: ["local" as const], - minRuntimeVersion: "v1.0" as const, - } - const experts = { - "test-expert": expert, - "delegate-expert": { - key: "delegate-expert", - name: "Delegate Expert", - version: "1.0.0", - description: "A delegate expert for testing", - instruction: "Delegate instruction", - skills: {}, - delegates: [], - tags: [], - runtime: ["local" as const], - minRuntimeVersion: "v1.0" as const, - }, - } - const result = createInstructionMessage(expert, experts, startedAt) - expect(result.contents[0].text).toContain('About "Delegate Expert":') - expect(result.contents[0].text).toContain("A delegate expert for testing") - }) - - it("skips delegate rules when delegate not found", () => { - const expert = { - key: "test-expert", - name: "Test Expert", - version: "1.0.0", - instruction: "Test instruction", - skills: {}, - delegates: ["nonexistent-delegate"], - tags: [], - runtime: ["local" as const], - minRuntimeVersion: "v1.0" as const, - } - const result = createInstructionMessage(expert, {}, startedAt) - expect(result.contents[0].text).not.toContain('About "') - }) - it("uses startedAt for timestamp in instruction", () => { const expert = { key: "test-expert", @@ -637,7 +589,7 @@ describe("@perstack/messages: instruction-message", () => { runtime: ["local" as const], minRuntimeVersion: "v1.0" as const, } - const result = createInstructionMessage(expert, {}, startedAt) + const result = createInstructionMessage(expert, startedAt) expect(result.contents[0].text).toContain("2023-11-14T22:13:20.000Z") }) }) diff --git a/packages/runtime/src/state-machine/states/init.ts b/packages/runtime/src/state-machine/states/init.ts index cab68f2b..8500bd5b 100644 --- a/packages/runtime/src/state-machine/states/init.ts +++ b/packages/runtime/src/state-machine/states/init.ts @@ -31,7 +31,7 @@ export async function initLogic({ return startRun(setting, checkpoint, { initialCheckpoint: checkpoint, inputMessages: [ - createInstructionMessage(expert, experts, setting.startedAt), + createInstructionMessage(expert, setting.startedAt), createUserMessage([{ type: "textPart", text: setting.input.text }]), ], }) From 7c79c674962bc186fb296708c93735cd8b1ff7ce Mon Sep 17 00:00:00 2001 From: HiranoMasaaki Date: Sun, 15 Feb 2026 15:02:40 +0000 Subject: [PATCH 2/3] chore: add changeset for runtime patch Co-Authored-By: Claude Opus 4.6 --- .changeset/simplify-meta-instruction.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/simplify-meta-instruction.md diff --git a/.changeset/simplify-meta-instruction.md b/.changeset/simplify-meta-instruction.md new file mode 100644 index 00000000..08b75178 --- /dev/null +++ b/.changeset/simplify-meta-instruction.md @@ -0,0 +1,5 @@ +--- +"@perstack/runtime": patch +--- + +Simplify meta instruction and remove duplicate delegate description from system prompt From 3d429a64733d90fe0951651410ddb1f43ef88303 Mon Sep 17 00:00:00 2001 From: HiranoMasaaki Date: Sun, 15 Feb 2026 15:03:40 +0000 Subject: [PATCH 3/3] chore: fix formatting Co-Authored-By: Claude Opus 4.6 --- packages/runtime/src/messages/instruction-message.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/runtime/src/messages/instruction-message.ts b/packages/runtime/src/messages/instruction-message.ts index f54f5406..999a9d3d 100644 --- a/packages/runtime/src/messages/instruction-message.ts +++ b/packages/runtime/src/messages/instruction-message.ts @@ -14,10 +14,7 @@ function getMetaInstruction(startedAt: number): string { ` } -export function createInstructionMessage( - expert: Expert, - startedAt: number, -): InstructionMessage { +export function createInstructionMessage(expert: Expert, startedAt: number): InstructionMessage { const instruction = dedent` You are Perstack, an AI expert that tackles tasks requested by users by utilizing all available tools. @@ -58,4 +55,3 @@ function getSkillRules(expert: Expert): string { `.trim() }, "" as string) } -