# Prompt construction
[Feature docs index](README.md) · [Repository README](../../README.md)
## Purpose
Explain how `magi-code` builds provider-visible prompt context: static templates, runtime facts, `AGENTS.md` files, tools, skills, subagents, provider request mapping, and customization points.
## Prompt assembly
`AgentSession::new_with_prompt_dir_and_subagents` builds one assistant system prompt before each agent session starts. `src/agent/prompt.rs` renders sections in this order:
1. `prompts/system.md`
2. `prompts/tools.md`
3. `prompts/codemode.md`, only when `code_mode` is enabled (`capabilities.tools.code_mode.enabled`) and not disabled
4. optional generated subagent identity section
5. `prompts/skills.md`
6. generated dynamic `AGENTS.md` context files
Empty sections are skipped. Non-empty sections are joined with one blank line and the final prompt ends with `\n`.
Prompt structure:
```xml
<SYSTEM>
Core magi-code behavior rules.
</SYSTEM>
<USER-SYSTEM>
- operating system
- terminal indicators
</USER-SYSTEM>
<Tools>
General tool-use guidance; provider-native tool definitions are supplied separately.
</Tools>
<Subagent-Identities>
Optional identity metadata when configured.
</Subagent-Identities>
<Available-Skills>
- skill-name: frontmatter description
</Available-Skills>
<Additional-Context-Files>
These files are automatically injected and MUST ALWAYS be remembered and considered in every action, do NOT read these files again:
<Context File=/Users/example/.magi-code/AGENTS.md>
raw user instruction file
</Context>
<Context File=/repo/AGENTS.md>
raw repo instruction file
</Context>
</Additional-Context-Files>
```
## Template fragments
Bundled defaults live in `prompts/`. User overrides live in `$MC_HOME/prompts/` or `~/.magi-code/prompts/` and are selected per fragment; missing overrides fall back independently to bundled defaults.
| Fragment | Role | Variables |
| --- | --- | --- |
| `system.md` | Core assistant identity, global behavior, bounded runtime facts. | `{{operating_system}}`, `{{terminal_environment}}` |
| `tools.md` | General built-in tool-use guidance; it does not enumerate tool definitions. | runtime fact variables, `{{SKILLS_LIST}}` |
| `codemode.md` | `code_mode` tool guidance; included only when `code_mode` is enabled. | runtime fact variables, `{{SKILLS_LIST}}` |
| `subagents.md` | Template for generated subagent identity metadata. | `{{LIST_SUBAGENTS}}` at generation site |
| `skills.md` | Human-readable enabled skill list and skill-use rule. | `{{SKILLS_LIST}}` |
| `compact.md` | `/compact` summary instruction prompt, not part of normal system prompt. | runtime fact variables |
`{{TOOLS_LIST}}` is unsupported. A custom prompt fragment containing it fails fast as an unsupported variable.
Template variables are exact and case-sensitive. Extra whitespace inside braces is invalid. Unknown or malformed variables fail prompt construction with fragment name and offending token.
Runtime facts are local and bounded:
- `{{operating_system}}`: friendly Rust target OS name.
- `{{terminal_environment}}`: sanitized `TERM_PROGRAM`, `TERM`, and `COLORTERM` values only.
## Dynamic `AGENTS.md` context
Instruction discovery is intentionally narrow and ordered:
1. user file: `$MC_HOME/AGENTS.md` / `~/.magi-code/AGENTS.md`
2. repository file: active working directory `AGENTS.md`
3. absolute readable UTF-8 `.md` files in `knowledge.instructions.additional_markdown_paths`, in array order
Discovered files are appended after tool, subagent, and skill sections inside `<Additional-Context-Files>`. Each file uses:
```xml
<Context File=PATH>
raw file content
</Context>
```
The delimiters identify injected files:
- `Additional-Context-Files` separates injected file material from the static product prompt.
- `Context File=PATH` preserves the source path directly beside the raw content.
- Raw content remains unescaped, so author `AGENTS.md` as trusted instruction text, not data.
- The prompt explicitly tells the model not to read the same files again because their content is already injected.
If no files are discovered, the prompt contains `No AGENTS.md instruction files were discovered.`
## Tools in prompt vs provider schema
Tool-use guidance and tool definitions are separate surfaces:
| Surface | Source | Purpose |
| --- | --- | --- |
| Prompt text | Bundled or overridden `prompts/tools.md` guidance | Explain how to use the bounded tool interfaces. |
| Provider-native tool descriptions and JSON schemas | `mvp_tool_definitions_json_with_subagents(...)` | Let the provider emit validated function/tool calls. |
Tool names, descriptions, and schemas come from `src/tools/capability.rs` for provider requests. They are not copied into prompt text. Disabled tools are enforced in provider schemas and dispatch; the shared `<Tools>` guidance is not filtered.
## Skills
Skill discovery loads `SKILL.md` frontmatter and bodies locally, but the normal system prompt includes only enabled skill names and non-empty `description` frontmatter:
```text
- review: Review code changes for correctness.
- zed-themes
```
Full skill content enters context only when the model calls `read` on `skill://<name>` or `skill://<name>/<relative-reference>`. This keeps the base prompt compact while listing available capabilities.
Skill root priority, highest last-write wins:
1. `$MC_HOME/skills`
2. absolute configured `knowledge.skills.additional_paths` in listed order
3. repo `.agents/skills`
Discovery accepts direct `<skill>/SKILL.md` and one-level grouped `<group>/<skill>/SKILL.md` layouts.
## Subagents
Subagent identity metadata is optional. When available, generated identity text is inserted between tools and skills. Child agent sessions receive the same prompt guidance; disabled tools narrow their provider schemas and dispatch without changing that guidance.
A selected subagent profile appends its trimmed body in the same exact `<Your-Role Persona=...>` wrapper as a primary profile. The filename stem remains the selection/list id, while frontmatter `name` supplies `Persona`; nested selected profiles append after inherited ancestor wrappers.
`subagents` tool calls return bounded aggregate parent-visible output; raw child transcript details stay in child sessions.
## Provider request mapping
The constructed system prompt is stored as a system message in `ProviderRequest` conversation items, then mapped per provider API mode:
| Provider API mode | Mapping |
| --- | --- |
| Chat completions | System prompt stays in `messages[]` as role `system`; non-system messages, tool calls, and tool results also remain in `messages[]`. Tool schemas use Chat format: `{ "type": "function", "function": { ... } }`. |
| Responses API, custom providers | All system messages are joined with blank lines into top-level `instructions`; non-system conversation items go into top-level `input`. Tool schemas use Responses format: `{ "type": "function", "name": ..., "parameters": ... }`. |
| OpenAI Codex Responses | Same `instructions` + `input` split, with Codex defaults such as `text.verbosity=low`, reasoning insertion when supported, and `parallel_tool_calls=true` when tools are enabled. |
| Anthropic Messages | All system messages are joined with blank lines into top-level `system`; user and assistant turns go into `messages[]`. Tool schemas use `{ "name", "description", "input_schema" }`. |
| Claude subscription | Magi-code builds the Anthropic Messages body and hands it to Claude CLI. The joined `system` text goes into a temporary file passed with `--system-prompt-file`, which replaces Claude Code's default system prompt. Tool names get an `mcp__magi__` prefix and travel through `CLAUDE_CODE_EXTRA_BODY`. An inert MCP server named `magi` lists the same tools, so the CLI accepts those names without ever running them. `--tools ""` turns off Claude Code's built-in tools. Replayed thinking blocks are dropped. |
Chat completions keeps each system message where it appears in the conversation. Responses, Anthropic, and Claude subscription merge every system message into one system text, so a later system message loses its position.
Prompt cache material includes provider id, model, system prompt, and conversation items, so changing templates, `AGENTS.md`, tools/skills text, or provider model changes cache identity.
## Customization points
- Edit `$MC_HOME/AGENTS.md` for user-wide behavior.
- Edit repo `AGENTS.md` for project behavior.
- Override prompt fragments in `$MC_HOME/prompts/<fragment>.md`.
- Add skills under `$MC_HOME/skills`, configured absolute paths, or repo `.agents/skills`.
- Add subagent identity profiles under `$MC_HOME/subagents`.
- Add primary-agent profiles under `$MC_HOME/agents`; the selected primary-agent body is appended only to the main assistant system prompt, not child subagent prompts.
## Invariants
- Prompt section order is stable: system → tools → subagents → skills → additional context files.
- Dynamic context uses `<Additional-Context-Files>` and `<Context File=PATH>` delimiters.
- `<Tools>` contains guidance only; tool descriptions and schemas are supplied separately as provider-native definitions.
- Skills list only names/descriptions until `read skill://...` loads full content.
- Runtime facts are bounded, local, and non-secret by design.
- `CLAUDE.md` and arbitrary parent `AGENTS.md` files are not discovered.
- Provider mapping preserves system instructions outside normal user input for Responses APIs.
## Source map
| Behavior | Source |
| --- | --- |
| Prompt section order, template loading, variable rendering, dynamic context delimiters | `src/agent/prompt.rs` |
| Agent session prompt creation and primary-agent append hook | `src/agent.rs` |
| `AGENTS.md` discovery order | `src/instructions.rs` |
| Bundled prompt text | `prompts/system.md`, `prompts/tools.md`, `prompts/codemode.md`, `prompts/skills.md`, `prompts/subagents.md`, `prompts/compact.md` |
| Tool names, descriptions, provider schemas | `src/tools/capability.rs` |
| Skill discovery, frontmatter parsing, priority | `src/skills.rs` |
| Chat/Responses/Codex request bodies | `src/providers/openai.rs` |
| Anthropic Messages request body | `src/providers/anthropic.rs` |
| Claude subscription projection, CLI launch, inert tool inventory | `src/providers/claude_projection.rs`, `src/providers/claude_subscription.rs`, `src/providers/claude_inert.rs` |
| Related feature overview | `docs/features/instructions-prompts-skills-and-agents.md` |
## Related docs
- [Instructions, prompts, skills, and primary agents](instructions-prompts-skills-and-agents.md)
- [Tools and safety model](tools-and-safety.md)
- [Parallel subagents](parallel-subagents.md)
- [Sessions, context, and cache](sessions-context-cache.md)
---
[Back to feature docs](README.md) · [Back to repository README](../../README.md)