Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0787c2316 | |||
| 8fd72f8d37 |
+74
-74
@@ -22,9 +22,9 @@
|
|||||||
│ 2. AGENT LOOP START (runAgentLoop) │
|
│ 2. AGENT LOOP START (runAgentLoop) │
|
||||||
│ │
|
│ │
|
||||||
│ new_messages = copy(prompts) │
|
│ new_messages = copy(prompts) │
|
||||||
│ current_context.messages = vcat(context.messages, copy(prompts)) │
|
│ current_context.messages = vcat(context.messages, copy(prompts)) │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ └─→ User messages are IMMEDIATELY added to context.messages │
|
│ └─→ User messages are IMMEDIATELY added to context.messages │
|
||||||
│ (They are NOT in the steering queue!) │
|
│ (They are NOT in the steering queue!) │
|
||||||
│ │
|
│ │
|
||||||
│ emit(AgentStartEvent) │
|
│ emit(AgentStartEvent) │
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
│ │
|
│ │
|
||||||
│ pending_messages = get_steering_messages() │
|
│ pending_messages = get_steering_messages() │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ └─→ Steering queue: messages from agent.steer() │
|
│ └─→ Steering queue: messages from agent.steer() │
|
||||||
│ These are for CONTINUING conversation (NOT new user prompts) │
|
│ These are for CONTINUING conversation (NOT new user prompts) │
|
||||||
│ │
|
│ │
|
||||||
│ ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
│ ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||||
@@ -51,17 +51,17 @@
|
|||||||
│ │ ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ │
|
│ │ ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ │
|
||||||
│ │ │ 4. PENDING MESSAGE HANDLING (steering messages only) │ │ │
|
│ │ │ 4. PENDING MESSAGE HANDLING (steering messages only) │ │ │
|
||||||
│ │ │ │ │ │
|
│ │ │ │ │ │
|
||||||
│ │ │ pending_messages = get_steering() │ │ │
|
│ │ │ pending_messages = get_steering() │ │ │
|
||||||
│ │ │ if !isempty(pending_messages): │ │ │
|
│ │ │ if !isempty(pending_messages): │ │ │
|
||||||
│ │ │ for msg in pending_messages: │ │ │
|
│ │ │ for msg in pending_messages: │ │ │
|
||||||
│ │ │ emit(MessageStartEvent(msg)) │ │ │
|
│ │ │ emit(MessageStartEvent(msg)) │ │ │
|
||||||
│ │ │ emit(MessageEndEvent(msg)) │ │ │
|
│ │ │ emit(MessageEndEvent(msg)) │ │ │
|
||||||
│ │ │ push to current_context.messages ← Steering messages go HERE │ │ │
|
│ │ │ push to current_context.messages ← Steering messages go HERE │ │ │
|
||||||
│ │ │ push to new_messages │ │ │
|
│ │ │ push to new_messages │ │ │
|
||||||
│ │ │ pending_messages = [] │ │ │
|
│ │ │ pending_messages = [] │ │ │
|
||||||
│ │ │ │ │ │
|
│ │ │ │ │ │
|
||||||
│ │ │ Note: User messages from Agent.prompt() are ALREADY in context.messages │ │ │
|
│ │ │ Note: User messages from Agent.prompt() are ALREADY in context.messages │ │ │
|
||||||
│ │ │ (They were added in runAgentLoop via vcat(), not via this queue) │ │ │
|
│ │ │ (They were added in runAgentLoop via vcat(), not via this queue) │ │ │
|
||||||
│ │ └─────────────────────────────────────────────────────────────────────────────────────────────────────┘ │ │
|
│ │ └─────────────────────────────────────────────────────────────────────────────────────────────────────┘ │ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ │ ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ │
|
│ │ ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ │
|
||||||
@@ -168,7 +168,7 @@
|
|||||||
│ new_messages = [UserMessage("What is Julia?")] │
|
│ new_messages = [UserMessage("What is Julia?")] │
|
||||||
│ current_context.messages = vcat([...existing...], [UserMessage("What is Julia?")]) │
|
│ current_context.messages = vcat([...existing...], [UserMessage("What is Julia?")]) │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ └─→ User message IMMEDIATELY added to context.messages (NOT via steering queue!) │
|
│ └─→ User message IMMEDIATELY added to context.messages (NOT via steering queue!) │
|
||||||
│ emit(AgentStartEvent), emit(TurnStartEvent) │
|
│ emit(AgentStartEvent), emit(TurnStartEvent) │
|
||||||
│ emit(MessageStart/End) for user message │
|
│ emit(MessageStart/End) for user message │
|
||||||
│ │
|
│ │
|
||||||
@@ -207,11 +207,11 @@
|
|||||||
│ │ follow_up_queue: [] │ │
|
│ │ follow_up_queue: [] │ │
|
||||||
│ └───────────────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
│ └───────────────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
│ LLM SEES (convert_to_llm() filters): │ │
|
│ LLM SEES (convert_to_llm() filters): │
|
||||||
│ ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ Messages passed to LLM API: │ │
|
│ │ Messages passed to LLM API: │ │
|
||||||
│ │ [UserMessage("What is Julia?"), AssistantMessage("Julia is...")] │ │
|
│ │ [UserMessage("What is Julia?"), AssistantMessage("Julia is...")] │ │
|
||||||
│ └─────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
│ └─────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
│ TURN #2: User asks "How does it work?" │
|
│ TURN #2: User asks "How does it work?" │
|
||||||
│ ───────────────────────────────────────── │
|
│ ───────────────────────────────────────── │
|
||||||
@@ -223,7 +223,7 @@
|
|||||||
│ new_messages = [UserMessage("How does it work?")] │
|
│ new_messages = [UserMessage("How does it work?")] │
|
||||||
│ current_context.messages = vcat([...previous..., UserMessage("How does it work?")]) │
|
│ current_context.messages = vcat([...previous..., UserMessage("How does it work?")]) │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ └─→ User message added (context preserved from Turn #1) │
|
│ └─→ User message added (context preserved from Turn #1) │
|
||||||
│ emit(AgentStartEvent), emit(TurnStartEvent) │
|
│ emit(AgentStartEvent), emit(TurnStartEvent) │
|
||||||
│ emit(MessageStart/End) for user message │
|
│ emit(MessageStart/End) for user message │
|
||||||
│ │
|
│ │
|
||||||
@@ -245,13 +245,13 @@
|
|||||||
│ └───────────────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
│ └───────────────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
│ LLM SEES: │
|
│ LLM SEES: │
|
||||||
│ ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ Messages passed to LLM API: │ │
|
│ │ Messages passed to LLM API: │ │
|
||||||
│ │ [UserMessage("What is Julia?"), │ │
|
│ │ [UserMessage("What is Julia?"), │ │
|
||||||
│ │ AssistantMessage("Julia is..."), │ │
|
│ │ AssistantMessage("Julia is..."), │ │
|
||||||
│ │ UserMessage("How does it work?"), │ │
|
│ │ UserMessage("How does it work?"), │ │
|
||||||
│ │ AssistantMessage("It works by...")] │ │
|
│ │ AssistantMessage("It works by...")] │ │
|
||||||
│ └─────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
│ └─────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
@@ -261,83 +261,83 @@
|
|||||||
│ │
|
│ │
|
||||||
│ What is a steering message? │
|
│ What is a steering message? │
|
||||||
│ • A message (any AgentMessage type) injected via: `agent.steer(message)` │
|
│ • A message (any AgentMessage type) injected via: `agent.steer(message)` │
|
||||||
│ • Goes into the steering queue, not immediately to context.messages │
|
│ • Goes into the steering queue, not immediately to context.messages │
|
||||||
│ │
|
│ │
|
||||||
│ How is it created? │
|
│ How is it created? │
|
||||||
│ • User code calls: agent.steer(UserMessage("...")) │
|
│ • User code calls: agent.steer(UserMessage("...")) │
|
||||||
│ • Or: agent.steer(AssistantMessage("...")) │
|
│ • Or: agent.steer(AssistantMessage("...")) │
|
||||||
│ • Or any other AgentMessage subtype │
|
│ • Or any other AgentMessage subtype │
|
||||||
│ │
|
│ │
|
||||||
│ When is it processed? │
|
│ When is it processed? │
|
||||||
│ • At the START of the next loop iteration (line 194-202 in agent_loop.jl) │
|
│ • At the START of the next loop iteration (line 194-202 in agent_loop.jl) │
|
||||||
│ • AFTER the previous assistant turn completes │
|
│ • AFTER the previous assistant turn completes │
|
||||||
│ • BEFORE the next assistant response is streamed │
|
│ • BEFORE the next assistant response is streamed │
|
||||||
│ │
|
│ │
|
||||||
│ Why use steering? │
|
│ Why use steering? │
|
||||||
│ Use case 1: Tool execution result injection │
|
│ Use case 1: Tool execution result injection │
|
||||||
│ - Agent calls a tool (e.g., read_file, bash) │
|
│ - Agent calls a tool (e.g., read_file, bash) │
|
||||||
│ - Tool returns result │
|
│ - Tool returns result │
|
||||||
│ - You want to inject a follow-up question based on the result │
|
│ - You want to inject a follow-up question based on the result │
|
||||||
│ - agent.steer(UserMessage("Based on the file, what should we do next?")) │
|
│ - agent.steer(UserMessage("Based on the file, what should we do next?")) │
|
||||||
│ │
|
│ │
|
||||||
│ Use case 2: Multi-turn conversation without user input │
|
│ Use case 2: Multi-turn conversation without user input │
|
||||||
│ - Agent responds to user │
|
│ - Agent responds to user │
|
||||||
│ - Before user types again, you want to inject a system message │
|
│ - Before user types again, you want to inject a system message │
|
||||||
│ - agent.steer(BashExecutionMessage(...)) or custom message │
|
│ - agent.steer(BashExecutionMessage(...)) or custom message │
|
||||||
│ - This continues the conversation automatically │
|
│ - This continues the conversation automatically │
|
||||||
│ │
|
│ │
|
||||||
│ Use case 3: Branch navigation recovery │
|
│ Use case 3: Branch navigation recovery │
|
||||||
│ - User navigates between conversation branches │
|
│ - User navigates between conversation branches │
|
||||||
│ - After switching branches, you want to inject a context message │
|
│ - After switching branches, you want to inject a context message │
|
||||||
│ - agent.steer(BranchSummaryMessage(...)) │
|
│ - agent.steer(BranchSummaryMessage(...)) │
|
||||||
│ - The agent can then continue from the new branch context │
|
│ - The agent can then continue from the new branch context │
|
||||||
│ │
|
│ │
|
||||||
│ Use case 4: Compaction summary injection │
|
│ Use case 4: Compaction summary injection │
|
||||||
│ - Conversation history is compacted │
|
│ - Conversation history is compacted │
|
||||||
│ - After compaction, inject summary message │
|
│ - After compaction, inject summary message │
|
||||||
│ - agent.steer(CompactionSummaryMessage(...)) │
|
│ - agent.steer(CompactionSummaryMessage(...)) │
|
||||||
│ - Agent knows old history was summarized │
|
│ - Agent knows old history was summarized │
|
||||||
│ │
|
│ │
|
||||||
│ Example: │
|
│ Example: │
|
||||||
│ agent.steer(UserMessage("Follow-up question here")) │
|
│ agent.steer(UserMessage("Follow-up question here")) │
|
||||||
│ # This will be processed in the next loop iteration, │
|
│ # This will be processed in the next loop iteration, │
|
||||||
│ # appearing in context.messages before the next LLM call │
|
│ # appearing in context.messages before the next LLM call │
|
||||||
│ │
|
│ │
|
||||||
│ The LLM sees: │
|
│ The LLM sees: │
|
||||||
│ ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ All messages become Message[] via convert_to_llm(): │ │
|
│ │ All messages become Message[] via convert_to_llm(): │ │
|
||||||
│ │ [UserMessage(...), AssistantMessage(...), UserMessage(from_steer), ...] │ │
|
│ │ [UserMessage(...), AssistantMessage(...), UserMessage(from_steer), ...] │ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ │ The LLM cannot tell which came from Agent.prompt() vs agent.steer() │ │
|
│ │ The LLM cannot tell which came from Agent.prompt() vs agent.steer() │ │
|
||||||
│ └─────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
│ └─────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ LLM PROCESSING: How LLM sees messages │
|
│ LLM PROCESSING: How LLM sees messages │
|
||||||
├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||||
│ │
|
│ │
|
||||||
│ The LLM NEVER sees "user message" vs "steering message" - it only sees Message types: │
|
│ The LLM NEVER sees "user message" vs "steering message" - it only sees Message types: │
|
||||||
│ │
|
│ │
|
||||||
│ ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ convert_to_llm() transforms ALL AgentMessages to Message[]: │ │
|
│ │ convert_to_llm() transforms ALL AgentMessages to Message[]: │ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ │ UserMessage("user") → UserMessage (for LLM) │ │
|
│ │ UserMessage("user") → UserMessage (for LLM) │ │
|
||||||
│ │ Steering UserMessage("user") → UserMessage (for LLM) ← Same! │ │
|
│ │ Steering UserMessage("user") → UserMessage (for LLM) ← Same! │ │
|
||||||
│ │ AssistantMessage("assistant") → AssistantMessage (for LLM) │ │
|
│ │ AssistantMessage("assistant") → AssistantMessage (for LLM) │ │
|
||||||
│ │ ToolResultMessage("toolResult") → ToolResultMessage (for LLM) │ │
|
│ │ ToolResultMessage("toolResult") → ToolResultMessage (for LLM) │ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ │ BranchSummaryMessage → UserMessage (wrapped in summary tags) │ │
|
│ │ BranchSummaryMessage → UserMessage (wrapped in summary tags) │ │
|
||||||
│ │ CompactionSummaryMessage → UserMessage (wrapped in summary tags) │ │
|
│ │ CompactionSummaryMessage → UserMessage (wrapped in summary tags) │ │
|
||||||
│ │ BashExecutionMessage → UserMessage (if not excluded) │ │
|
│ │ BashExecutionMessage → UserMessage (if not excluded) │ │
|
||||||
│ │ CustomMessage → UserMessage │ │
|
│ │ CustomMessage → UserMessage │ │
|
||||||
│ └─────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
│ └─────────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
│ The difference is ONLY in HOW messages enter the system: │
|
│ The difference is ONLY in HOW messages enter the system: │
|
||||||
│ • User messages: Agent.prompt() → vcat() → context.messages (direct) │
|
│ • User messages: Agent.prompt() → vcat() → context.messages (direct) │
|
||||||
│ • Steering: agent.steer() → queue → loop → context.messages (indirect) │
|
│ • Steering: agent.steer() → queue → loop → context.messages (indirect) │
|
||||||
│ │
|
│ │
|
||||||
│ At LLM level: BOTH become UserMessage in the conversation! │
|
│ At LLM level: BOTH become UserMessage in the conversation! │
|
||||||
│ │
|
│ │
|
||||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
@@ -347,13 +347,13 @@
|
|||||||
│ │
|
│ │
|
||||||
│ 1. User prompts go DIRECTLY to context.messages via vcat() in runAgentLoop() │
|
│ 1. User prompts go DIRECTLY to context.messages via vcat() in runAgentLoop() │
|
||||||
│ │
|
│ │
|
||||||
│ 2. Steering queue is for messages injected via agent.steer() AFTER a turn finishes │
|
│ 2. Steering queue is for messages injected via agent.steer() AFTER a turn finishes │
|
||||||
│ This allows continuing conversation without calling Agent.prompt() again │
|
│ This allows continuing conversation without calling Agent.prompt() again │
|
||||||
│ │
|
│ │
|
||||||
│ 3. Context is preserved across turns - context.messages grows with each turn │
|
│ 3. Context is preserved across turns - context.messages grows with each turn │
|
||||||
│ LLM sees the full conversation history │
|
│ LLM sees the full conversation history │
|
||||||
│ │
|
│ │
|
||||||
│ 4. At LLM level, ALL messages become Message types (UserMessage/AssistantMessage/ToolResultMessage) │
|
│ 4. At LLM level, ALL messages become Message types (UserMessage/AssistantMessage/ToolResultMessage) │
|
||||||
│ The "steering" vs "user" distinction is just a control mechanism, not a message type │
|
│ The "steering" vs "user" distinction is just a control mechanism, not a message type │
|
||||||
│ │
|
│ │
|
||||||
│ 5. New turn is triggered by: │
|
│ 5. New turn is triggered by: │
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────┐
|
||||||
│ Agent Lifecycle │
|
│ Agent Lifecycle │
|
||||||
└─────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
User Code
|
User Code
|
||||||
@@ -83,20 +83,20 @@
|
|||||||
▼
|
▼
|
||||||
┌──────────────────────────────────────────────────────────────┐
|
┌──────────────────────────────────────────────────────────────┐
|
||||||
│ AgentLoop (runs in separate thread) │
|
│ AgentLoop (runs in separate thread) │
|
||||||
│ │
|
│ │
|
||||||
│ ┌────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────┐ │
|
||||||
│ │ 1. Emit AgentStartEvent │ │
|
│ │ 1. Emit AgentStartEvent │ │
|
||||||
│ │ 2. Emit TurnStartEvent │ │
|
│ │ 2. Emit TurnStartEvent │ │
|
||||||
│ │ 3. Process prompts (emit MessageStart/End) │ │
|
│ │ 3. Process prompts (emit MessageStart/End) │ │
|
||||||
│ │ 4. ┌──────────────────────────────────────────────┐ │ │
|
│ │ 4.┌────────────────────────────────────────────────┐ │ │
|
||||||
│ │ │ while true: │ │ │
|
│ │ │ while true: │ │ │
|
||||||
│ │ │ │ Process steering/follow-up messages │ │ │
|
│ │ │ │ Process steering/follow-up messages │ │ │
|
||||||
│ │ │ │ Stream assistant response (LLM call) │ │ │
|
│ │ │ │ Stream assistant response (LLM call) │ │ │
|
||||||
│ │ │ │ Execute tool calls (parallel/sequential) │ │ │
|
│ │ │ │ Execute tool calls (parallel/sequential) │ │ │
|
||||||
│ │ │ │ Emit TurnEndEvent │ │ │
|
│ │ │ │ Emit TurnEndEvent │ │ │
|
||||||
│ │ │ │ Check if should stop │ │ │
|
│ │ │ │ Check if should stop │ │ │
|
||||||
│ │ │ │ Get next steering messages │ │ │
|
│ │ │ │ Get next steering messages │ │ │
|
||||||
│ │ └───┴────────────────────────────────────────────┘ │ │
|
│ │ └───┴────────────────────────────────────────────┘ │ │
|
||||||
│ └────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────┘ │
|
||||||
└──────────────────────────────────────────────────────────────┘
|
└──────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
@@ -125,18 +125,18 @@
|
|||||||
│ ┌────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ agentLoop(prompts, context, config, signal, stream_fn) │ │
|
│ │ agentLoop(prompts, context, config, signal, stream_fn) │ │
|
||||||
│ └────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ runAgentLoop(prompts, context, config, emit, signal) │ │
|
│ │ runAgentLoop(prompts, context, config, emit, signal) │ │
|
||||||
│ └────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ runLoop() - Main Event Loop │ │
|
│ │ runLoop() - Main Event Loop │ │
|
||||||
│ └────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
└──────────────────────────────┼───────────────────────────────────────┘
|
└──────────────────────────────┼─────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
│ Loop Iteration
|
│ Loop Iteration
|
||||||
▼
|
▼
|
||||||
@@ -150,8 +150,8 @@
|
|||||||
│ │ │ (after assistant) │ │ (after stop) │ │ │
|
│ │ │ (after assistant) │ │ (after stop) │ │ │
|
||||||
│ │ └────────────────────┘ └──────────────────────┘ │ │
|
│ │ └────────────────────┘ └──────────────────────┘ │ │
|
||||||
│ └────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ 2. Stream Assistant Response │ │
|
│ │ 2. Stream Assistant Response │ │
|
||||||
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
||||||
@@ -161,39 +161,39 @@
|
|||||||
│ │ │ - Text deltas │ │ │
|
│ │ │ - Text deltas │ │ │
|
||||||
│ │ │ - Tool call deltas │ │ │
|
│ │ │ - Tool call deltas │ │ │
|
||||||
│ │ └────────────────────────────────────────────────────┘ │ │
|
│ │ └────────────────────────────────────────────────────┘ │ │
|
||||||
│ │ │ │ │
|
│ │ │ │ │
|
||||||
│ │ ▼ │ │
|
│ │ ▼ │ │
|
||||||
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
||||||
│ │ │ Emit: MessageStartEvent, MessageUpdateEvent, │ │ │
|
│ │ │ Emit: MessageStartEvent, MessageUpdateEvent, │ │ │
|
||||||
│ │ │ MessageEndEvent │ │ │
|
│ │ │ MessageEndEvent │ │ │
|
||||||
│ │ └────────────────────────────────────────────────────┘ │ │
|
│ │ └────────────────────────────────────────────────────┘ │ │
|
||||||
│ └────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ 3. Execute Tool Calls │ │
|
│ │ 3. Execute Tool Calls │ │
|
||||||
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
||||||
│ │ │ extract ToolCall from assistant content │ │ │
|
│ │ │ extract ToolCall from assistant content │ │ │
|
||||||
│ │ │ │ │ │
|
│ │ │ │ │ │
|
||||||
│ │ │ if EXECUTION_SEQUENTIAL || has_sequential_tool: │ │ │
|
│ │ │ if EXECUTION_SEQUENTIAL || has_sequential_tool: │ │ │
|
||||||
│ │ │ executeToolCallsSequential() │ │ │
|
│ │ │ executeToolCallsSequential() │ │ │
|
||||||
│ │ │ else: │ │ │
|
│ │ │ else: │ │ │
|
||||||
│ │ │ executeToolCallsParallel() │ │ │
|
│ │ │ executeToolCallsParallel() │ │ │
|
||||||
│ │ └────────────────────────────────────────────────────┘ │ │
|
│ │ └────────────────────────────────────────────────────┘ │ │
|
||||||
│ │ │ │ │
|
│ │ │ │ │
|
||||||
│ │ ▼ │ │
|
│ │ ▼ │ │
|
||||||
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
||||||
│ │ │ For each tool call: │ │ │
|
│ │ │ For each tool call: │ │ │
|
||||||
│ │ │ 1. before_tool_call hook │ │ │
|
│ │ │ 1. before_tool_call hook │ │ │
|
||||||
│ │ │ 2. prepareToolCall() │ │ │
|
│ │ │ 2. prepareToolCall() │ │ │
|
||||||
│ │ │ 3. execute() │ │ │
|
│ │ │ 3. execute() │ │ │
|
||||||
│ │ │ 4. after_tool_call hook │ │ │
|
│ │ │ 4. after_tool_call hook │ │ │
|
||||||
│ │ │ 5. Emit ToolExecutionStart/Update/EndEvent │ │ │
|
│ │ │ 5. Emit ToolExecutionStart/Update/EndEvent │ │ │
|
||||||
│ │ │ 6. Emit ToolResultMessage │ │ │
|
│ │ │ 6. Emit ToolResultMessage │ │ │
|
||||||
│ │ └────────────────────────────────────────────────────┘ │ │
|
│ │ └────────────────────────────────────────────────────┘ │ │
|
||||||
│ └────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ 4. Prepare Next Turn │ │
|
│ │ 4. Prepare Next Turn │ │
|
||||||
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
||||||
@@ -202,29 +202,29 @@
|
|||||||
│ │ │ - Optional: Update context │ │ │
|
│ │ │ - Optional: Update context │ │ │
|
||||||
│ │ └────────────────────────────────────────────────────┘ │ │
|
│ │ └────────────────────────────────────────────────────┘ │ │
|
||||||
│ └────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ 5. Check Termination Conditions │ │
|
│ │ 5. Check Termination Conditions │ │
|
||||||
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
│ │ ┌────────────────────────────────────────────────────┐ │ │
|
||||||
│ │ │ should_stop_after_turn(context) -> bool │ │ │
|
│ │ │ should_stop_after_turn(context) -> bool │ │ │
|
||||||
│ │ │ - Max turns reached? │ │ │
|
│ │ │ - Max turns reached? │ │ │
|
||||||
│ │ │ - Tool returned terminate=true? │ │ │
|
│ │ │ - Tool returned terminate=true? │ │ │
|
||||||
│ │ │ - Steering queue empty and follow-up empty? │ │ │
|
│ │ │ - Steering queue empty and follow-up empty? │ │ │
|
||||||
│ │ └────────────────────────────────────────────────────┘ │ │
|
│ │ └────────────────────────────────────────────────────┘ │ │
|
||||||
│ └────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ 6. Emit TurnEndEvent (message, tool_results) │ │
|
│ │ 6. Emit TurnEndEvent (message, tool_results) │ │
|
||||||
│ └────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ Loop continues until termination condition met │ │
|
│ │ Loop continues until termination condition met │ │
|
||||||
│ └────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
└──────────────────────────────┼───────────────────────────────────────┘
|
└──────────────────────────────┼─────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌────────────────────────────────────────────────────────────────────┐
|
┌────────────────────────────────────────────────────────────────────┐
|
||||||
@@ -240,34 +240,34 @@
|
|||||||
└─────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌───────────────────────────────────────────────────────────────────┐
|
┌───────────────────────────────────────────────────────────────────┐
|
||||||
│ Assistant Message with Tool Calls │
|
│ Assistant Message with Tool Calls │
|
||||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ AssistantMessage: │ │
|
│ │ AssistantMessage: │ │
|
||||||
│ │ content: [ │ │
|
│ │ content: [ │ │
|
||||||
│ │ TextContent("I'll help you"), │ │
|
│ │ TextContent("I'll help you"), │ │
|
||||||
│ │ ToolCall(id="tc1", name="bash", args={...}), │ │
|
│ │ ToolCall(id="tc1", name="bash", args={...}), │ │
|
||||||
│ │ ToolCall(id="tc2", name="read", args={...}) │ │
|
│ │ ToolCall(id="tc2", name="read", args={...}) │ │
|
||||||
│ │ ] │ │
|
│ │ ] │ │
|
||||||
│ └─────────────────────────────────────────────────────────────┘ │
|
│ └─────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
└───────────────────────────────────────────────────────────────────┘
|
└───────────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
│ executeToolCalls()
|
│ executeToolCalls()
|
||||||
▼
|
▼
|
||||||
┌───────────────────────────────────────────────────────────────────┐
|
┌───────────────────────────────────────────────────────────────────┐
|
||||||
│ Determine Execution Mode │
|
│ Determine Execution Mode │
|
||||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ config.tool_execution == EXECUTION_SEQUENTIAL? │ │
|
│ │ config.tool_execution == EXECUTION_SEQUENTIAL? │ │
|
||||||
│ │ OR any tool has execution_mode == EXECUTION_SEQUENTIAL? │ │
|
│ │ OR any tool has execution_mode == EXECUTION_SEQUENTIAL? │ │
|
||||||
│ └─────────────────────────────────────────────────────────────┘ │
|
│ └─────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ┌───────────────┴───────────────┐ │
|
│ ┌───────────────┴───────────────┐ │
|
||||||
│ ▼ ▼ │
|
│ ▼ ▼ │
|
||||||
│ ┌────────────────────────┐ ┌────────────────────────┐ │
|
│ ┌────────────────────────┐ ┌────────────────────────┐ │
|
||||||
│ │ executeSequential() │ │ executeParallel() │ │
|
│ │ executeSequential() │ │ executeParallel() │ │
|
||||||
│ └────────────────────────┘ └────────────────────────┘ │
|
│ └────────────────────────┘ └────────────────────────┘ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
└──────────────┼───────────────────────────────┼────────────────────┘
|
└──────────────┼───────────────────────────────┼────────────────────┘
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
@@ -285,7 +285,7 @@
|
|||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌───────────────────────────────────────────────────────────────────┐
|
┌───────────────────────────────────────────────────────────────────┐
|
||||||
│ For Each Tool Call │
|
│ For Each Tool Call │
|
||||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ 1. before_tool_call hook (optional) │ │
|
│ │ 1. before_tool_call hook (optional) │ │
|
||||||
│ │ - Can block execution │ │
|
│ │ - Can block execution │ │
|
||||||
@@ -293,20 +293,20 @@
|
|||||||
│ │ - validateToolArguments() │ │
|
│ │ - validateToolArguments() │ │
|
||||||
│ │ - prepareToolCallArguments() (optional) │ │
|
│ │ - prepareToolCallArguments() (optional) │ │
|
||||||
│ │ 3. Execute Tool: │ │
|
│ │ 3. Execute Tool: │ │
|
||||||
│ │ tool.execute(tool_call_id, args, signal, on_update) │ │
|
│ │ tool.execute(tool_call_id, args, signal, on_update) │ │
|
||||||
│ │ 4. after_tool_call hook (optional) │ │
|
│ │ 4. after_tool_call hook (optional) │ │
|
||||||
│ │ - Can modify result content │ │
|
│ │ - Can modify result content │ │
|
||||||
│ │ 5. Emit events: │ │
|
│ │ 5. Emit events: │ │
|
||||||
│ │ - ToolExecutionStartEvent │ │
|
│ │ - ToolExecutionStartEvent │ │
|
||||||
│ │ - ToolExecutionUpdateEvent (optional) │ │
|
│ │ - ToolExecutionUpdateEvent (optional) │ │
|
||||||
│ │ - ToolExecutionEndEvent │ │
|
│ │ - ToolExecutionEndEvent │ │
|
||||||
│ │ 6. Create ToolResultMessage │ │
|
│ │ 6. Create ToolResultMessage │ │
|
||||||
│ └─────────────────────────────────────────────────────────────┘ │
|
│ └─────────────────────────────────────────────────────────────┘ │
|
||||||
└───────────────────────────────────────────────────────────────────┘
|
└───────────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌───────────────────────────────────────────────────────────────────┐
|
┌───────────────────────────────────────────────────────────────────┐
|
||||||
│ Tool Result Messages │
|
│ Tool Result Messages │
|
||||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ ToolResultMessage: │ │
|
│ │ ToolResultMessage: │ │
|
||||||
│ │ role: "toolResult" │ │
|
│ │ role: "toolResult" │ │
|
||||||
@@ -329,47 +329,47 @@
|
|||||||
|
|
||||||
┌───────────────────────────────────────────────────────────────────┐
|
┌───────────────────────────────────────────────────────────────────┐
|
||||||
│ Branch Navigation │
|
│ Branch Navigation │
|
||||||
│ │
|
│ │
|
||||||
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
|
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
|
||||||
│ │ E1 │────▶│ E2 │────▶│ E3 │────▶│ E4 │────▶│ E5 │ (leaf) │
|
│ │ E1 │────▶│ E2 │────▶│ E3 │────▶│ E4 │────▶│ E5 │ (leaf) │
|
||||||
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
|
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
|
||||||
│ │ │ │ │ │ │
|
│ │ │ │ │ │ │
|
||||||
│ ▼ ▼ ▼ ▼ ▼ │
|
│ ▼ ▼ ▼ ▼ ▼ │
|
||||||
│ Message Message Compaction Message BranchSummary │
|
│ Message Message Compaction Message BranchSummary │
|
||||||
│ │
|
│ │
|
||||||
│ E3 is a Compaction Entry: │
|
│ E3 is a Compaction Entry: │
|
||||||
│ - Summary of E1, E2 │
|
│ - Summary of E1, E2 │
|
||||||
│ - first_kept_entry_id: reference to first retained message │
|
│ - first_kept_entry_id: reference to first retained message │
|
||||||
│ - tokens_before: context size before compaction │
|
│ - tokens_before: context size before compaction │
|
||||||
│ │
|
│ │
|
||||||
│ E5 is a BranchSummary Entry: │
|
│ E5 is a BranchSummary Entry: │
|
||||||
│ - Summary of branch from from_id │
|
│ - Summary of branch from from_id │
|
||||||
│ - Represents a fork point in conversation history │
|
│ - Represents a fork point in conversation history │
|
||||||
│ │
|
│ │
|
||||||
└───────────────────────────────────────────────────────────────────┘
|
└───────────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
│ Session.moveTo()
|
│ Session.moveTo()
|
||||||
▼
|
▼
|
||||||
┌───────────────────────────────────────────────────────────────────┐
|
┌───────────────────────────────────────────────────────────────────┐
|
||||||
│ Forking & Branching │
|
│ Forking & Branching │
|
||||||
│ │
|
│ │
|
||||||
│ Current branch: │
|
│ Current branch: │
|
||||||
│ ┌─────┐ ┌─────┐ ┌─────┐ │
|
│ ┌─────┐ ┌─────┐ ┌─────┐ │
|
||||||
│ │ E1 │────▶│ E2 │────▶│ E3 │ │
|
│ │ E1 │────▶│ E2 │────▶│ E3 │ │
|
||||||
│ └─────┘ └─────┘ └─────┘ │
|
│ └─────┘ └─────┘ └─────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ │ moveTo(E2) │
|
│ │ moveTo(E2) │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
|
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
|
||||||
│ │ E1 │────▶│ E2 │────▶│ E3' │────▶│ E4' │ (new branch) │
|
│ │ E1 │────▶│ E2 │────▶│ E3' │────▶│ E4' │ (new branch) │
|
||||||
│ └─────┘ └─────┘ └─────┘ └─────┘ │
|
│ └─────┘ └─────┘ └─────┘ └─────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ │ create BranchSummary │
|
│ │ create BranchSummary │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌─────┐ │
|
│ ┌─────┐ │
|
||||||
│ │ E5 │ (branch summary) │
|
│ │ E5 │ (branch summary) │
|
||||||
│ └─────┘ │
|
│ └─────┘ │
|
||||||
│ │
|
│ │
|
||||||
└───────────────────────────────────────────────────────────────────┘
|
└───────────────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -377,7 +377,7 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ Component Relationships │
|
│ Component Relationships │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
User Code
|
User Code
|
||||||
@@ -409,7 +409,7 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ Data Flow Between Layers │
|
│ Data Flow Between Layers │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
User Input (String/Message)
|
User Input (String/Message)
|
||||||
|
|||||||
@@ -403,9 +403,9 @@ Scenario: User sends message, agent responds with tool calls
|
|||||||
┌────────────────────────────────────────────────────────────┐
|
┌────────────────────────────────────────────────────────────┐
|
||||||
│ Time 2: User queues steering message │
|
│ Time 2: User queues steering message │
|
||||||
│ ┌──────────────────┐ │
|
│ ┌──────────────────┐ │
|
||||||
│ │ steer(msg2) │ ──► steering_queue.push(msg2) │
|
│ │ steer(msg2) │ ──► steering_queue.push(msg2) │
|
||||||
│ └──────────────────┘ │
|
│ └──────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
│ (msg2 not processed yet!) │
|
│ (msg2 not processed yet!) │
|
||||||
└────────────────────────────────────────────────────────────┘
|
└────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
@@ -413,9 +413,9 @@ Scenario: User sends message, agent responds with tool calls
|
|||||||
┌────────────────────────────────────────────────────────────┐
|
┌────────────────────────────────────────────────────────────┐
|
||||||
│ Time 3: Tool execution │
|
│ Time 3: Tool execution │
|
||||||
│ ┌──────────────────────────────────────────────────────┐ │
|
│ ┌──────────────────────────────────────────────────────┐ │
|
||||||
│ │ Execute bash tool... │ │
|
│ │ Execute bash tool... │ │
|
||||||
│ │ Execute read tool... │ │
|
│ │ Execute read tool... │ │
|
||||||
│ │ Emit ToolResultMessage[] │ │
|
│ │ Emit ToolResultMessage[] │ │
|
||||||
│ └──────────────────────────────────────────────────────┘ │
|
│ └──────────────────────────────────────────────────────┘ │
|
||||||
└────────────────────────────────────────────────────────────┘
|
└────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
|
|||||||
@@ -31,55 +31,55 @@ agentLoopContinue()
|
|||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ 1. runAgentLoop() ── Entry point for new conversation │
|
│ 1. runAgentLoop() ── Entry point for new conversation │
|
||||||
│ - Creates copy of prompts │
|
│ - Creates copy of prompts │
|
||||||
│ - Appends prompts to context.messages │
|
│ - Appends prompts to context.messages │
|
||||||
│ - Emits AgentStartEvent │
|
│ - Emits AgentStartEvent │
|
||||||
│ - Emits TurnStartEvent │
|
│ - Emits TurnStartEvent │
|
||||||
│ - Emits MessageStart/End for each prompt │
|
│ - Emits MessageStart/End for each prompt │
|
||||||
│ - Calls runLoop() │
|
│ - Calls runLoop() │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ 2. runLoop() ── Main event loop │
|
│ 2. runLoop() ── Main event loop │
|
||||||
│ ┌────────────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ while true: │ │
|
│ │ while true: │ │
|
||||||
│ │ 1. Get steering/follow-up messages (if any) │ │
|
│ │ 1. Get steering/follow-up messages (if any) │ │
|
||||||
│ │ 2. Emit messages as UserMessage │ │
|
│ │ 2. Emit messages as UserMessage │ │
|
||||||
│ │ 3. streamAssistantResponse() │ │
|
│ │ 3. streamAssistantResponse() │ │
|
||||||
│ │ 4. Execute tool calls (sequential or parallel) │ │
|
│ │ 4. Execute tool calls (sequential or parallel) │ │
|
||||||
│ │ 5. Emit TurnEndEvent │ │
|
│ │ 5. Emit TurnEndEvent │ │
|
||||||
│ │ 6. prepare_next_turn (optional) │ │
|
│ │ 6. prepare_next_turn (optional) │ │
|
||||||
│ │ 7. should_stop_after_turn? (check termination) │ │
|
│ │ 7. should_stop_after_turn? (check termination) │ │
|
||||||
│ │ 8. Loop continues if not terminated │ │
|
│ │ 8. Loop continues if not terminated │ │
|
||||||
│ └────────────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────────────┘ │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ 3. streamAssistantResponse() ── LLM interaction │
|
│ 3. streamAssistantResponse() ── LLM interaction │
|
||||||
│ - transform_context (optional) │
|
│ - transform_context (optional) │
|
||||||
│ - convert_to_llm (transform to Message[]) │
|
│ - convert_to_llm (transform to Message[]) │
|
||||||
│ - Call stream_fn (LLM API) │
|
│ - Call stream_fn (LLM API) │
|
||||||
│ - Stream response deltas │
|
│ - Stream response deltas │
|
||||||
│ - Emit MessageStart/Update/End events │
|
│ - Emit MessageStart/Update/End events │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ 4. executeToolCalls() ── Tool execution │
|
│ 4. executeToolCalls() ── Tool execution │
|
||||||
│ ┌────────────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ if EXECUTION_SEQUENTIAL || has_sequential_tool: │ │
|
│ │ if EXECUTION_SEQUENTIAL || has_sequential_tool: │ │
|
||||||
│ │ executeToolCallsSequential() │ │
|
│ │ executeToolCallsSequential() │ │
|
||||||
│ │ else: │ │
|
│ │ else: │ │
|
||||||
│ │ executeToolCallsParallel() │ │
|
│ │ executeToolCallsParallel() │ │
|
||||||
│ └────────────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────────────┘ │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ 5. AgentEndEvent ── Final event with all messages │
|
│ 5. AgentEndEvent ── Final event with all messages │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -520,13 +520,13 @@ ToolResultMessage(
|
|||||||
|
|
||||||
┌──────┐
|
┌──────┐
|
||||||
│ TC1 │ ──► prepareToolCall() ──► create closure ──► ┐
|
│ TC1 │ ──► prepareToolCall() ──► create closure ──► ┐
|
||||||
└──────┘ │
|
└──────┘ │
|
||||||
│
|
│
|
||||||
┌──────┐ │
|
┌──────┐ │
|
||||||
│ TC2 │ ──► prepareToolCall() ──► create closure ──► ├─► All closures queued
|
│ TC2 │ ──► prepareToolCall() ──► create closure ──► ├─► All closures queued
|
||||||
└──────┘ │
|
└──────┘ │
|
||||||
│
|
│
|
||||||
┌──────┐ │
|
┌──────┐ │
|
||||||
│ TC3 │ ──► prepareToolCall() ──► create closure ──► ┘
|
│ TC3 │ ──► prepareToolCall() ──► create closure ──► ┘
|
||||||
└──────┘
|
└──────┘
|
||||||
|
|
||||||
|
|||||||
@@ -19,80 +19,80 @@
|
|||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ ToolExecutionMode (Enum) │
|
│ ToolExecutionMode (Enum) │
|
||||||
│ - EXECUTION_SEQUENTIAL (Tools run one at a time) │
|
│ - EXECUTION_SEQUENTIAL (Tools run one at a time) │
|
||||||
│ - EXECUTION_PARALLEL (Tools run concurrently) │
|
│ - EXECUTION_PARALLEL (Tools run concurrently) │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ QueueMode (Enum) │
|
│ QueueMode (Enum) │
|
||||||
│ - QUEUE_ALL (Drain all messages at once) │
|
│ - QUEUE_ALL (Drain all messages at once) │
|
||||||
│ - QUEUE_ONE_AT_A_TIME (Process one message at a time) │
|
│ - QUEUE_ONE_AT_A_TIME (Process one message at a time) │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ MessageContent (Abstract Type) │
|
│ MessageContent (Abstract Type) │
|
||||||
│ ├── TextContent (String) │
|
│ ├── TextContent (String) │
|
||||||
│ └── ImageContent (data::String, mime_type::String) │
|
│ └── ImageContent (data::String, mime_type::String) │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ Message (Abstract Type) │
|
│ Message (Abstract Type) │
|
||||||
│ ├── UserMessage │
|
│ ├── UserMessage │
|
||||||
│ │ └─ role: "user", content: Message[], timestamp: Int64 │
|
│ │ └─ role: "user", content: Message[], timestamp: Int64 │
|
||||||
│ ├── AssistantMessage │
|
│ ├── AssistantMessage │
|
||||||
│ │ └─ role: "assistant", content: Message[], api, provider, model, │
|
│ │ └─ role: "assistant", content: Message[], api, provider, model, │
|
||||||
│ │ usage: Usage, stop_reason, error_message, timestamp │
|
│ │ usage: Usage, stop_reason, error_message, timestamp │
|
||||||
│ └── ToolResultMessage │
|
│ └── ToolResultMessage │
|
||||||
│ └─ role: "toolResult", tool_call_id, tool_name, content, details, │
|
│ └─ role: "toolResult", tool_call_id, tool_name, content, details, │
|
||||||
│ usage, added_tool_names, is_error, timestamp │
|
│ usage, added_tool_names, is_error, timestamp │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ AgentMessage (Abstract Type) │
|
│ AgentMessage (Abstract Type) │
|
||||||
│ └─ Union of all message types above + custom types │
|
│ └─ Union of all message types above + custom types │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ AgentTool │
|
│ AgentTool │
|
||||||
│ - name: String │
|
│ - name: String │
|
||||||
│ - label: String │
|
│ - label: String │
|
||||||
│ - description: String │
|
│ - description: String │
|
||||||
│ - parameters: Any │
|
│ - parameters: Any │
|
||||||
│ - execute: Function │
|
│ - execute: Function │
|
||||||
│ - prepare_arguments: Union{Function, Nothing} │
|
│ - prepare_arguments: Union{Function, Nothing} │
|
||||||
│ - execution_mode: Union{ToolExecutionMode, Nothing} │
|
│ - execution_mode: Union{ToolExecutionMode, Nothing} │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ AgentContext │
|
│ AgentContext │
|
||||||
│ - system_prompt: String │
|
│ - system_prompt: String │
|
||||||
│ - messages: Vector{AgentMessage} │
|
│ - messages: Vector{AgentMessage} │
|
||||||
│ - tools: Union{Vector{AgentTool}, Nothing} │
|
│ - tools: Union{Vector{AgentTool}, Nothing} │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ AgentEvent (Abstract Type) │
|
│ AgentEvent (Abstract Type) │
|
||||||
│ ├── AgentStartEvent / AgentEndEvent │
|
│ ├── AgentStartEvent / AgentEndEvent │
|
||||||
│ ├── TurnStartEvent / TurnEndEvent │
|
│ ├── TurnStartEvent / TurnEndEvent │
|
||||||
│ ├── MessageStartEvent / MessageEndEvent │
|
│ ├── MessageStartEvent / MessageEndEvent │
|
||||||
│ ├── MessageUpdateEvent │
|
│ ├── MessageUpdateEvent │
|
||||||
│ ├── ToolExecutionStartEvent / ToolExecutionEndEvent │
|
│ ├── ToolExecutionStartEvent / ToolExecutionEndEvent │
|
||||||
│ └── ToolExecutionUpdateEvent │
|
│ └── ToolExecutionUpdateEvent │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ Usage & ModelCost │
|
│ Usage & ModelCost │
|
||||||
│ Usage: input, output, cache_read, cache_write, total_tokens, cost │
|
│ Usage: input, output, cache_read, cache_write, total_tokens, cost │
|
||||||
│ ModelCost: input, output, cache_read, cache_write (all Float64) │
|
│ ModelCost: input, output, cache_read, cache_write (all Float64) │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ Model │
|
│ Model │
|
||||||
│ - id, name, api, provider, base_url, reasoning: Bool │
|
│ - id, name, api, provider, base_url, reasoning: Bool │
|
||||||
│ - input: Vector{String} │
|
│ - input: Vector{String} │
|
||||||
│ - cost: ModelCost │
|
│ - cost: ModelCost │
|
||||||
│ - context_window, max_tokens: Int64 │
|
│ - context_window, max_tokens: Int64 │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -9,23 +9,23 @@
|
|||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ Session = Tree of Entries │
|
│ Session = Tree of Entries │
|
||||||
│ │
|
│ │
|
||||||
│ Each entry represents a change in conversation state │
|
│ Each entry represents a change in conversation state │
|
||||||
│ │
|
│ │
|
||||||
│ Branch Navigation: │
|
│ Branch Navigation: │
|
||||||
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
|
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
|
||||||
│ │ E1 │────▶│ E2 │────▶│ E3 │────▶│ E4 │────▶│ E5 │ (current leaf) │
|
│ │ E1 │────▶│ E2 │────▶│ E3 │────▶│ E4 │────▶│ E5 │ (current leaf) │
|
||||||
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
|
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
|
||||||
│ │ │ │ │ │ │
|
│ │ │ │ │ │ │
|
||||||
│ ▼ ▼ ▼ ▼ ▼ │
|
│ ▼ ▼ ▼ ▼ ▼ │
|
||||||
│ Message Message Compaction Message BranchSummary │
|
│ Message Message Compaction Message BranchSummary │
|
||||||
│ │
|
│ │
|
||||||
│ To navigate to E2 (fork point): │
|
│ To navigate to E2 (fork point): │
|
||||||
│ Session.moveTo(E2) │
|
│ Session.moveTo(E2) │
|
||||||
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
|
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
|
||||||
│ │ E1 │────▶│ E2 │────▶│ E3' │────▶│ E4' │────▶│ E5' │ (new branch) │
|
│ │ E1 │────▶│ E2 │────▶│ E3' │────▶│ E4' │────▶│ E5' │ (new branch) │
|
||||||
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
|
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ │ ▼ create BranchSummary │
|
│ │ ▼ create BranchSummary │
|
||||||
│ │ ┌─────┐ │
|
│ │ ┌─────┐ │
|
||||||
│ └──────│ E6 │ (branch summary) │
|
│ └──────│ E6 │ (branch summary) │
|
||||||
|
|||||||
+12
-12
@@ -8,14 +8,14 @@
|
|||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ AgentTool │
|
│ AgentTool │
|
||||||
│ - name: String (identifier) │
|
│ - name: String (identifier) │
|
||||||
│ - label: String (display name) │
|
│ - label: String (display name) │
|
||||||
│ - description: String (what it does) │
|
│ - description: String (what it does) │
|
||||||
│ - parameters: JSON schema │
|
│ - parameters: JSON schema │
|
||||||
│ - execute::Function (main logic) │
|
│ - execute::Function (main logic) │
|
||||||
│ - prepare_arguments::Union{Function, Nothing} │
|
│ - prepare_arguments::Union{Function, Nothing} │
|
||||||
│ - execution_mode::Union{ToolExecutionMode, Nothing} │
|
│ - execution_mode::Union{ToolExecutionMode, Nothing} │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
┌───────────────┼───────────────┐
|
┌───────────────┼───────────────┐
|
||||||
@@ -47,8 +47,8 @@
|
|||||||
▼
|
▼
|
||||||
┌────────────────────────────────────────────────────────┐
|
┌────────────────────────────────────────────────────────┐
|
||||||
│ AgentLoop.executeToolCalls() │
|
│ AgentLoop.executeToolCalls() │
|
||||||
│ - Extract ToolCalls from message content │
|
│ - Extract ToolCalls from message content │
|
||||||
│ - Determine execution mode (sequential/parallel) │
|
│ - Determine execution mode (sequential/parallel) │
|
||||||
└────────────────────────────────────────────────────────┘
|
└────────────────────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
├─► executeToolCallsSequential()
|
├─► executeToolCallsSequential()
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
▼
|
▼
|
||||||
┌────────────────────────────────────────────────────────┐
|
┌────────────────────────────────────────────────────────┐
|
||||||
│ ToolResultMessage │
|
│ ToolResultMessage │
|
||||||
│ - tool_call_id: "ref to original ToolCall" │
|
│ - tool_call_id: "ref to original ToolCall" │
|
||||||
│ - tool_name: "bash" │
|
│ - tool_name: "bash" │
|
||||||
│ - content: [TextContent("file1.md\nfile2.md\n")] │
|
│ - content: [TextContent("file1.md\nfile2.md\n")] │
|
||||||
│ - is_error: false │
|
│ - is_error: false │
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌────────────────────────────────────────────────────────┐
|
┌────────────────────────────────────────────────────────┐
|
||||||
│ AgentState.messages.append(tool_result) │
|
│ AgentState.messages.append(tool_result) │
|
||||||
│ - Next turn: LLM sees tool results │
|
│ - Next turn: LLM sees tool results │
|
||||||
└────────────────────────────────────────────────────────┘
|
└────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|||||||
+16
-16
@@ -9,31 +9,31 @@
|
|||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
│ AgentHarness = Agent + Session + Resources │
|
│ AgentHarness = Agent + Session + Resources │
|
||||||
│ │
|
│ │
|
||||||
│ ┌───────────────────────────────────────────────────────────────────────┐ │
|
│ ┌───────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ AgentHarness │ │
|
│ │ AgentHarness │ │
|
||||||
│ │ - Manages Agent instances │ │
|
│ │ - Manages Agent instances │ │
|
||||||
│ │ - Provides Session persistence │ │
|
│ │ - Provides Session persistence │ │
|
||||||
│ │ - Manages resources (skills, prompt templates) │ │
|
│ │ - Manages resources (skills, prompt templates) │ │
|
||||||
│ │ - Handles extension hooks │ │
|
│ │ - Handles extension hooks │ │
|
||||||
│ │ - Coordinates tool execution with context │ │
|
│ │ - Coordinates tool execution with context │ │
|
||||||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ┌─────────────────────┼─────────────────────┐ │
|
│ ┌─────────────────────┼─────────────────────┐ │
|
||||||
│ ▼ ▼ ▼ │
|
│ ▼ ▼ ▼ │
|
||||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||||
│ │ Agent │ │ SessionRepo │ │ Resources │ │
|
│ │ Agent │ │ SessionRepo │ │ Resources │ │
|
||||||
│ │ (state, │ │ (create, │ │ (skills, │ │
|
│ │ (state, │ │ (create, │ │ (skills, │ │
|
||||||
│ │ events) │ │ open, │ │ templates) │ │
|
│ │ events) │ │ open, │ │ templates) │ │
|
||||||
│ └──────────────┘ │ list) │ └──────────────┘ │
|
│ └──────────────┘ │ list) │ └──────────────┘ │
|
||||||
│ └──────────────┘ │
|
│ └──────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ ┌──────────────┐ │
|
│ ┌──────────────┐ │
|
||||||
│ │ Session │ │
|
│ │ Session │ │
|
||||||
│ │ (history, │ │
|
│ │ (history, │ │
|
||||||
│ │ branching) │ │
|
│ │ branching) │ │
|
||||||
│ └──────────────┘ │
|
│ └──────────────┘ │
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
|||||||
Reference in New Issue
Block a user