Files
YiemAgent/learning/01-ARCHITECTURE_OVERVIEW.md
T
2026-07-30 09:28:19 +07:00

61 KiB

AgentCore.jl - Architecture Overview

Top-Down Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│                        AgentCore.jl Layers                              │
└─────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────┐
│  Level 1: AgentHarness (Session Management & Persistence)               │
│  - Session persistence with JSONL storage                               │
│  - Resource management (skills, prompt templates)                       │
│  - Extension hooks system                                               │
│  - Branch navigation and compaction                                     │
└─────────────────────────────────────────────────────────────────────────┘
                              │
                              │ orchestrates
                              ▼
┌─────────────────────────────────────────────────────────────────────────┐
│  Level 2: Agent (State Management & Event Streaming)                    │
│  - Conversation state (messages, tools, system prompt)                  │
│  - Event streaming and lifecycle management                             │
│  - Steering and follow-up message queues                                │
│  - Abort handling                                                       │
└─────────────────────────────────────────────────────────────────────────┘
                              │
                              │ delegates to
                              ▼
┌─────────────────────────────────────────────────────────────────────────┐
│  Level 3: AgentLoop (Core LLM Interaction Loop)                         │
│  - Stateful LLM interactions                                            │
│  - Tool execution (parallel or sequential)                              │
│  - Event emission lifecycle                                             │
│  - Steering/follow-up message handling                                  │
└─────────────────────────────────────────────────────────────────────────┘
                              │
                              │ transforms to
                              ▼
┌─────────────────────────────────────────────────────────────────────────┐
│  Level 4: Session (Conversation History Management)                     │
│  - Tree-based conversation history                                      │
│  - Branch support with compaction                                       │
│  - Message and metadata persistence                                     │
└─────────────────────────────────────────────────────────────────────────┘

Process Flow

1. Agent Lifecycle

┌─────────────────────────────────────────────────────────────────────────┐
│                         Agent Lifecycle                                 │
└─────────────────────────────────────────────────────────────────────────┘

    User Code
         │
         │ 1. Create Agent
         ▼
    ┌──────────────┐
    │   Agent()    │  ──► Initialize state, queues, listeners
    └──────────────┘
         │
         │ 2. Subscribe to events
         ▼
    ┌──────────────────┐
    │ subscribe()      │  ──► Register event handlers
    └──────────────────┘
         │
         │ 3. Run prompt
         ▼
    ┌──────────────────┐
    │ prompt()         │  ──► Validate input, normalize messages
    └──────────────────┘
         │
         │ 4. Start AgentLoop
         ▼
    ┌──────────────────┐
    │ runPromptMessages│  ──► Create ActiveRun, spawn loop
    └──────────────────┘
         │
         ▼
    ┌──────────────────────────────────────────────────────────────┐
    │  AgentLoop (runs in separate thread)                         │
    │                                                              │
    │  ┌────────────────────────────────────────────────────────┐  │
    │  │ 1. Emit AgentStartEvent                                │  │
    │  │ 2. Emit TurnStartEvent                                 │  │
    │  │ 3. Process prompts (emit MessageStart/End)             │  │
    │  │ 4.┌────────────────────────────────────────────────┐   │  │
    │  │   │ while true:                                    │   │  │
    │  │   │   │ Process steering/follow-up messages        │   │  │
    │  │   │   │ Stream assistant response (LLM call)       │   │  │
    │  │   │   │ Execute tool calls (parallel/sequential)   │   │  │
    │  │   │   │ Emit TurnEndEvent                          │   │  │
    │  │   │   │ Check if should stop                       │   │  │
    │  │   │   │ Get next steering messages                 │   │  │
    │  │   └───┴────────────────────────────────────────────┘   │  │
    │  └────────────────────────────────────────────────────────┘  │
    └──────────────────────────────────────────────────────────────┘
         │
         │ 5. Event streaming
         ▼
    ┌──────────────────┐
    │ Event Handlers   │  ──► User-defined listeners receive events
    └──────────────────┘
         │
         │ 6. Wait for completion
         ▼
    ┌──────────────────┐
    │ waitForIdle()    │  ──► Resolve when all events processed
    └──────────────────┘

2. AgentLoop Flow Diagram

┌─────────────────────────────────────────────────────────────────────────┐
│                    AgentLoop Process Flow                               │
└─────────────────────────────────────────────────────────────────────────┘

    ┌────────────────────────────────────────────────────────────────────┐
    │  AgentLoop Entrypoint                                              │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ agentLoop(prompts, context, config, signal, stream_fn)     │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                              │                                     │
    │                              ▼                                     │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ runAgentLoop(prompts, context, config, emit, signal)       │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                              │                                     │
    │                              ▼                                     │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ runLoop() - Main Event Loop                                │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                              │                                     │
    └──────────────────────────────┼─────────────────────────────────────┘
                                   │
                                   │ Loop Iteration
                                   ▼
    ┌────────────────────────────────────────────────────────────────────┐
    │  Main Processing Loop                                              │
    │                                                                    │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ 1. Get Steering/Follow-up Messages                         │    │
    │  │    ┌────────────────────┐      ┌──────────────────────┐    │    │
    │  │    │ steering_queue     │      │ follow_up_queue      │    │    │
    │  │    │ (after assistant)  │      │ (after stop)         │    │    │
    │  │    └────────────────────┘      └──────────────────────┘    │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                              │                                     │
    │                              ▼                                     │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ 2. Stream Assistant Response                               │    │
    │  │    ┌────────────────────────────────────────────────────┐  │    │
    │  │    │ transform_context()                                │  │    │
    │  │    │ convert_to_llm(messages) -> Message[]              │  │    │
    │  │    │ stream_fn(model, context, config) -> Response      │  │    │
    │  │    │  - Text deltas                                     │  │    │
    │  │    │  - Tool call deltas                                │  │    │
    │  │    └────────────────────────────────────────────────────┘  │    │
    │  │                              │                             │    │
    │  │                              ▼                             │    │
    │  │  ┌────────────────────────────────────────────────────┐    │    │
    │  │  │ Emit: MessageStartEvent, MessageUpdateEvent,       │    │    │
    │  │  │       MessageEndEvent                              │    │    │
    │  │  └────────────────────────────────────────────────────┘    │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                              │                                     │
    │                              ▼                                     │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ 3. Execute Tool Calls                                      │    │
    │  │    ┌────────────────────────────────────────────────────┐  │    │
    │  │    │ extract ToolCall from assistant content            │  │    │
    │  │    │                                                    │  │    │
    │  │    │ if EXECUTION_SEQUENTIAL || has_sequential_tool:    │  │    │
    │  │    │   executeToolCallsSequential()                     │  │    │
    │  │    │ else:                                              │  │    │
    │  │    │   executeToolCallsParallel()                       │  │    │
    │  │    └────────────────────────────────────────────────────┘  │    │
    │  │                              │                             │    │
    │  │                              ▼                             │    │
    │  │  ┌────────────────────────────────────────────────────┐    │    │
    │  │  │ For each tool call:                                │    │    │
    │  │  │  1. before_tool_call hook                          │    │    │
    │  │  │  2. prepareToolCall()                              │    │    │
    │  │  │  3. execute()                                      │    │    │
    │  │  │  4. after_tool_call hook                           │    │    │
    │  │  │  5. Emit ToolExecutionStart/Update/EndEvent        │    │    │
    │  │  │  6. Emit ToolResultMessage                         │    │    │
    │  │  └────────────────────────────────────────────────────┘    │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                              │                                     │
    │                              ▼                                     │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ 4. Prepare Next Turn                                       │    │
    │  │    ┌────────────────────────────────────────────────────┐  │    │
    │  │    │ prepare_next_turn(context) -> next_turn_snapshot   │  │    │
    │  │    │ - Optional: Update model/thinking_level            │  │    │
    │  │    │ - Optional: Update context                         │  │    │
    │  │    └────────────────────────────────────────────────────┘  │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                              │                                     │
    │                              ▼                                     │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ 5. Check Termination Conditions                            │    │
    │  │    ┌────────────────────────────────────────────────────┐  │    │
    │  │    │ should_stop_after_turn(context) -> bool            │  │    │
    │  │    │ - Max turns reached?                               │  │    │
    │  │    │ - Tool returned terminate=true?                    │  │    │
    │  │    │ - Steering queue empty and follow-up empty?        │  │    │
    │  │    └────────────────────────────────────────────────────┘  │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                              │                                     │
    │                              ▼                                     │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ 6. Emit TurnEndEvent (message, tool_results)               │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                              │                                     │
    │                              ▼                                     │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ Loop continues until termination condition met             │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                              │                                     │
    └──────────────────────────────┼─────────────────────────────────────┘
                                   │
                                   ▼
    ┌────────────────────────────────────────────────────────────────────┐
    │  AgentEndEvent with final messages                                 │
    └────────────────────────────────────────────────────────────────────┘

3. Tool Execution Flow

┌─────────────────────────────────────────────────────────────────────────┐
│                        Tool Execution Flow                              │
└─────────────────────────────────────────────────────────────────────────┘

    ┌───────────────────────────────────────────────────────────────────┐
    │  Assistant Message with Tool Calls                                │
    │  ┌─────────────────────────────────────────────────────────────┐  │
    │  │ AssistantMessage:                                           │  │
    │  │   content: [                                                │  │
    │  │     TextContent("I'll help you"),                           │  │
    │  │     ToolCall(id="tc1", name="bash", args={...}),            │  │
    │  │     ToolCall(id="tc2", name="read", args={...})             │  │
    │  │   ]                                                         │  │
    │  └─────────────────────────────────────────────────────────────┘  │
    │                              │                                    │
    │                              ▼                                    │
    └───────────────────────────────────────────────────────────────────┘
                                   │
                                   │ executeToolCalls()
                                   ▼
    ┌───────────────────────────────────────────────────────────────────┐
    │  Determine Execution Mode                                         │
    │  ┌─────────────────────────────────────────────────────────────┐  │
    │  │ config.tool_execution == EXECUTION_SEQUENTIAL?              │  │
    │  │ OR any tool has execution_mode == EXECUTION_SEQUENTIAL?     │  │
    │  └─────────────────────────────────────────────────────────────┘  │
    │                              │                                    │
    │              ┌───────────────┴───────────────┐                    │
    │              ▼                               ▼                    │
    │  ┌────────────────────────┐      ┌────────────────────────┐       │
    │  │ executeSequential()    │      │ executeParallel()      │       │
    │  └────────────────────────┘      └────────────────────────┘       │
    │              │                               │                    │
    └──────────────┼───────────────────────────────┼────────────────────┘
                   │                               │
                   │                               │
                   ▼                               ▼
    ┌──────────────────────┐              ┌──────────────────────┐
    │ Sequential Execution │              │ Parallel Execution   │
    │                      │              │                      │
    │  for tool_call in:   │              │  for tool_call in:   │
    │    prepareToolCall() │              │    prepareToolCall() │
    │    execute()         │              │    execute() (async) │
    │    finalize()        │              │                      │
    │                      │              │  wait all results    │
    │                      │              └──────────────────────┘
    └──────────────────────┘
                   │
                   ▼
    ┌───────────────────────────────────────────────────────────────────┐
    │  For Each Tool Call                                               │
    │  ┌─────────────────────────────────────────────────────────────┐  │
    │  │ 1. before_tool_call hook (optional)                         │  │
    │  │    - Can block execution                                    │  │
    │  │ 2. prepareToolCall()                                        │  │
    │  │    - validateToolArguments()                                │  │
    │  │    - prepareToolCallArguments() (optional)                  │  │
    │  │ 3. Execute Tool:                                            │  │
    │  │    tool.execute(tool_call_id, args, signal, on_update)      │  │
    │  │ 4. after_tool_call hook (optional)                          │  │
    │  │    - Can modify result content                              │  │
    │  │ 5. Emit events:                                             │  │
    │  │    - ToolExecutionStartEvent                                │  │
    │  │    - ToolExecutionUpdateEvent (optional)                    │  │
    │  │    - ToolExecutionEndEvent                                  │  │
    │  │ 6. Create ToolResultMessage                                 │  │
    │  └─────────────────────────────────────────────────────────────┘  │
    └───────────────────────────────────────────────────────────────────┘
                   │
                   ▼
    ┌───────────────────────────────────────────────────────────────────┐
    │  Tool Result Messages                                             │
    │  ┌─────────────────────────────────────────────────────────────┐  │
    │  │ ToolResultMessage:                                          │  │
    │  │   role: "toolResult"                                        │  │
    │  │   tool_call_id: "tc1"                                       │  │
    │  │   tool_name: "bash"                                         │  │
    │  │   content: [TextContent("command output")]                  │  │
    │  │   is_error: false                                           │  │
    │  └─────────────────────────────────────────────────────────────┘  │
    └───────────────────────────────────────────────────────────────────┘

4. Session & Tree Structure

┌─────────────────────────────────────────────────────────────────────────┐
│                        Session Tree Structure                           │
└─────────────────────────────────────────────────────────────────────────┘

    Session = Linked List of Entries (tree structure)

    ┌───────────────────────────────────────────────────────────────────┐
    │  Branch Navigation                                                │
    │                                                                   │
    │  ┌─────┐      ┌─────┐     ┌─────┐      ┌─────┐     ┌─────┐        │
    │  │ E1  │────▶│ E2  │────▶│ E3  │────▶│ E4  │────▶│ E5  │ (leaf) │
    │  └─────┘      └─────┘     └─────┘      └─────┘     └─────┘        │
    │      │           │           │           │           │            │
    │      ▼           ▼           ▼           ▼           ▼            │
    │   Message    Message    Compaction   Message    BranchSummary     │
    │                                                                   │
    │  E3 is a Compaction Entry:                                        │
    │  - Summary of E1, E2                                              │
    │  - first_kept_entry_id: reference to first retained message       │
    │  - tokens_before: context size before compaction                  │
    │                                                                   │
    │  E5 is a BranchSummary Entry:                                     │
    │  - Summary of branch from from_id                                 │
    │  - Represents a fork point in conversation history                │
    │                                                                   │
    └───────────────────────────────────────────────────────────────────┘
                   │
                   │ Session.moveTo()
                   ▼
    ┌───────────────────────────────────────────────────────────────────┐
    │  Forking & Branching                                              │
    │                                                                   │
    │  Current branch:                                                  │
    │  ┌─────┐      ┌─────┐     ┌─────┐                                 │
    │  │ E1  │────▶│ E2  │────▶│ E3  │                                 │
    │  └─────┘      └─────┘     └─────┘                                 │
    │                              │                                    │
    │                              │ moveTo(E2)                         │
    │                              ▼                                    │
    │  ┌─────┐      ┌─────┐     ┌─────┐      ┌─────┐                    │
    │  │ E1  │────▶│ E2  │────▶│ E3' │────▶│ E4' │ (new branch)       │
    │  └─────┘      └─────┘     └─────┘      └─────┘                    │
    │                                    │                              │
    │                                    │ create BranchSummary         │
    │                                    ▼                              │
    │                                  ┌─────┐                          │
    │                                  │ E5  │ (branch summary)         │
    │                                  └─────┘                          │
    │                                                                   │
    └───────────────────────────────────────────────────────────────────┘

Component Relationships

┌─────────────────────────────────────────────────────────────────────────────┐
│                          Component Relationships                            │
└─────────────────────────────────────────────────────────────────────────────┘

    User Code
        │
        ├── Creates ──► Agent
        │                  │
        │                  ├── Uses ──► AgentLoop
        │                  │                 │
        │                  │                 ├── Uses ──► StreamFn (LLM API)
        │                  │                 │
        │                  │                 └── Uses ──► Session
        │                  │
        │                  ├── Manages ──► AgentState
        │                  │
        │                  ├── Queues ──► SteeringQueue
        │                  │
        │                  └── Queues ──► FollowUpQueue
        │
        └── Interacts With ──► AgentHarness (optional, higher level)
                              │
                              ├── Manages ──► SessionRepo
                              │
                              ├── Manages ──► Skills
                              │
                              └── Manages ──► PromptTemplates

Data Flow with Type Transformations

Complete User Input → Conversation History Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│ Level 1: User Input                                                         │
└─────────────────────────────────────────────────────────────────────────────┘
    User Input
    • String: "Hello, what's in the directory?"
    • AgentMessage: UserMessage(...)
    • Vector{AgentMessage}: [UserMessage(...), AssistantMessage(...)]

              │
              ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ Agent.prompt() / normalizePromptInput()                      │
    │                                                              │
    │  Type Dispatch:                                              │
    │  • String → UserMessage("user", [TextContent(input)], ts)    │
    │  • AgentMessage → [input] (wrap in array)                    │
    │  • Vector{AgentMessage} → input (pass-through)               │
    │                                                              │
    │  Output: Vector{AgentMessage}                                │
    └──────────────────────────────────────────────────────────────┘
              │
              ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ AgentState.messages (AgentMessage[])                         │
    │                                                              │
    │  AgentMessage Types:                                         │
    │  • UserMessage (role: "user")                                │
    │  • AssistantMessage (role: "assistant")                      │
    │  • ToolResultMessage (role: "toolResult")                    │
    │  • BashExecutionMessage (custom)                             │
    │  • CompactionSummaryMessage (custom)                         │
    │  • BranchSummaryMessage (custom)                             │
    └──────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│ Level 2: AgentLoop Processing                                               │
└─────────────────────────────────────────────────────────────────────────────┘

    ┌──────────────────────────────────────────────────────────────┐
    │ transform_context() (optional hook)                          │
    │                                                              │
    │  Input:  Vector{AgentMessage}                                │
    │  Output: Vector{AgentMessage} (transformed)                  │
    │  - Can truncate, filter, or modify messages                  │
    └──────────────────────────────────────────────────────────────┘
              │
              ▼
    ┌────────────────────────────────────────────────────────────────┐
    │ convertToLlm() - Type Transformation Pipeline                  │
    │                                                                │
    │  Input:  Vector{AgentMessage}                                  │
    │  Output: Vector{Message} (for LLM API)                         │
    │                                                                │
    │  Single Dispatch Mapping:                                      │
    │  • UserMessage → UserMessage (pass-through)                    │
    │  • AssistantMessage → AssistantMessage (pass-through)          │
    │  • ToolResultMessage → ToolResultMessage (pass-through)        │
    │                                                                │
    │  Custom Message Conversions:                                   │
    │  • BashExecutionMessage → UserMessage (via bashExecutionToText)│
    │  • CompactionSummaryMessage → UserMessage (wrapped)            │
    │  • BranchSummaryMessage → UserMessage (wrapped)                │
    └────────────────────────────────────────────────────────────────┘
              │
              ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ Context for LLM API                                          │
    │  - system_prompt: String                                     │
    │  - messages: Vector{Message}                                 │
    │  - tools: Vector{AgentTool}                                  │
    └──────────────────────────────────────────────────────────────┘
              │
              ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ LLM API Call (stream_fn)                                     │
    │                                                              │
    │  Input:  model, context, config                              │
    │  Output: Stream{AssistantMessageEvent}                       │
    │    • StartEvent: partial AssistantMessage                    │
    │    • TextStartEvent/TextDeltaEvent/TextEndEvent              │
    │    • ToolCallStartEvent/ToolCallDeltaEvent/ToolCallEndEvent  │
    │    • DoneEvent: final AssistantMessage with usage            │
    └──────────────────────────────────────────────────────────────┘
              │
              ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ AssistantMessage (returned from LLM)                         │
    │                                                              │
    │  • role: "assistant"                                         │
    │  • content: Vector{MessageContent}                           │
    │    └─ Contains: TextContent[] and/or ToolCall[]              │
    │  • api, provider, model: String                              │
    │  • usage: Usage (input, output, cache_read, cache_write)     │
    │  • stop_reason: String ("done", "length", "error", etc.)     │
    │  • error_message: Union{String, Nothing}                     │
    │  • timestamp: Timestamp (Int64)                              │
    └──────────────────────────────────────────────────────────────┘
              │
              ├─► Append to AgentState.messages (AssistantMessage)
              │
              ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ executeToolCalls() - Tool Processing                         │
    │                                                              │
    │  Extract: filter(c -> c isa ToolCall, assistant.content)     │
    │  Output: ExecutedToolCallBatch                               │
    │    • messages: Vector{ToolResultMessage}                     │
    │    • terminate: Bool                                         │
    └──────────────────────────────────────────────────────────────┘
              │
              ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ ToolResultMessage (for each ToolCall)                        │
    │                                                              │
    │  • role: "toolResult"                                        │
    │  • tool_call_id: String (matches ToolCall.id)                │
    │  • tool_name: String (matches ToolCall.name)                 │
    │  • content: Vector{MessageContent}                           │
    │  • details: Any (tool-specific)                              │
    │  • usage: Union{Usage, Nothing}                              │
    │  • added_tool_names: Union{Vector{String}, Nothing}          │
    │  • is_error: Bool                                            │
    │  • timestamp: Timestamp (Int64)                              │
    └──────────────────────────────────────────────────────────────┘
              │
              ├─► Append to AgentState.messages (ToolResultMessage)
              │
              ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ Updated AgentState.messages (AgentMessage[])                 │
    │                                                              │
    │  Conversation History:                                       │
    │  [UserMessage, AssistantMessage, ToolResultMessage, ...]     │
    └──────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│ Level 3: Session Storage (optional, for persistence)                        │
└─────────────────────────────────────────────────────────────────────────────┘

    AgentState.messages (Vector{AgentMessage})
              │
              ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ Session Storage (JSONL)                                      │
    │                                                              │
    │  SessionTreeEntry Types:                                     │
    │  • MessageEntry (agent_message)                              │
    │  • CompactionEntry (summary, tokens_before)                  │
    │  • BranchSummaryEntry (from_id, summary)                     │
    │  • ModelChangeEntry (provider, model_id)                     │
    │  • ThinkingLevelChangeEntry (thinking_level)                 │
    │  • ActiveToolsChangeEntry (active_tool_names)                │
    └──────────────────────────────────────────────────────────────┘
              │
              ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ Persisted Data (JSON format)                                 │
    │  - Each entry has: id, parent_id, timestamp, type            │
    │  - MessageEntry contains full AgentMessage                   │
    └──────────────────────────────────────────────────────────────┘

Tool Call Execution Flow (Detailed)

ToolCall (from AssistantMessage.content)
    │
    ├─ type: "tool"
    ├─ id: "tc_abc123"
    ├─ name: "bash"
    ├─ arguments: Dict("command" => "ls -la")
    └─ partial_json: nothing
         │
         ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ prepareToolCall()                                            │
    │                                                              │
    │  Input:  tool_call::ToolCall                                 │
    │  Output: Union{PreparedToolCall, ImmediateToolCallOutcome}   │
    │                                                              │
    │  Steps:                                                      │
    │  1. Find tool by name in current_context.tools               │
    │  2. before_tool_call hook (optional)                         │
    │     Input: BeforeToolCallContext                             │
    │     Output: BeforeToolCallResult (block, reason) or nothing  │
    │  3. prepareToolCallArguments() (optional)                    │
    │     Input: tool_call.arguments::Dict                         │
    │     Output: prepared_arguments::Any                          │
    │  4. validateToolArguments() (optional)                       │
    │     Input: prepared_tool_call.arguments                      │
    │     Output: validated_args::Any                              │
    │  5. Return: PreparedToolCall(kind, tool_call, tool, args)    │
    └──────────────────────────────────────────────────────────────┘
         │
         ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ executePreparedToolCall() (if prepared)                      │
    │                                                              │
    │  Input:  PreparedToolCall                                    │
    │  Output: ExecutedToolCallOutcome                             │
    │                                                              │
    │  tool.execute(tool_call.id, args, signal, on_update)         │
    │     │                                                        │
    │     └─ Returns: AgentToolResultMutable                       │
    │         • content::Vector{MessageContent}                    │
    │         • details::Any                                       │
    │         • usage::Union{Usage, Nothing}                       │
    │         • added_tool_names::Union{Vector{String}, Nothing}   │
    │         • terminate::Union{Bool, Nothing}                    │
    └──────────────────────────────────────────────────────────────┘
         │
         ▼
    ┌───────────────────────────────────────────────────────────────┐
    │ finalizeExecutedToolCall()                                    │
    │                                                               │
    │  Input:  ExecutedToolCallOutcome                              │
    │  Output: FinalizedToolCallOutcome                             │
    │                                                               │
    │  Steps:                                                       │
    │  1. after_tool_call hook (optional)                           │
    │     Input: AfterToolCallContext                               │
    │     Output: AfterToolCallResult (patches)                     │
    │  2. Apply patches to result                                   │
    │  3. Return: FinalizedToolCallOutcome(tool_call, result, error)│
    └───────────────────────────────────────────────────────────────┘
         │
         ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ createToolResultMessage()                                    │
    │                                                              │
    │  Input:  FinalizedToolCallOutcome                            │
    │  Output: ToolResultMessage                                   │
    │                                                              │
    │  Fields:                                                     │
    │  • role: "toolResult"                                        │
    │  • tool_call_id: tool_call.id                                │
    │  • tool_name: tool_call.name                                 │
    │  • content: result.content                                   │
    │  • details: result.details                                   │
    │  • usage: result.usage                                       │
    │  • added_tool_names: result.added_tool_names                 │
    │  • is_error: is_error                                        │
    │  • timestamp: Int64(Dates.now(Dates.UTC).datetime)           │
    └──────────────────────────────────────────────────────────────┘
         │
         ▼
    ┌──────────────────────────────────────────────────────────────┐
    │ Emit: ToolResultMessage to conversation                      │
    └──────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│ Summary of Type Transformations                                             │
└─────────────────────────────────────────────────────────────────────────────┘

    User Input (String)
         │
         ├─► normalizePromptInput()
         │    └─► UserMessage (AgentMessage subtype)
         │
    Vector{AgentMessage}
         │
         ├─► transform_context() (optional)
         │    └─► Vector{AgentMessage} (transformed)
         │
         ├─► convertToLlm()
         │    └─► Vector{Message} (LLM API format)
         │         ├── UserMessage (pass-through)
         │         ├── AssistantMessage (pass-through)
         │         ├── ToolResultMessage (pass-through)
         │         └── Custom messages → UserMessage
         │
    AssistantMessage (from LLM)
         │
         ├─► executeToolCalls()
         │    └─► ToolResultMessage[]
         │
    ToolResultMessage[]
         │
         └─► Appended to AgentState.messages
              └─► Vector{AgentMessage} (updated conversation history)

Summary

Summary

The AgentCore.jl architecture follows a clean separation of concerns:

  1. AgentHarness - Highest level, handles persistence and resources
  2. Agent - State management and event streaming
  3. AgentLoop - Core LLM interaction loop
  4. Session - Conversation history management

Data Transformation Summary

Input Type Flow:
    User Input (String/Message)
         │
         ├─ normalizePromptInput()
         │    └─► Vector{AgentMessage}
         │
         ├─ transform_context() (optional)
         │    └─► Vector{AgentMessage} (transformed)
         │
         ├─ convertToLlm()
         │    └─► Vector{Message} (LLM API format)
         │
         ├─ LLM API (stream_fn)
         │    └─► AssistantMessage
         │
         ├─ executeToolCalls()
         │    └─► ToolResultMessage[]
         │
         └─► Vector{AgentMessage} (final conversation)

Key Data Flow Patterns

  1. Message Transformation: AgentMessage[] → Message[] via convertToLlm()

    • UserMessage → UserMessage (pass-through)
    • AssistantMessage → AssistantMessage (pass-through)
    • ToolResultMessage → ToolResultMessage (pass-through)
    • Custom messages (Bash, Compaction, Branch) → UserMessage
  2. Tool Execution: ToolCall → ToolResultMessage

    • prepareToolCall() validates and prepares
    • execute() runs the tool
    • finalize() applies hooks and returns outcome
    • createToolResultMessage() creates result entry
  3. Event Streaming: Stream{Event} with lifecycle events

    • AgentStartEvent, TurnStartEvent
    • MessageStartEvent, MessageUpdateEvent, MessageEndEvent
    • ToolExecutionStartEvent, ToolExecutionEndEvent
    • TurnEndEvent, AgentEndEvent

Each layer transforms data and passes it to the next layer, with clear interfaces and event hooks for customization.