diff --git a/docs/agent_loop_diagram.md b/docs/agent_loop_diagram.md
new file mode 100644
index 0000000..2e35f96
--- /dev/null
+++ b/docs/agent_loop_diagram.md
@@ -0,0 +1,325 @@
+# Agent Loop Diagram
+
+## Overview
+
+This document describes the agent loop execution flow in AgentCore.jl, showing how the agent processes messages, executes tools, and handles steering/follow-up messages.
+
+## Architecture Layers
+
+```
+┌─────────────────────────────────────────────────────────────────────────┐
+│ Agent (High-Level) │
+│ - State management, event streaming, queueing │
+│ - Steering queue (steer()) and Follow-up queue (followUp()) │
+└─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────────────┐
+│ AgentLoop (Low-Level) │
+│ - Core loop execution with tool calling │
+│ - Tool execution (parallel/sequential) │
+│ - Event emission lifecycle │
+└─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────────────┐
+│ LLM Provider │
+│ - Stream function calls the LLM API │
+│ - Returns assistant response (text + tool calls) │
+└─────────────────────────────────────────────────────────────────────────┘
+```
+
+## Main Agent Loop Flow
+
+```mermaid
+flowchart TD
+ Start[Start Agent Loop] --> EmitStart[Emitter: AgentStartEvent]
+ EmitStart --> EmitTurnStart[Emitter: TurnStartEvent]
+
+ subgraph SteeringQueue "Check Steering Queue"
+ SteeringQueue --> HasSteering{Has pending
steering messages?}
+ HasSteering -- Yes --> ProcessSteering[Process steering messages
Emit MessageStart/End]
+ ProcessSteering --> AddToContext[Add to context messages]
+ AddToContext --> PollSteering
+ HasSteering -- No --> PollSteering
+ end
+
+ PollSteering{Next iteration:
Poll steering queue again}
+
+ subgraph AssistantLoop "Assistant Response Loop"
+ PollSteering --> StreamResponse[Stream Assistant Response from LLM]
+ StreamResponse --> CheckStop{Stop reason?}
+
+ CheckStop -- error/aborted --> EmitTurnEnd1[Emit: TurnEndEvent]
+ EmitTurnEnd1 --> EmitAgentEnd1[Emit: AgentEndEvent]
+ EmitAgentEnd1 --> End1[End Loop]
+
+ CheckStop -- length/truncated --> FailTools[Fail all tool calls
with error message]
+ CheckStop -- normal --> ExtractTools[Extract ToolCall objects]
+
+ FailTools --> HasMoreTools
+ ExtractTools --> HasMoreTools{Has tool
calls?}
+
+ HasMoreTools -- Yes --> ExecuteTools[Execute Tools]
+ HasMoreTools -- No --> CheckFollowUp
+
+ subgraph ToolExecution "Tool Execution"
+ direction TB
+ ExecuteTools --> ExecMode{Execution Mode?}
+
+ ExecMode -- Sequential --> SeqLoop[For each tool call:]
+ ExecMode -- Parallel --> ParaLoop[For each tool call:]
+
+ SeqLoop --> SeqPrepare[Prepare tool call]
+ ParaLoop --> ParaPrepare[Prepare tool call]
+
+ SeqPrepare --> SeqExec[Execute sequentially]
+ ParaPrepare --> ParaExec[Execute in parallel
& collect results]
+
+ SeqExec --> SeqFinalize[Finalize tool call
Emit: ToolExecutionEndEvent]
+ ParaExec --> ParaFinalize[Finalize tool calls
Emit: ToolExecutionEndEvent]
+
+ SeqFinalize --> SeqResults[Create ToolResultMessages]
+ ParaFinalize --> ParaResults[Create ToolResultMessages]
+
+ SeqResults --> AddToolResults
+ ParaResults --> AddToolResults[Add tool results to context
Emit: MessageStart/End]
+ end
+
+ AddToolResults --> HasMoreTools
+
+ CheckFollowUp{Has pending
follow-up messages?}
+ CheckFollowUp -- Yes --> ProcessFollowUp[Process follow-up messages
Emit MessageStart/End]
+ ProcessFollowUp --> AddToContext2[Add to context messages]
+ AddToContext2 --> CheckPrepareNext
+
+ CheckPrepareNext{Should prepare
next turn?}
+ CheckPrepareNext -- Yes --> PrepareNext[Call prepare_next_turn hook]
+ PrepareNext --> UpdateContext[Update context & config]
+ UpdateContext --> CheckStop2
+ CheckPrepareNext -- No --> CheckStop2
+
+ CheckStop2{Stop after turn?}
+ CheckStop2 -- Yes --> EmitAgentEnd2[Emit: AgentEndEvent]
+ EmitAgentEnd2 --> End2[End Loop]
+ CheckStop2 -- No --> PollSteering
+ end
+
+ CheckFollowUp -- No --> CheckPrepareNext
+```
+
+## Detailed Event Lifecycle
+
+```mermaid
+sequenceDiagram
+ participant Agent
+ participant Loop as AgentLoop
+ participant Emitter as Event Sink
+ participant LLM
+ participant Tools
+
+ Agent->>Loop: agentLoop(prompts, context, config)
+ Loop->>Emitter: AgentStartEvent
+ Loop->>Emitter: TurnStartEvent
+
+ note over Loop: Process prompts
+ Loop->>Emitter: MessageStartEvent(prompt)
+ Loop->>Emitter: MessageEndEvent(prompt)
+
+ Loop->>LLM: stream_function(model, context, config)
+ LLM-->>Loop: AssistantResponse with ToolCalls
+
+ note over Loop: Process response
+ Loop->>Emitter: MessageStartEvent(assistant)
+
+ alt Has Tool Calls
+ Loop->>Tools: Execute tools
+ Tools-->>Loop: ToolResults
+
+ note over Loop: Emit tool execution events
+ Loop->>Emitter: ToolExecutionStartEvent
+ Loop->>Emitter: ToolExecutionUpdateEvent (if streaming)
+ Loop->>Emitter: ToolExecutionEndEvent
+
+ Loop->>Emitter: MessageStartEvent(toolResult)
+ Loop->>Emitter: MessageEndEvent(toolResult)
+ end
+
+ Loop->>Emitter: MessageEndEvent(assistant)
+ Loop->>Emitter: TurnEndEvent(message, tool_results)
+
+ note over Loop: Check for follow-up/steering
+ alt Has more work
+ Loop->>Loop: Continue loop
+ else Done
+ Loop->>Emitter: AgentEndEvent(messages)
+ end
+```
+
+## Steering vs Follow-up Messages
+
+```mermaid
+graph LR
+ subgraph "Main Conversation"
+ A[User Message] --> B[Assistant Response]
+ B --> C[Tool Execution]
+ C --> D[Tool Result]
+ D --> E{Decision Point}
+ end
+
+ E -->|Continue loop| B
+ E -->|Stop & check queues| F
+
+ subgraph "Steering Queue"
+ steer[steer(message)] --> SQueue[Queued after
assistant turn]
+ SQueue --> SProcess[Processed in
next turn iteration]
+ end
+
+ subgraph "Follow-up Queue"
+ follow[followUp(message)] --> FQueue[Queued to run
when agent would stop]
+ FQueue --> FProcess[Processed only
when no more work]
+ end
+
+ F --> SProcess
+ F --> FProcess
+```
+
+## Tool Execution Modes
+
+### Sequential Execution
+```mermaid
+flowchart LR
+ Tool1[Tool Call 1] --> Prepare1[Prepare]
+ Prepare1 --> Execute1[Execute]
+ Execute1 --> Finalize1[Finalize]
+ Finalize1 --> Result1[Tool Result 1]
+
+ Result1 --> Prepare2[Prepare]
+ Prepare2 --> Execute2[Execute]
+ Execute2 --> Finalize2[Finalize]
+ Finalize2 --> Result2[Tool Result 2]
+
+ note right of Execute1 "Must complete before next tool"
+ note right of Execute2 "Tools run one at a time"
+```
+
+### Parallel Execution
+```mermaid
+flowchart LR
+ Tool1[Tool Call 1] --> Prepare1[Prepare]
+ Tool2[Tool Call 2] --> Prepare2[Prepare]
+ Tool3[Tool Call 3] --> Prepare3[Prepare]
+
+ Prepare1 --> Execute1[Execute]
+ Prepare2 --> Execute2[Execute]
+ Prepare3 --> Execute3[Execute]
+
+ Execute1 --> Finalize1[Finalize] --> Result1[Tool Result 1]
+ Execute2 --> Finalize2[Finalize] --> Result2[Tool Result 2]
+ Execute3 --> Finalize3[Finalize] --> Result3[Tool Result 3]
+
+ note right of Prepare1 "Preparation can happen"
+ note right of Execute1 "All tools execute"
+ note right of Finalize1 "Results collected in order"
+```
+
+## Message Conversion at LLM Boundary
+
+```mermaid
+flowchart LR
+ subgraph "Agent Messages (Internal)"
+ AM1[UserMessage]
+ AM2[AssistantMessage]
+ AM3[ToolResultMessage]
+ AM4[CompactionSummaryMessage]
+ AM5[BranchSummaryMessage]
+ AM6[CustomMessage]
+ end
+
+ AM1 --> Convert[convertToLlm]
+ AM2 --> Convert
+ AM3 --> Convert
+ AM4 --> Convert
+ AM5 --> Convert
+ AM6 --> Convert
+
+ Convert --> LM1[UserMessage]
+ Convert --> LM2[AssistantMessage]
+ Convert --> LM3[ToolResultMessage]
+ Convert --> LM4[UserMessage (summary)]
+ Convert --> LM5[UserMessage (branch)]
+ Convert --> LM6[UserMessage (custom)]
+
+ LM1 --> LLM[LLM API]
+ LM2 --> LLM
+ LM3 --> LLM
+ LM4 --> LLM
+ LM5 --> LLM
+ LM6 --> LLM
+```
+
+## Key Data Structures
+
+### AgentContext
+```julia
+struct AgentContext
+ system_prompt::String
+ messages::Vector{AgentMessage}
+ tools::Union{Vector{AgentTool}, Nothing}
+end
+```
+
+### AgentLoopConfig
+```julia
+struct AgentLoopConfig
+ model::Model
+ reasoning::Union{ThinkingLevel, Nothing}
+ session_id::Union{String, Nothing}
+ convert_to_llm::Function
+ transform_context::Union{Function, Nothing}
+ get_api_key::Union{Function, Nothing}
+ get_steering_messages::Function
+ get_follow_up_messages::Function
+ before_tool_call::Union{Function, Nothing}
+ after_tool_call::Union{Function, Nothing}
+ prepare_next_turn::Union{Function, Nothing}
+ should_stop_after_turn::Function
+ tool_execution::ToolExecutionMode
+ # ... other options
+end
+```
+
+## Entry Points
+
+1. **`prompt(agent, input)`** - Start new conversation
+ - Validates no active run
+ - Normalizes input to messages
+ - Calls `runPromptMessages`
+
+2. **`continue!(agent)`** - Continue from last message
+ - Checks last message is not assistant
+ - Drains steering/follow-up queues first
+ - Calls agent loop continuation
+
+## Termination Conditions
+
+The agent loop terminates when:
+1. LLM response has stop_reason = "error" or "aborted"
+2. No tool calls and no pending steering/follow-up messages
+3. `should_stop_after_turn` returns true
+4. Agent is aborted via abort signal
+
+## Event Summary
+
+| Event | When Emitted |
+|-------|--------------|
+| `AgentStartEvent` | Loop begins |
+| `TurnStartEvent` | Each conversation turn |
+| `MessageStartEvent` | Message added to context |
+| `MessageEndEvent` | Message fully processed |
+| `MessageUpdateEvent` | Streaming updates |
+| `ToolExecutionStartEvent` | Tool execution begins |
+| `ToolExecutionUpdateEvent` | Tool execution progress |
+| `ToolExecutionEndEvent` | Tool execution completes |
+| `TurnEndEvent` | Turn completes |
+| `AgentEndEvent` | Loop terminates |
diff --git a/docs/agent_loop_sequence_diagram.md b/docs/agent_loop_sequence_diagram.md
deleted file mode 100644
index 6b1b4ea..0000000
--- a/docs/agent_loop_sequence_diagram.md
+++ /dev/null
@@ -1,130 +0,0 @@
-# Agent Loop Sequence Diagram
-
-```
-+---------+ +---------+ +------------+ +-------+ +-------+
-| User | | Agent | | AgentLoop | | LLM | | Tool |
-+---------+ +---------+ +------------+ +-------+ +-------+
- | | | | |
- | prompt(messages)| | | |
- |---------------->--> | | |
- | | normalizePrompt()| | |
- | |----------------->>| | |
- | | runPromptMessages| | |
- | |----------------->>| | |
- | | | | |
- | | createLoopConfig | | |
- | |----------------->>| | |
- | | | | |
- | | agentLoop() | | |
- | |----------------->>| | |
- | | | emit(AgentStart) | |
- | | |------------------> | |
- | | | | |
- | | | transform_context() | |
- | | |------------------> | |
- | | | convert_to_llm() | |
- | | |------------------> | |
- | | | stream_function() | |
- | | |-------------------------> |
- | | | | response |
- | | |<------------------------- |
- | | | emit(MessageStart)| |
- | | |------------------> | |
- | | | emit(MessageEnd) | |
- | | |------------------> | |
- | | | | |
- | | | extract_tool_calls()| |
- | | |------------------> | |
- | | | | |
- | | | executeToolCalls() | |
- | | |-------------------------> |
- | | | | execute() |
- | | |-------------------------> |
- | | | | result |
- | | |<------------------------- |
- | | | emit(ToolExecutionEnd)| |
- | | |------------------> | |
- | | | createToolResult() | |
- | | |------------------> | |
- | | | emit(MessageEnd) | |
- | | |------------------> | |
- | | | | |
- | | | emit(TurnEnd) | |
- | | |------------------> | |
- | | | | |
- | | | prepare_next_turn() | |
- | | |------------------> | |
- | | | | |
- | | | should_stop_check() | |
- | | |------------------> | |
- | | | | |
- | | | drain(steering_queue)| |
- | | |------------------> | |
- | | | | |
- | | | drain(follow_up_queue)| |
- | | |------------------> | |
- | | | | |
- | | emit(AgentEnd) | | |
- | |------------------>| | |
- | | | | |
- | | appendMessage() | | |
- | |------------------> Session | |
- |<----------------| | | |
- | messages | | | |
- | | | | |
-```
-
-## Key Participants
-
-```
-User - Initiates conversation by calling prompt()
-Agent - High-level wrapper managing state, queues, and events
-AgentLoop - Low-level execution engine (agentLoop, runLoop)
-LLM - Language model API (via stream_function)
-Tool - Tool execution (bash, read, write, edit)
-Session - Conversation history persistence
-```
-
-## Main Loop Flow
-
-```
-1. [Agent] normalizePromptInput() - Convert input to messages
-2. [Agent] runPromptMessages() - Start processing
-3. [Agent] createLoopConfig() - Build loop configuration
-4. [Agent] agentLoop() - Start low-level loop
-5. [AgentLoop] emit(AgentStart) - Signal start
-6. [AgentLoop] transform_context() - Optional context transform
-7. [AgentLoop] convert_to_llm() - Convert to LLM messages
-8. [AgentLoop] stream_function() - Call LLM
-9. [AgentLoop] emit(MessageStart/End) - Stream response
-10. [AgentLoop] extract_tool_calls() - Check for tool calls
-11. [AgentLoop] executeToolCalls() - Execute tools (seq/parallel)
-12. [AgentLoop] emit(TurnEnd) - Signal turn complete
-13. [AgentLoop] prepare_next_turn() - Optional next turn setup
-14. [AgentLoop] should_stop_check() - Check termination
-15. [AgentLoop] drain queues() - Check steering/follow-up
-16. [AgentLoop] emit(AgentEnd) - Signal completion
-17. [Agent] appendMessage() - Persist to session
-```
-
-## Queue Processing
-
-```
-steering_queue: Injected after assistant turn, before next LLM call
-follow_up_queue: Run only when agent would otherwise stop (after loop exit)
-```
-
-## Event Flow
-
-```
-AgentStart → [TurnStart → MessageStart → MessageEnd → ...] → TurnEnd → ...
- ↓
- AgentEnd
-```
-
-## Tool Execution Options
-
-```
-Sequential: One tool at a time, in order
-Parallel: All tools spawned concurrently, results collected
-```