From 2ca5a25ee5601ca7b01ddc7e6784afe2e65388b7 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Fri, 14 Aug 2026 13:46:29 -0500 Subject: [PATCH] minimize system prompt --- packages/core/src/session/generate-node.ts | 9 +++++++-- packages/core/src/session/model-request.ts | 9 +++++++-- .../core/src/session/runner/prompt/system.txt | 18 ++++++++++++++++++ packages/core/src/session/system-prompt.ts | 12 ++++++++++++ .../core/test/plugin/system-prompt.test.ts | 4 ++-- packages/core/test/session-runner.test.ts | 4 ++-- .../core/test/session-system-prompt.test.ts | 8 ++++++++ 7 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 packages/core/src/session/runner/prompt/system.txt create mode 100644 packages/core/src/session/system-prompt.ts create mode 100644 packages/core/test/session-system-prompt.test.ts diff --git a/packages/core/src/session/generate-node.ts b/packages/core/src/session/generate-node.ts index 2ecf94d44b3..1aa1afd85fd 100644 --- a/packages/core/src/session/generate-node.ts +++ b/packages/core/src/session/generate-node.ts @@ -13,7 +13,7 @@ import { SessionHistory } from "./history.js" import { SessionModelHeaders } from "./model-headers.js" import { SessionPromptCacheKey } from "./prompt-cache-key.js" import { SessionRunnerModel } from "./runner/model.js" -import PROMPT_DEFAULT from "./runner/prompt/base.txt" +import { SessionSystemPrompt } from "./system-prompt.js" import { toLLMMessages } from "./runner/to-llm-message.js" export const layer = Layer.effect( @@ -39,7 +39,12 @@ export const layer = Layer.effect( sessionID: selection.session.id, agent: selection.agent.id, model: model.ref, - system: [selection.agent.info.system ? selection.agent.info.system : PROMPT_DEFAULT, history.initial] + system: [ + selection.agent.info.system + ? selection.agent.info.system + : SessionSystemPrompt.make(toolDefinitions.map((tool) => tool.name)), + history.initial, + ] .filter((part) => part.length > 0) .map(SystemPart.make), messages: [ diff --git a/packages/core/src/session/model-request.ts b/packages/core/src/session/model-request.ts index 86eee2a6507..955e3103035 100644 --- a/packages/core/src/session/model-request.ts +++ b/packages/core/src/session/model-request.ts @@ -18,7 +18,7 @@ import { SessionModelHttp } from "./model-http.js" import { SessionPromptCacheKey } from "./prompt-cache-key.js" import { PromptCacheDiagnostics } from "./prompt-cache-diagnostics.js" import { MAX_STEPS_PROMPT } from "./runner/max-steps.js" -import PROMPT_DEFAULT from "./runner/prompt/base.txt" +import { SessionSystemPrompt } from "./system-prompt.js" import { toLLMMessages } from "./runner/to-llm-message.js" const IMAGE_BYTES_TRIGGER = 25 * 1024 * 1024 // 25 MiB @@ -182,7 +182,12 @@ export const layer = Layer.effect( // The final Step keeps definitions available to protocols with native "none", // preserving their prompt cache prefix. Calls are still rejected at execution. const tools = input.context.tools - const system = [agent.info.system ? agent.info.system : PROMPT_DEFAULT, input.context.initial] + const system = [ + agent.info.system + ? agent.info.system + : SessionSystemPrompt.make(tools.definitions.map((tool) => tool.name)), + input.context.initial, + ] .filter((part) => part.length > 0) .map(SystemPart.make) const history = toLLMMessages(input.context.messages, resolved.ref, providerMetadataKey) diff --git a/packages/core/src/session/runner/prompt/system.txt b/packages/core/src/session/runner/prompt/system.txt new file mode 100644 index 00000000000..9a64aa04f68 --- /dev/null +++ b/packages/core/src/session/runner/prompt/system.txt @@ -0,0 +1,18 @@ +You are an AI agent powered by OpenCode, a coding agent harness. Help the user accomplish their goals using the available tools. + +# Harness +- Responses are rendered as GitHub-flavored Markdown. +- Do not use shell commands to communicate thoughts, explanations, or instructions. Communicate directly in your response instead. +- Prefer using the read tool rather than shell commands like `cat`. +- `` blocks are harness instructions, not user-authored content. Read and follow them. +${OPENCODE_TOOL_INSTRUCTIONS} + +# Communication +- Use clear file paths when referring to files. +- Keep responses clear and concise, and avoid unnecessary technical jargon. + +# Working in codebases +- Keep changes consistent with the structure, naming, style, and patterns of the surrounding code. +- Treat unfamiliar files or changes as potential user work and investigate before deleting or overwriting them. + +${OPENCODE_INSTRUCTIONS} diff --git a/packages/core/src/session/system-prompt.ts b/packages/core/src/session/system-prompt.ts new file mode 100644 index 00000000000..451e1b6d269 --- /dev/null +++ b/packages/core/src/session/system-prompt.ts @@ -0,0 +1,12 @@ +export * as SessionSystemPrompt from "./system-prompt.js" + +import PROMPT from "./runner/prompt/system.txt" + +const TOOL_INSTRUCTIONS = new Map() +const OPENCODE_INSTRUCTIONS = "" + +export function make(tools: string[]) { + return PROMPT.replace("${OPENCODE_TOOL_INSTRUCTIONS}", () => + tools.flatMap((tool) => TOOL_INSTRUCTIONS.get(tool) ?? []).join("\n\n"), + ).replace("${OPENCODE_INSTRUCTIONS}", () => OPENCODE_INSTRUCTIONS) +} diff --git a/packages/core/test/plugin/system-prompt.test.ts b/packages/core/test/plugin/system-prompt.test.ts index c3246752919..aa98b6196fa 100644 --- a/packages/core/test/plugin/system-prompt.test.ts +++ b/packages/core/test/plugin/system-prompt.test.ts @@ -7,6 +7,7 @@ import { PluginHooks } from "@opencode-ai/core/plugin/hooks" import { PluginHost } from "@opencode-ai/core/plugin/host" import { SystemPromptPlugin } from "@opencode-ai/core/plugin/system-prompt" import { Session } from "@opencode-ai/core/session" +import { SessionSystemPrompt } from "@opencode-ai/core/session/system-prompt" import type { SessionHooks } from "@opencode-ai/plugin/effect/session" import { Model } from "@opencode-ai/schema/model" import { Provider } from "@opencode-ai/schema/provider" @@ -14,10 +15,9 @@ import { Effect } from "effect" import { testEffect } from "../lib/effect" import { PluginTestLayer } from "./fixture" import PROMPT_META from "../../src/plugin/system-prompt/meta.txt" -import PROMPT_DEFAULT from "../../src/session/runner/prompt/base.txt" const it = testEffect(PluginTestLayer) -const fallback = PROMPT_DEFAULT +const fallback = SessionSystemPrompt.make([]) const makeHost = Effect.gen(function* () { const agents = yield* Agent.Service const plugins = yield* Plugin.Service diff --git a/packages/core/test/session-runner.test.ts b/packages/core/test/session-runner.test.ts index e1cf377af0e..977e883cd2c 100644 --- a/packages/core/test/session-runner.test.ts +++ b/packages/core/test/session-runner.test.ts @@ -67,6 +67,7 @@ import { InstructionDiscovery } from "@opencode-ai/core/instruction-discovery" import { SkillInstructions } from "@opencode-ai/core/skill/instructions" import { ReferenceInstructions } from "@opencode-ai/core/reference/instructions" import { McpInstructions } from "@opencode-ai/core/mcp/instructions" +import { SessionSystemPrompt } from "@opencode-ai/core/session/system-prompt" import { ID } from "@opencode-ai/core/model" import { Location } from "@opencode-ai/core/location" import { Provider } from "@opencode-ai/core/provider" @@ -76,7 +77,6 @@ import { asc, desc, eq } from "drizzle-orm" import { testEffect } from "./lib/effect" import { permissionLayer } from "./lib/permission" import { agentHost, catalogHost, host } from "./plugin/host" -import PROMPT_DEFAULT from "../src/session/runner/prompt/base.txt" import { CodeModeInstructions } from "@opencode-ai/core/codemode/instructions" let requests: LLMRequest[] = [] @@ -133,7 +133,7 @@ const testLLM = TestLLM.layer({ }) const client = TestLLM.clientLayer const model = LanguageModel.make({ id: "fake-model", provider: "fake", route: OpenAIChat.route }) -const defaultSystem = PROMPT_DEFAULT +const defaultSystem = SessionSystemPrompt.make([]) const replacementModel = LanguageModel.make({ id: "replacement", provider: "fake", route: OpenAIChat.route }) const compactModel = LanguageModel.make({ id: "compact", diff --git a/packages/core/test/session-system-prompt.test.ts b/packages/core/test/session-system-prompt.test.ts new file mode 100644 index 00000000000..dc875131400 --- /dev/null +++ b/packages/core/test/session-system-prompt.test.ts @@ -0,0 +1,8 @@ +import { expect, test } from "bun:test" +import { SessionSystemPrompt } from "@opencode-ai/core/session/system-prompt" + +test("renders the default system prompt instructions", () => { + const prompt = SessionSystemPrompt.make(["read", "shell"]) + expect(prompt).not.toContain("${OPENCODE_TOOL_INSTRUCTIONS}") + expect(prompt).not.toContain("${OPENCODE_INSTRUCTIONS}") +})