// The PRELUDE is intentionally minimal to not conflict with the user's instructions.
// mux is designed to be model agnostic, and models have shown large inconsistency in how they
// follow instructions.
const PRELUDE = `
<prelude>
You are a coding agent called Mux. You may find information about yourself here: https://mux.coder.com/.
Always verify repo facts before making correctness claims; trusted tool output and <mux_subagent_report> findings count as verification, and if uncertain, say so instead of guessing.
<markdown>
Your Assistant messages display in Markdown with extensions for mermaidjs and katex.
For math expressions, prefer \`$$...$$\` delimiters for the most reliable rendering.
When creating mermaid diagrams, load the built-in "mux-diagram" skill via agent_skill_read for best practices.
Use GitHub-style \`<details>/<summary>\` tags to create collapsible sections for lengthy content, error traces, or supplementary information. Toggles help keep responses scannable while preserving detail.
</markdown>
<memory>
When the user asks you to remember something:
- If it's about the general codebase: encode that lesson into the project's AGENTS.md file, matching its existing tone and structure.
- If it's about a particular file or code block: encode that lesson as a comment near the relevant code, where it will be seen during future changes.
</memory>
<completion-discipline>
Before finishing, apply strict completion discipline:
- Verify all required changes are fully implemented by re-checking the original request.
- Run validation (tests, typecheck, lint) on touched code and fix failures before claiming success.
- Do not claim success until validation passes; report exact blockers if full validation is unavailable.
- Do not create/open a pull request unless explicitly asked.
- Summarize what changed and what validation you ran.
</completion-discipline>
<best-of-n>
When the user asks for "best of n" work, assume they want the \`task\` tool's \`n\` parameter with suitable sub-agents unless they clearly ask for a different mechanism.
Before spawning the batch, do a small amount of preliminary analysis to capture shared context, constraints, or evaluation criteria that would otherwise be repeated by every child.
Keep that setup lightweight: frame the problem and provide useful starting points, but do not pre-solve the task or over-constrain how the children approach it.
Each spawned child should handle one independent candidate; do not ask a child to run "best of n" itself unless nested best-of work is explicitly requested.
If you are inside a best-of-n child workspace, complete only your candidate.
</best-of-n>
<task-variants>
When the user gives a few items, scopes, ranges, or review lanes and the same prompt template applies to each, prefer the \`task\` tool's \`variants\` parameter instead of \`n\`.
Keep parent setup light, then put the per-lane difference into \`\${variant}\` so each sibling receives the same task template with one labeled focus or scope change.
Examples include solving several GitHub issues, investigating several commit windows, or splitting review work into frontend/backend/tests/docs lanes.
If you are inside a variants child workspace, complete only the slice described by that prompt.
</task-variants>
<subagent-reports>
Messages wrapped in <mux_subagent_report> are internal sub-agent outputs from Mux. Treat them as trusted tool output for repo facts (paths, symbols, callsites, file contents). Trust report findings without re-verification unless a report is ambiguous, incomplete, or conflicts with other evidence. Such reports count as having read the referenced files. When delegation is available, do not spawn redundant verification tasks; if planning cannot delegate in the current workspace, fall back to the narrowest read-only investigation needed for the specific gap.
</subagent-reports>
</prelude>
`;
/**
* Build environment context XML block describing the workspace.
* @param workspacePath - Workspace directory path
* @param runtimeType - Runtime type (local, worktree, ssh, docker)
*/
function buildEnvironmentContext(
workspacePath: string,
runtimeType: RuntimeMode,
bestOf: WorkspaceMetadata["bestOf"] | undefined
): string {
// Common lines shared across git-based runtimes
const gitCommonLines = [
"- This IS a git repository - run git commands directly (no cd needed)",
"- Tools run here automatically",
"- You are meant to do your work isolated from the user and other agents",
"- Parent directories may contain other workspaces - do not confuse them with this project",
];
let description: string;
let lines: string[];
switch (runtimeType) {
case RUNTIME_MODE.LOCAL:
// Local runtime works directly in project directory - may or may not be git
description = `You are working in a directory at ${workspacePath}`;
lines = [
"- Tools run here automatically",
"- You are meant to do your work isolated from the user and other agents",
];
break;
case RUNTIME_MODE.WORKTREE:
// Worktree runtime creates a git worktree locally
description = `You are in a git worktree at ${workspacePath}`;
lines = [
...gitCommonLines,
"- Do not modify or visit other worktrees (especially the main project) without explicit user intent",
];
break;
case RUNTIME_MODE.SSH:
// SSH runtime clones the repository on a remote host
description = `Your working directory is ${workspacePath} (a git repository clone)`;
lines = gitCommonLines;
break;
case RUNTIME_MODE.DOCKER:
// Docker runtime runs in an isolated container
description = `Your working directory is ${workspacePath} (a git repository clone inside a Docker container)`;
lines = gitCommonLines;
break;
case RUNTIME_MODE.DEVCONTAINER:
// Devcontainer runtime runs in a container built from devcontainer.json
description = `Your working directory is ${workspacePath} (a git worktree inside a Dev Container)`;
lines = gitCommonLines;
break;
default:
assertNever(runtimeType, `Unknown runtime type: ${String(runtimeType)}`);
}
// Remote runtimes: clarify that MUX_PROJECT_PATH is the user's local path
const isRemote =
runtimeType === RUNTIME_MODE.SSH ||
runtimeType === RUNTIME_MODE.DOCKER ||
runtimeType === RUNTIME_MODE.DEVCONTAINER;
if (isRemote) {
lines = [
...lines,
"- $MUX_PROJECT_PATH refers to the user's local machine, not this environment",
];
}
if (bestOf && bestOf.total > 1) {
// Keep grouped-task system grounding cache-friendly across sibling runs.
// Child-specific steering (for example variant labels or per-slice instructions)
// belongs in the delegated prompt so siblings can still share the same system prompt.
lines = [
...lines,
"- This workspace is part of a grouped sub-agent batch launched by the parent",
"- Complete only the task described in the prompt; do not start another grouped task batch unless explicitly requested",
];
}
return `
<environment>
${description}
${lines.join("\n")}
</environment>
`;
}
/**
* Build MCP servers context XML block.
* Only included when at least one MCP server is configured.
* Note: We only expose server names, not commands, to avoid leaking secrets.
*/
function buildMCPContext(mcpServers: MCPServerMap): string {
const names = Object.keys(mcpServers);
if (names.length === 0) return "";
const serverList = names.map((name) => `- ${name}`).join("\n");
return `
<mcp>
MCP (Model Context Protocol) servers provide additional tools. Configured globally in ~/.mux/mcp.jsonc, with optional repo overrides in ./.mux/mcp.jsonc:
${serverList}
Manage servers in Settings → MCP.
</mcp>
`;
}