magi-code 0.77.1

Repository-aware CLI coding agent for terminal work
Documentation
# 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. optional generated subagent identity section
4. `prompts/skills.md`
5. 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`.

Progressive shape:

```xml
<SYSTEM>
  Core magi-code behavior rules.
</SYSTEM>

<USER-SYSTEM>
  - ripgrep availability
  - 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. | `{{has_ripgrep}}`, `{{operating_system}}`, `{{terminal_environment}}` |
| `tools.md` | General built-in tool-use guidance; it does not enumerate tool definitions. | 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:

- `{{has_ripgrep}}`: result of a timed `rg --version` probe.
- `{{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 project root `AGENTS.md`

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>
```

Why delimiter matters:

- `Additional-Context-Files` separates injected file material from static product prompt.
- `Context File=PATH` preserves source path directly beside raw content.
- Raw content remains unescaped, so author `AGENTS.md` as trusted instruction text, not data.
- Prompt explicitly tells model not to read same files again because content is already injected.

If no files are discovered, 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 model calls `read` on `skill://<name>` or `skill://<name>/<relative-reference>`. This keeps the base prompt compact while advertising available capabilities.

Skill root priority, highest last-write wins:

1. legacy `~/.agents/skills`
2. `$MC_HOME/skills`
3. absolute configured `knowledge.skills.additional_paths` in listed order
4. 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 OpenAI-compatible 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. |

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/primary-agents`; selected primary-agent body is appended only to 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/mod.rs` |
| `AGENTS.md` discovery order | `src/instructions/mod.rs` |
| Bundled prompt text | `prompts/system.md`, `prompts/tools.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/mod.rs` |
| Chat/Responses/Codex request bodies | `src/providers/openai.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)