update
This commit is contained in:
@@ -405,87 +405,295 @@
|
||||
└── Manages ──► PromptTemplates
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
## Data Flow with Type Transformations
|
||||
|
||||
### Complete User Input → Conversation History Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ Data Flow Between Layers │
|
||||
│ 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 │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
User Input (String/Message)
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ transform_context() (optional hook) │
|
||||
│ │
|
||||
│ Input: Vector{AgentMessage} │
|
||||
│ Output: Vector{AgentMessage} (transformed) │
|
||||
│ - Can truncate, filter, or modify messages │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ Agent.prompt() │
|
||||
│ - normalizeInput() │
|
||||
└──────────────────────┘
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ 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) │
|
||||
└────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ AgentState.messages │ ──► AgentMessage[]
|
||||
└──────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ Context for LLM API │
|
||||
│ - system_prompt: String │
|
||||
│ - messages: Vector{Message} │
|
||||
│ - tools: Vector{AgentTool} │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ AgentLoop │
|
||||
│ - transform_context │
|
||||
└──────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ 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 │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ convertToLlm() │ ──► Transforms AgentMessage[] to Message[]
|
||||
└──────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ 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)
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ LLM API (StreamFn) │
|
||||
│ - Context: Message[] │
|
||||
└──────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ executeToolCalls() - Tool Processing │
|
||||
│ │
|
||||
│ Extract: filter(c -> c isa ToolCall, assistant.content) │
|
||||
│ Output: ExecutedToolCallBatch │
|
||||
│ • messages: Vector{ToolResultMessage} │
|
||||
│ • terminate: Bool │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ Response (Streaming) │
|
||||
│ - Text deltas │
|
||||
│ - Tool call deltas │
|
||||
└──────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ 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)
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ AssistantMessage │
|
||||
│ - content: Message[] │
|
||||
└──────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ Updated AgentState.messages (AgentMessage[]) │
|
||||
│ │
|
||||
│ Conversation History: │
|
||||
│ [UserMessage, AssistantMessage, ToolResultMessage, ...] │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ Level 3: Session Storage (optional, for persistence) │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
AgentState.messages (Vector{AgentMessage})
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ AgentState.messages │ ──► Appended to conversation
|
||||
└──────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ 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) │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ Tool Execution │
|
||||
│ - Extract ToolCalls │
|
||||
│ - Execute tools │
|
||||
└──────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ ToolResultMessage[] │
|
||||
└──────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ AgentState.messages │ ──► Tool results appended
|
||||
└──────────────────────┘
|
||||
│
|
||||
│ (Loop back to LLM or end)
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ Session Storage │
|
||||
│ - JSONL format │
|
||||
│ - Tree entries │
|
||||
└──────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ 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:
|
||||
@@ -495,4 +703,48 @@ The AgentCore.jl architecture follows a clean separation of concerns:
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user