update
This commit is contained in:
+116
-207
@@ -1,221 +1,130 @@
|
||||
# Agent Loop Sequence Diagram (ASCII)
|
||||
# Agent Loop Sequence Diagram
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ ┌───────────┐
|
||||
│ User │─────>│ Agent │─────>│ AgentLoop │─────>│ LLM │
|
||||
└─────────────┘ └─────────────┘ └─────────────────┘ └───────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐ ┌─────────────────┐ ┌───────────┐ ┌─────────────┐
|
||||
│ User │<─────│ AgentLoop │─────>│ Agent │─────>│ Session │
|
||||
└─────────────┘ └─────────────────┘ └───────────┘ └─────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ Session │
|
||||
└─────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ AGENT LOOP MAIN FLOW │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
User
|
||||
│
|
||||
│ prompt(messages)
|
||||
▼
|
||||
Agent
|
||||
│
|
||||
│ normalizePromptInput()
|
||||
│ runPromptMessages()
|
||||
│
|
||||
├─ alt steering_queue has messages
|
||||
│ │ drain(steering_queue)
|
||||
│ │ runPromptMessages()
|
||||
│
|
||||
├─ alt follow_up_queue has messages
|
||||
│ │ drain(follow_up_queue)
|
||||
│ │ runPromptMessages()
|
||||
│
|
||||
└─ else (normal prompt)
|
||||
│ createLoopConfig()
|
||||
│ createActiveRun()
|
||||
│
|
||||
▼
|
||||
AgentLoop
|
||||
│
|
||||
│ agentLoop(messages, context, config)
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ MAIN LOOP │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. Handle queued messages │
|
||||
│ ├─ drain(steering_queue) │
|
||||
│ ├─ emit(MessageStartEvent) │
|
||||
│ ├─ push to context.messages │
|
||||
│ └─ emit(MessageEndEvent) │
|
||||
│ │
|
||||
│ 2. Get LLM Response │
|
||||
│ ├─ transform_context?(messages) │
|
||||
│ ├─ convert_to_llm(messages) │
|
||||
│ └─ stream_function(model, context, config) │
|
||||
│ │
|
||||
│ LLM │
|
||||
│ │ response stream │
|
||||
│ └─ emit(MessageStartEvent) │
|
||||
│ └─ emit(MessageUpdateEvent) (streaming) │
|
||||
│ └─ emit(MessageEndEvent(final_message)) │
|
||||
│ │
|
||||
│ 3. Check for Tool Calls │
|
||||
│ └─ extract_tool_calls(message.content) │
|
||||
│ │
|
||||
│ 4. Execute Tools (if any) │
|
||||
│ ├─ emit(ToolExecutionStartEvent) │
|
||||
│ ├─ prepareToolCall() │
|
||||
│ │ ├─ before_tool_call? (block if needed) │
|
||||
│ │ └─ validateToolArguments() │
|
||||
│ ├─ execute(tool_call_id, args) │
|
||||
│ │ Tool │
|
||||
│ │ │ execute() │
|
||||
│ │ └─ on_update(partial_result) │
|
||||
│ ├─ emit(ToolExecutionEndEvent) │
|
||||
│ └─ createToolResultMessage() │
|
||||
│ │
|
||||
│ 5. Emit Turn End Event │
|
||||
│ └─ emit(TurnEndEvent(message, tool_results)) │
|
||||
│ │
|
||||
│ 6. Prepare Next Turn │
|
||||
│ └─ prepare_next_turn(context) │
|
||||
│ └─ AgentLoopTurnUpdate │
|
||||
│ │
|
||||
│ 7. Check Stop Condition │
|
||||
│ └─ should_stop_after_turn? (break if true) │
|
||||
│ │
|
||||
│ 8. Get Steering/Follow-up Messages │
|
||||
│ ├─ drain(steering_queue) │
|
||||
│ └─ drain(follow_up_queue) │
|
||||
│ │
|
||||
│ 9. Continue or Break │
|
||||
│ ├─ alt pending messages exist → continue loop │
|
||||
│ └─ else → break │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
AgentLoop
|
||||
│
|
||||
│ emit(AgentEndEvent(messages))
|
||||
│
|
||||
▼
|
||||
Agent
|
||||
│
|
||||
│ appendMessage() → Session
|
||||
│
|
||||
▼
|
||||
User (via promise)
|
||||
+---------+ +---------+ +------------+ +-------+ +-------+
|
||||
| User | | Agent | | AgentLoop | | LLM | | Tool |
|
||||
+---------+ +---------+ +------------+ +-------+ +-------+
|
||||
| | | | |
|
||||
| prompt(messages)| | | |
|
||||
|---------------->--> | | |
|
||||
| | normalizePrompt()| | |
|
||||
| |----------------->>| | |
|
||||
| | runPromptMessages| | |
|
||||
| |----------------->>| | |
|
||||
| | | | |
|
||||
| | createLoopConfig | | |
|
||||
| |----------------->>| | |
|
||||
| | | | |
|
||||
| | agentLoop() | | |
|
||||
| |----------------->>| | |
|
||||
| | | emit(AgentStart) | |
|
||||
| | |------------------> | |
|
||||
| | | | |
|
||||
| | | transform_context() | |
|
||||
| | |------------------> | |
|
||||
| | | convert_to_llm() | |
|
||||
| | |------------------> | |
|
||||
| | | stream_function() | |
|
||||
| | |-------------------------> |
|
||||
| | | | response |
|
||||
| | |<------------------------- |
|
||||
| | | emit(MessageStart)| |
|
||||
| | |------------------> | |
|
||||
| | | emit(MessageEnd) | |
|
||||
| | |------------------> | |
|
||||
| | | | |
|
||||
| | | extract_tool_calls()| |
|
||||
| | |------------------> | |
|
||||
| | | | |
|
||||
| | | executeToolCalls() | |
|
||||
| | |-------------------------> |
|
||||
| | | | execute() |
|
||||
| | |-------------------------> |
|
||||
| | | | result |
|
||||
| | |<------------------------- |
|
||||
| | | emit(ToolExecutionEnd)| |
|
||||
| | |------------------> | |
|
||||
| | | createToolResult() | |
|
||||
| | |------------------> | |
|
||||
| | | emit(MessageEnd) | |
|
||||
| | |------------------> | |
|
||||
| | | | |
|
||||
| | | emit(TurnEnd) | |
|
||||
| | |------------------> | |
|
||||
| | | | |
|
||||
| | | prepare_next_turn() | |
|
||||
| | |------------------> | |
|
||||
| | | | |
|
||||
| | | should_stop_check() | |
|
||||
| | |------------------> | |
|
||||
| | | | |
|
||||
| | | drain(steering_queue)| |
|
||||
| | |------------------> | |
|
||||
| | | | |
|
||||
| | | drain(follow_up_queue)| |
|
||||
| | |------------------> | |
|
||||
| | | | |
|
||||
| | emit(AgentEnd) | | |
|
||||
| |------------------>| | |
|
||||
| | | | |
|
||||
| | appendMessage() | | |
|
||||
| |------------------> Session | |
|
||||
|<----------------| | | |
|
||||
| messages | | | |
|
||||
| | | | |
|
||||
```
|
||||
|
||||
## KEY COMPONENTS
|
||||
|
||||
### Agent Layer
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ Agent │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ state: AgentState │ │
|
||||
│ │ - system_prompt │ │
|
||||
│ │ - model │ │
|
||||
│ │ - messages[] │ │
|
||||
│ │ - tools[] │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ Queues: │ │
|
||||
│ │ - steering_queue: inject after assistant turn │ │
|
||||
│ │ - follow_up_queue: run when agent stops │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### AgentLoop Layer
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ AgentLoop │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ agentLoop() │ │
|
||||
│ │ - Main loop execution │ │
|
||||
│ │ - Tool orchestration │ │
|
||||
│ │ - Event emission │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ executeToolCallsSequential() │ │
|
||||
│ │ executeToolCallsParallel() │ │
|
||||
│ │ - Tool execution coordination │ │
|
||||
│ │ - Hook invocation │ │
|
||||
│ │ - Result collection │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Lifecycle Events Flow
|
||||
```
|
||||
AgentStartEvent
|
||||
│
|
||||
├─ TurnStartEvent
|
||||
│ ├─ MessageStartEvent (user/assistant)
|
||||
│ ├─ MessageEndEvent
|
||||
│ ├─ ToolExecutionStartEvent
|
||||
│ │ ├─ ToolExecutionUpdateEvent (streaming)
|
||||
│ │ └─ ToolExecutionEndEvent
|
||||
│ └─ TurnEndEvent
|
||||
│
|
||||
└─ AgentEndEvent (with final messages)
|
||||
```
|
||||
|
||||
## QUEUE PROCESSING ORDER
|
||||
|
||||
1. **Initial steering messages** (if any)
|
||||
2. **Main loop**:
|
||||
- Steering/follow-up messages (if any)
|
||||
- LLM call
|
||||
- Tool execution (if any)
|
||||
- Turn end event
|
||||
- Next turn preparation
|
||||
- Check stop condition
|
||||
3. **Follow-up messages** (after loop exits, only if no steering)
|
||||
|
||||
## DATA FLOW
|
||||
## Key Participants
|
||||
|
||||
```
|
||||
Input:
|
||||
User messages → Agent.normalizePromptInput() → AgentLoop
|
||||
|
||||
LLM Call:
|
||||
AgentMessage[] → transform_context() → convert_to_llm() →
|
||||
LLM.stream() → AssistantMessage
|
||||
|
||||
Tool Execution:
|
||||
ToolCall[] → prepareToolCall() →
|
||||
before_tool_call? → execute() → after_tool_call? →
|
||||
ToolResultMessage[]
|
||||
|
||||
Output:
|
||||
AgentEndEvent(messages) → Session.appendMessage() → User promise
|
||||
User - Initiates conversation by calling prompt()
|
||||
Agent - High-level wrapper managing state, queues, and events
|
||||
AgentLoop - Low-level execution engine (agentLoop, runLoop)
|
||||
LLM - Language model API (via stream_function)
|
||||
Tool - Tool execution (bash, read, write, edit)
|
||||
Session - Conversation history persistence
|
||||
```
|
||||
|
||||
## EXECUTION MODES
|
||||
## Main Loop Flow
|
||||
|
||||
### Sequential (EXECUTION_SEQUENTIAL)
|
||||
```
|
||||
ToolCall1 → ToolCall2 → ToolCall3
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
Result1 Result2 Result3
|
||||
1. [Agent] normalizePromptInput() - Convert input to messages
|
||||
2. [Agent] runPromptMessages() - Start processing
|
||||
3. [Agent] createLoopConfig() - Build loop configuration
|
||||
4. [Agent] agentLoop() - Start low-level loop
|
||||
5. [AgentLoop] emit(AgentStart) - Signal start
|
||||
6. [AgentLoop] transform_context() - Optional context transform
|
||||
7. [AgentLoop] convert_to_llm() - Convert to LLM messages
|
||||
8. [AgentLoop] stream_function() - Call LLM
|
||||
9. [AgentLoop] emit(MessageStart/End) - Stream response
|
||||
10. [AgentLoop] extract_tool_calls() - Check for tool calls
|
||||
11. [AgentLoop] executeToolCalls() - Execute tools (seq/parallel)
|
||||
12. [AgentLoop] emit(TurnEnd) - Signal turn complete
|
||||
13. [AgentLoop] prepare_next_turn() - Optional next turn setup
|
||||
14. [AgentLoop] should_stop_check() - Check termination
|
||||
15. [AgentLoop] drain queues() - Check steering/follow-up
|
||||
16. [AgentLoop] emit(AgentEnd) - Signal completion
|
||||
17. [Agent] appendMessage() - Persist to session
|
||||
```
|
||||
|
||||
### Parallel (EXECUTION_PARALLEL)
|
||||
## Queue Processing
|
||||
|
||||
```
|
||||
ToolCall1 ─┐
|
||||
ToolCall2──┼→ Execute all → Wait for all → Results
|
||||
ToolCall3 ─┘
|
||||
steering_queue: Injected after assistant turn, before next LLM call
|
||||
follow_up_queue: Run only when agent would otherwise stop (after loop exit)
|
||||
```
|
||||
|
||||
## Event Flow
|
||||
|
||||
```
|
||||
AgentStart → [TurnStart → MessageStart → MessageEnd → ...] → TurnEnd → ...
|
||||
↓
|
||||
AgentEnd
|
||||
```
|
||||
|
||||
## Tool Execution Options
|
||||
|
||||
```
|
||||
Sequential: One tool at a time, in order
|
||||
Parallel: All tools spawned concurrently, results collected
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user