update
This commit is contained in:
+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: │
|
||||||
|
|||||||
Reference in New Issue
Block a user