Context: Studying Claude Code source code (backup branch)
Complete Message Anatomy of a Claude Code API Turn
System Prompt (role: system)
Built in QueryEngine.ts:321, finalized in claude.ts:1358:
- Attribution header (fingerprint)
- CLI sysprompt prefix (interactive vs non-interactive)
- Default system prompt (or custom SDK prompt)
- Memory mechanics prompt (if custom prompt + memory override)
- Append system prompt (SDK callers)
- Advisor tool instructions (if advisor model)
- Chrome tool search instructions (if chrome MCP)
- gitStatus (from
context.ts:116viaappendSystemContext) - cacheBreaker (ant-only)
Messages (role: user or assistant)
Everything except system prompt and assistant responses is user-role. The API only has system/user/assistant roles.
Session Start
[user, isMeta]Deferred tools listing (claude.ts:1337)[user, isMeta]userContext wrapped in<system-reminder>(api.ts:449): CLAUDE.md content, currentDate
User Input + Attachments
[user]Actual user message[user, isMeta]~30+ attachment types fromgetAttachments()(attachments.ts:743), all<system-reminder>wrapped. Categories:- User input: @-mentioned files (simulated Read tool_use/result), MCP resources, agent mentions, skill discovery
- Per-turn state: queued_commands, date_change, ultrathink_effort, deferred_tools_delta, agent_listing_delta, mcp_instructions_delta, changed files, nested_memory, relevant_memories, dynamic_skill, skill_listing, plan_mode, todo/task_reminder, teammate_mailbox, team_context, critical_system_reminder, compaction_reminder, context_efficiency, output_style, diagnostics, IDE state
- Post-compact: invoked_skills (up to 25K tokens), plan_file_reference, current_session_memory
Model Response
[assistant]thinking block, text blocks, tool_use blocks
Tool Execution Cycle (toolExecution.ts)
For each tool_use in the assistant response:
PreToolUse hooks:
[user, isMeta] hook_success (line 815)
[user, isMeta] hook_additional_context (line 846, <system-reminder> wrapped)
[user, isMeta] hook_permission_decision (if hook decided)
[user, isMeta] hook_blocking_error (if hook blocked)
OR [user] tool_result error (line 853, if hook stopped)
Permission check:
[user, isMeta] command_permissions (line 985)
Tool result:
[user] tool_result (line 1478)
PostToolUse hooks (non-MCP, pushed immediately):
[user, isMeta] hook_success (line 1515)
[user, isMeta] hook_additional_context (toolHooks.ts:133)
Tool's newMessages (e.g. SkillTool):
[user] command metadata (<command-message> tags)
[user, isMeta] SKILL.md content (full skill instructions)
[user, isMeta] skill @-mention attachments
[user, isMeta] command_permissions (skill's allowedTools)
[user, isMeta] hook_stopped_continuation (line 1572, if preventContinuation)
Then getAttachmentMessages runs again with updated state, plus memory prefetch and skill discovery prefetch consume.
Loop repeats for each subsequent tool_use until stop_reason: end_turn.
Key Observations
- All injected content is user-role. Hooks, attachments, skills, tool results, file changes, IDE state, memory, team messages: all
isMeta: trueuser messages. The model has no formal way to distinguish sources. - Consecutive user messages are merged by
normalizeMessagesForAPI(messages.ts:1989) into single user turns. Content blocks accumulate. <system-reminder>is the only priority signal. Withtengu_chair_sermongate, all attachments getensureSystemReminderWrap. Without it, only some types wrap explicitly. Either way, no formal authority hierarchy.- Recency dominates. Order within a turn: user input → attachments → assistant → PreToolUse hooks → tool_result → PostToolUse hooks → skill newMessages → more attachments. Skill content and post-execution attachments have strongest positional influence.