From 7817e9b227fe58f9605da356ede9c9a5309e978a Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 17 Mar 2026 12:44:16 +0100 Subject: [PATCH] fix(coding-agent): make prompt snippets opt in closes #2285 --- packages/coding-agent/CHANGELOG.md | 4 ++ packages/coding-agent/docs/extensions.md | 4 +- .../coding-agent/src/core/extensions/types.ts | 2 +- .../coding-agent/src/core/system-prompt.ts | 5 +- .../test/agent-session-dynamic-tools.test.ts | 46 +++++++++++++++++++ .../coding-agent/test/system-prompt.test.ts | 12 ++++- 6 files changed, 67 insertions(+), 6 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 1e9351f9..3f9d2c8f 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Breaking Changes + +- Changed custom tool system prompt behavior so extension and SDK tools are included in the default `Available tools` section only when they provide `promptSnippet`. Omitting `promptSnippet` now leaves the tool out of that section instead of falling back to `description` ([#2285](https://github.com/badlogic/pi-mono/issues/2285)) + ## [0.58.4] - 2026-03-16 ### Fixed diff --git a/packages/coding-agent/docs/extensions.md b/packages/coding-agent/docs/extensions.md index 8bf7a526..62327427 100644 --- a/packages/coding-agent/docs/extensions.md +++ b/packages/coding-agent/docs/extensions.md @@ -934,7 +934,7 @@ Register a custom tool callable by the LLM. See [Custom Tools](#custom-tools) fo Use `pi.setActiveTools()` to enable or disable tools (including dynamically added tools) at runtime. -Use `promptSnippet` to customize that tool's one-line entry in `Available tools`, and `promptGuidelines` to append tool-specific bullets to the default `Guidelines` section when the tool is active. +Use `promptSnippet` to opt a custom tool into a one-line entry in `Available tools`, and `promptGuidelines` to append tool-specific bullets to the default `Guidelines` section when the tool is active. See [dynamic-tools.ts](../examples/extensions/dynamic-tools.ts) for a full example. @@ -1336,7 +1336,7 @@ export default function (pi: ExtensionAPI) { Register tools the LLM can call via `pi.registerTool()`. Tools appear in the system prompt and can have custom rendering. -Use `promptSnippet` for a short one-line entry in the `Available tools` section in the default system prompt. If omitted, pi falls back to `description`. +Use `promptSnippet` for a short one-line entry in the `Available tools` section in the default system prompt. If omitted, custom tools are left out of that section. Use `promptGuidelines` to add tool-specific bullets to the default system prompt `Guidelines` section. These bullets are included only while the tool is active (for example, after `pi.setActiveTools([...])`). diff --git a/packages/coding-agent/src/core/extensions/types.ts b/packages/coding-agent/src/core/extensions/types.ts index 69ddb323..76960667 100644 --- a/packages/coding-agent/src/core/extensions/types.ts +++ b/packages/coding-agent/src/core/extensions/types.ts @@ -339,7 +339,7 @@ export interface ToolDefinition name in toolDescriptions || toolSnippets?.[name]); const toolsList = - tools.length > 0 - ? tools + visibleTools.length > 0 + ? visibleTools .map((name) => { const snippet = toolSnippets?.[name] ?? toolDescriptions[name] ?? name; return `- ${name}: ${snippet}`; diff --git a/packages/coding-agent/test/agent-session-dynamic-tools.test.ts b/packages/coding-agent/test/agent-session-dynamic-tools.test.ts index 0127bad1..766dcd6d 100644 --- a/packages/coding-agent/test/agent-session-dynamic-tools.test.ts +++ b/packages/coding-agent/test/agent-session-dynamic-tools.test.ts @@ -74,4 +74,50 @@ describe("AgentSession dynamic tool registration", () => { session.dispose(); }); + + it("keeps custom tools active but omits them from available tools when promptSnippet is not provided", async () => { + const settingsManager = SettingsManager.create(tempDir, agentDir); + const sessionManager = SessionManager.inMemory(); + + const resourceLoader = new DefaultResourceLoader({ + cwd: tempDir, + agentDir, + settingsManager, + extensionFactories: [ + (pi) => { + pi.on("session_start", () => { + pi.registerTool({ + name: "hidden_tool", + label: "Hidden Tool", + description: "Description should not appear in available tools", + parameters: Type.Object({}), + execute: async () => ({ + content: [{ type: "text", text: "ok" }], + details: {}, + }), + }); + }); + }, + ], + }); + await resourceLoader.reload(); + + const { session } = await createAgentSession({ + cwd: tempDir, + agentDir, + model: getModel("anthropic", "claude-sonnet-4-5")!, + settingsManager, + sessionManager, + resourceLoader, + }); + + await session.bindExtensions({}); + + expect(session.getAllTools().map((tool) => tool.name)).toContain("hidden_tool"); + expect(session.getActiveToolNames()).toContain("hidden_tool"); + expect(session.systemPrompt).not.toContain("hidden_tool"); + expect(session.systemPrompt).not.toContain("Description should not appear in available tools"); + + session.dispose(); + }); }); diff --git a/packages/coding-agent/test/system-prompt.test.ts b/packages/coding-agent/test/system-prompt.test.ts index db266296..65b0e655 100644 --- a/packages/coding-agent/test/system-prompt.test.ts +++ b/packages/coding-agent/test/system-prompt.test.ts @@ -39,7 +39,7 @@ describe("buildSystemPrompt", () => { }); describe("custom tool snippets", () => { - test("includes custom tools in available tools section", () => { + test("includes custom tools in available tools section when promptSnippet is provided", () => { const prompt = buildSystemPrompt({ selectedTools: ["read", "dynamic_tool"], toolSnippets: { @@ -51,6 +51,16 @@ describe("buildSystemPrompt", () => { expect(prompt).toContain("- dynamic_tool: Run dynamic test behavior"); }); + + test("omits custom tools from available tools section when promptSnippet is not provided", () => { + const prompt = buildSystemPrompt({ + selectedTools: ["read", "dynamic_tool"], + contextFiles: [], + skills: [], + }); + + expect(prompt).not.toContain("dynamic_tool"); + }); }); describe("prompt guidelines", () => {