Skip to content

System Prompt Construction

源码版本v0.73.1

system-prompt.ts is the assembly workshop for pi's default system prompt. One file, one buildSystemPrompt function, turning the tool list, guidelines, pi doc paths, project context files, skills, date, and cwd into the final prompt string. createAgentSession doesn't call it directly — AgentSession rebuilds it before each prompt based on the currently active tools, so the prompt stays in sync when tools are added or removed.

Responsibilities

  1. Assemble the default prompt: when buildSystemPrompt has no customPrompt, it takes the default path and produces the full prompt starting with "You are an expert coding assistant operating inside pi". See packages/coding-agent/src/core/system-prompt.ts:28-80 and packages/coding-agent/src/core/system-prompt.ts:131-171.
  2. Custom prompt path: when customPrompt is provided, the default template is skipped and only contextFiles, skills, date, and cwd are appended. See packages/coding-agent/src/core/system-prompt.ts:53-80.
  3. Tool list and guidelines: selectedTools decides which tools are visible, and guidelines are generated dynamically based on the tool combination (e.g., when bash+grep are both present, prefer grep). See packages/coding-agent/src/core/system-prompt.ts:89-129.
  4. Prompt snippet injection: each tool's promptSnippet is a one-line description, concatenated into the "Available tools" list, so the LLM can judge what each tool is for. See packages/coding-agent/src/core/system-prompt.ts:89-92.
  5. Skill attachment: formatSkillsForPrompt turns visible skills (non-disableModelInvocation) into an <available_skills> XML block. See packages/coding-agent/src/core/system-prompt.ts:162-165.
  6. Doc self-pointers: the prompt includes pi's own doc paths (readme, docs, examples) and tells the LLM to read them when the user asks about pi. See packages/coding-agent/src/core/system-prompt.ts:141-147.

Design Motivation

Why not have AgentSession hold the prompt string directly? Because the toolset is dynamic — users can add or remove tools mid-session via /tools, and extensions can register new tools. If the prompt were a static string, the LLM would keep calling disabled tools per the old prompt after a tool change. buildSystemPrompt regenerates on every call, keeping the prompt strictly aligned with the currently active toolset.

Why distinguish the default prompt from the custom prompt path? The default is pi's officially tuned version, including the tool list, guidelines, and doc self-pointers. A custom prompt is fully user- or extension-provided and only wants contextFiles and skills appended. Both paths share the append logic for contextFiles, skills, date, and cwd, but the default path also assembles the toolsList and guidelines.

The dynamic guidelines are worth noting: if bash and grep/find/ls are all enabled, the prompt suggests "Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)"; if bash is present but grep/find/ls are not, it suggests "Use bash for file operations like ls, rg, find". This lets the LLM pick an efficient path under any tool combination.

Key Files

Dynamic guidelines, deduped via a Set:

typescript
// packages/coding-agent/src/core/system-prompt.ts:105-129
const hasBash = tools.includes("bash");
const hasGrep = tools.includes("grep");
const hasFind = tools.includes("find");
const hasLs = tools.includes("ls");

if (hasBash && !hasGrep && !hasFind && !hasLs) {
	addGuideline("Use bash for file operations like ls, rg, find");
} else if (hasBash && (hasGrep || hasFind || hasLs)) {
	addGuideline("Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)");
}

for (const guideline of promptGuidelines ?? []) {
	const normalized = guideline.trim();
	if (normalized.length > 0) {
		addGuideline(normalized);
	}
}

// Always include these
addGuideline("Be concise in your responses");
addGuideline("Show file paths clearly when working with files");

Date and cwd are appended at the end of the default prompt, deliberately placed last so the LLM notices them:

typescript
// packages/coding-agent/src/core/system-prompt.ts:167-171
if (hasRead && skills.length > 0) {
	prompt += formatSkillsForPrompt(skills);
}

// Add date and working directory last
prompt += `\nCurrent date: ${date}`;
prompt += `\nCurrent working directory: ${promptCwd}`;

return prompt;

Data Flow

Prompt construction flow:

Edges and Failures

Summary

buildSystemPrompt is the prompt assembly workshop: it generates guidelines dynamically based on the current toolset, and the custom and default paths share the append logic for contextFiles/skills/date/cwd. For skill loading and formatting, see Skill System; for message conversion, see Message Types and convertToLlm; for the toolset itself, see Tools: read/bash/edit/write/grep/find/ls.