Files
YiemAgent/learning/README.md
T
2026-07-29 11:14:04 +07:00

387 lines
7.8 KiB
Markdown

# AgentCore.jl - Learning Guide
## How to Use This Documentation
### Top-Down Learning Approach
This documentation is organized in a **top-down** order, starting from high-level concepts and drilling down into implementation details. Follow this sequence:
1. **Architecture Overview** - Understand the big picture
2. **Agent Component** - Learn about state management and event streaming
3. **AgentLoop Component** - Understand the core LLM interaction loop
4. **Types & Messages** - Learn the data structures
5. **Session Management** - Understand conversation history
6. **Tools** - Learn about tool execution
### Learning Style
- **Visual learners**: Study the ASCII diagrams
- **Hands-on learners**: Code examples provided for each section
- **Conceptual learners**: Read summaries and overviews first
## Quick Start
### Minimal Example
```julia
using AgentCore
# Create agent
agent = Agent(Dict(
:systemPrompt => "You are a helpful assistant.",
:model => Model(...),
:tools => [bash_tool],
))
# Run conversation
prompt(agent, "Hello!")
# Wait for completion
wait_for_idle(agent)
```
### Understanding the Flow
```
User Code
├─► Create Agent
│ ├─ Initialize state
│ ├─ Set up queues
│ └─ Register hooks
├─► prompt("Hello")
│ ├─ Validate input
│ └─ Start AgentLoop
├─► AgentLoop (runs in thread)
│ ├─ Stream LLM response
│ ├─ Execute tools
│ └─ Emit events
└─► Event handlers receive events
├─ MessageEndEvent
├─ ToolExecutionEndEvent
└─ AgentEndEvent
```
## Core Concepts
### Agent
**What it is**: High-level interface for LLM interactions
**What it does**:
- Manages conversation state
- Handles event streaming
- Queues steering/follow-up messages
- Provides hooks for customization
**Key methods**:
- `prompt()` - Start new conversation
- `continue!()` - Continue existing conversation
- `steer()` - Queue message for next turn
- `followUp()` - Queue message after stop
- `subscribe()` - Listen to events
### AgentLoop
**What it is**: Core LLM interaction loop
**What it does**:
- Calls LLM API with streaming
- Executes tool calls (parallel or sequential)
- Emits lifecycle events
- Handles steering/follow-up messages
**Key functions**:
- `agentLoop()` - Start new conversation
- `agentLoopContinue()` - Continue conversation
- `runAgentLoop()` - Internal loop execution
- `streamAssistantResponse()` - LLM API call
- `executeToolCalls()` - Tool execution
### Session
**What it is**: Conversation history management
**What it does**:
- Persists messages to storage
- Supports branching
- Implements compaction
- Manages conversation tree
**Key methods**:
- `appendMessage()` - Add message
- `appendCompaction()` - Compress history
- `moveTo()` - Navigate branches
- `buildSessionContext()` - Build context for LLM
### Tools
**What it is**: Functions agents can call
**What they do**:
- Execute external operations
- Return results to agent
- Support streaming updates
- Implement hooks
**Built-in tools**:
- `bash` - Execute shell commands
- `read` - Read files
- `write` - Write files
- `edit` - Edit files
## Event System
### Event Types
```
AgentEvent
├─ AgentStartEvent / AgentEndEvent
├─ TurnStartEvent / TurnEndEvent
├─ MessageStartEvent / MessageEndEvent
├─ MessageUpdateEvent
├─ ToolExecutionStartEvent / ToolExecutionEndEvent
└─ ToolExecutionUpdateEvent
```
### Event Flow
```
AgentStartEvent
├─ TurnStartEvent
│ ├─ MessageStartEvent (user)
│ ├─ MessageEndEvent (user)
│ ├─ MessageStartEvent (assistant)
│ ├─ MessageUpdateEvent (streaming)
│ ├─ MessageEndEvent (assistant)
│ ├─ ToolExecutionStartEvent
│ ├─ ToolExecutionEndEvent
│ └─ TurnEndEvent
└─ AgentEndEvent
```
## Data Flow
### Message Transformation
```
AgentMessage[] (internal)
├─ transform_context() (optional)
AgentMessage[] (transformed)
├─ convert_to_llm()
Message[] (LLM API)
```
### Tool Execution Flow
```
ToolCall (in assistant message)
├─ before_tool_call hook
├─ prepareToolCall()
├─ execute()
├─ after_tool_call hook
└─ createToolResultMessage()
```
## Best Practices
### 1. Use Hooks for Customization
```julia
# Before tool call
before_hook = (context, signal) -> begin
println("Executing: $(context.tool_call.name)")
return nothing
end
# After tool call
after_hook = (context, signal) -> begin
if context.is_error
println("Tool failed: $(context.tool_call.name)")
end
return nothing
end
```
### 2. Monitor Events
```julia
subscribe(agent) do event, signal
if event isa MessageEndEvent
println("Message: $(event.message)")
elseif event isa ToolExecutionEndEvent
println("Tool completed: $(event.tool_name)")
end
end
```
### 3. Use Steering for Redirection
```julia
# Agent is going wrong direction
steer(agent, UserMessage("Actually, let's do X instead"))
```
### 4. Use Follow-Up for Continuation
```julia
# Agent thinks it's done, but user wants more
followUp(agent, UserMessage("Wait, there's one more thing"))
```
## Common Patterns
### Pattern 1: Conversation with Memory
```julia
# Use Session to persist conversation
storage = JsonlSessionStorage(...)
session = Session(storage)
# Add messages to session
appendMessage(session, user_message)
appendMessage(session, assistant_message)
# Build context from session
context = buildSessionContext(session)
```
### Pattern 2: Long Conversations
```julia
# Compact periodically to stay within context limits
if token_count > MAX_TOKENS * 0.8
compact_id = appendCompaction(
session,
summary,
first_kept_id,
token_count,
)
end
```
### Pattern 3: Branching Conversations
```julia
# User wants to explore alternative
session.moveTo(branch_point_id)
# Create new branch
appendBranchSummary(session, "Exploring alternative approach")
appendMessage(session, new_user_message)
```
### Pattern 4: Custom Tools
```julia
# Create custom tool
custom_tool = AgentTool(
"custom",
"custom",
"Does custom thing",
...,
execute_function,
nothing,
EXECUTION_PARALLEL,
)
# Add to agent
agent = Agent(Dict(:tools => [custom_tool]))
```
## Debugging
### Check Active Run
```julia
if !isnothing(agent.active_run)
println("Agent is busy")
else
println("Agent is idle")
end
```
### Clear Queues
```julia
clearAllQueues(agent)
```
### Reset State
```julia
reset!(agent)
```
## Performance Tips
1. **Use parallel execution** for independent tools
2. **Compact periodically** for long conversations
3. **Use thinking_level wisely** (higher = slower but better)
4. **Batch tool calls** when possible
5. **Cache LLM responses** when appropriate
## Troubleshooting
### Agent stuck in loop
```julia
# Check if agent is still processing
if hasQueuedMessages(agent)
# Clear queues
clearAllQueues(agent)
end
```
### Too many tokens
```julia
# Compact session
compact_id = appendCompaction(
session,
summary,
first_kept_id,
token_count,
)
```
### Tool execution failed
```julia
# Check tool result
if result.is_error
println("Tool failed: $(result.error)")
end
```
## Next Steps
1. Read **Architecture Overview** for deep understanding
2. Explore **Agent Component** for state management
3. Study **AgentLoop** for core logic
4. Learn **Types & Messages** for data structures
5. Master **Session Management** for persistence
6. Build **Tools** for custom functionality
## Resources
- Original TypeScript implementation: `@earendil-works/pi-agent-core`
- AgentCore.jl source code: `src/`
- Examples: `examples/`
## Community
For questions and discussions:
- GitHub Issues: `/issues`
- Documentation: `docs/`