update
This commit is contained in:
+274
-15
@@ -98,6 +98,52 @@
|
||||
|
||||
## Message Types
|
||||
|
||||
### Type Hierarchy
|
||||
|
||||
```
|
||||
Message (for LLM API)
|
||||
├── UserMessage (role: "user")
|
||||
│ ├── content::Vector{MessageContent}
|
||||
│ │ ├── TextContent (text::String)
|
||||
│ │ └── ImageContent (data::String, mime_type::String)
|
||||
│ └── timestamp::Timestamp (Int64)
|
||||
├── AssistantMessage (role: "assistant")
|
||||
│ ├── content::Vector{MessageContent}
|
||||
│ │ ├── TextContent
|
||||
│ │ └── ToolCall (type, id, name, arguments::Dict{String, Any})
|
||||
│ ├── api::String
|
||||
│ ├── provider::String
|
||||
│ ├── model::String
|
||||
│ ├── usage::Usage
|
||||
│ │ ├── input, output, cache_read, cache_write, total_tokens::Int64
|
||||
│ │ └── cost::UsageCost (input, output, cache_read, cache_write, total::Float64)
|
||||
│ ├── stop_reason::String
|
||||
│ ├── error_message::Union{String, Nothing}
|
||||
│ └── timestamp::Timestamp
|
||||
└── ToolResultMessage (role: "toolResult")
|
||||
├── tool_call_id::String
|
||||
├── tool_name::String
|
||||
├── content::Vector{MessageContent}
|
||||
├── details::Any
|
||||
├── usage::Union{Usage, Nothing}
|
||||
├── added_tool_names::Union{Vector{String}, Nothing}
|
||||
├── is_error::Bool
|
||||
└── timestamp::Timestamp
|
||||
|
||||
AgentMessage (internal, extends Message)
|
||||
├── UserMessage (same as above)
|
||||
├── AssistantMessage (same as above)
|
||||
├── ToolResultMessage (same as above)
|
||||
├── BashExecutionMessage (custom, converted to UserMessage)
|
||||
│ ├── role, command, output, exit_code
|
||||
│ ├── cancelled, truncated, full_output_path
|
||||
│ └── exclude_from_context::Bool
|
||||
├── CompactionSummaryMessage (custom, converted to UserMessage)
|
||||
│ ├── summary, tokens_before, timestamp
|
||||
└── BranchSummaryMessage (custom, converted to UserMessage)
|
||||
├── summary, from_id, timestamp
|
||||
```
|
||||
|
||||
### UserMessage
|
||||
|
||||
```julia
|
||||
@@ -108,6 +154,16 @@ struct UserMessage <: Message
|
||||
end
|
||||
```
|
||||
|
||||
**Usage**:
|
||||
```julia
|
||||
# Simple text message
|
||||
UserMessage(
|
||||
"user",
|
||||
[TextContent("Hello, how are you?")],
|
||||
Int64(Dates.now(Dates.UTC).datetime)
|
||||
)
|
||||
```
|
||||
|
||||
**Usage**:
|
||||
```julia
|
||||
# Simple text message
|
||||
@@ -496,9 +552,9 @@ end
|
||||
|
||||
**Note**: AgentState is mutable and used internally by Agent
|
||||
|
||||
## Key Conversion Functions
|
||||
## Message Transformation Pipeline
|
||||
|
||||
### convertToLlm()
|
||||
### convertToLlm() - AgentMessage[] → Message[]
|
||||
|
||||
```julia
|
||||
function convertToLlm(messages::Vector{AgentMessage})::Vector{Message}
|
||||
@@ -515,26 +571,53 @@ function convertToLlm(messages::Vector{AgentMessage})::Vector{Message}
|
||||
end
|
||||
```
|
||||
|
||||
**Purpose**: Transform AgentMessage[] to Message[] for LLM API
|
||||
**Data Flow**:
|
||||
|
||||
```
|
||||
Vector{AgentMessage} (internal conversation history)
|
||||
│
|
||||
│ Type dispatch on convertToLlmMessage():
|
||||
│
|
||||
│ • UserMessage → UserMessage (pass-through)
|
||||
│ • AssistantMessage → AssistantMessage (pass-through)
|
||||
│ • ToolResultMessage → ToolResultMessage (pass-through)
|
||||
│
|
||||
│ Custom messages converted to UserMessage:
|
||||
│ • BashExecutionMessage → UserMessage
|
||||
│ (via bashExecutionToText() for display)
|
||||
│ • CompactionSummaryMessage → UserMessage
|
||||
│ (wrapped with COMPACTION_SUMMARY_PREFIX/SUFFIX)
|
||||
│ • BranchSummaryMessage → UserMessage
|
||||
│ (wrapped with BRANCH_SUMMARY_PREFIX/SUFFIX)
|
||||
│
|
||||
▼
|
||||
Vector{Message} (for LLM API)
|
||||
- Excludes: BashExecutionMessage (if exclude_from_context)
|
||||
- Includes: All standard messages + converted custom messages
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```julia
|
||||
# Input: AgentMessage[]
|
||||
# Input: Vector{AgentMessage}
|
||||
[
|
||||
UserMessage(...),
|
||||
AssistantMessage(...),
|
||||
ToolResultMessage(...),
|
||||
BashExecutionMessage(...), # Will be converted to UserMessage
|
||||
CompactionSummaryMessage(...), # Will be converted to UserMessage
|
||||
UserMessage("user", [TextContent("Hello")], 1234567890),
|
||||
AssistantMessage("assistant", [
|
||||
TextContent("Hi there!"),
|
||||
ToolCall("bash", "call_123", "bash", Dict("command" => "ls"), nothing)
|
||||
], "openai", "openai", "gpt-4", Usage(...), "done", nothing, 1234567891),
|
||||
BashExecutionMessage("custom", "ls -la", "file1.md\nfile2.md\n", 0, false, false, nothing, 1234567892, false),
|
||||
CompactionSummaryMessage("compactionSummary", "Previous conversation compacted", 1000, 1234567893),
|
||||
]
|
||||
|
||||
# Output: Message[]
|
||||
# Output: Vector{Message}
|
||||
[
|
||||
UserMessage(...),
|
||||
AssistantMessage(...),
|
||||
ToolResultMessage(...),
|
||||
UserMessage(...), # Converted from BashExecutionMessage
|
||||
UserMessage(...), # Converted from CompactionSummaryMessage
|
||||
UserMessage("user", [TextContent("Hello")], 1234567890),
|
||||
AssistantMessage("assistant", [
|
||||
TextContent("Hi there!"),
|
||||
ToolCall(...)
|
||||
], "openai", "openai", "gpt-4", Usage(...), "done", nothing, 1234567891),
|
||||
UserMessage("user", [TextContent("Ran `ls -la`\n```\nfile1.md\nfile2.md\n```\n")], 1234567892),
|
||||
UserMessage("user", [TextContent("<summary>Previous conversation compacted</summary>")], 1234567893),
|
||||
]
|
||||
```
|
||||
|
||||
@@ -571,6 +654,182 @@ function convertToLlmMessage(m::ToolResultMessage)
|
||||
end
|
||||
```
|
||||
|
||||
## Complete Data Flow Examples
|
||||
|
||||
### Example 1: User Prompt → Assistant Response
|
||||
|
||||
```
|
||||
User Input:
|
||||
"Hello, what's in the current directory?"
|
||||
|
||||
↓
|
||||
|
||||
prompt(agent, "Hello, what's in the current directory?")
|
||||
│
|
||||
└─► normalizePromptInput(String)
|
||||
Input: "Hello, what's in the current directory?"
|
||||
Output: [UserMessage("user", [TextContent("Hello, what's in the current directory?")], timestamp)]
|
||||
|
||||
↓
|
||||
|
||||
AgentLoop execution:
|
||||
│
|
||||
├─► transform_context() (optional)
|
||||
│ Input: [UserMessage(...)]
|
||||
│ Output: [UserMessage(...)]
|
||||
│
|
||||
├─► convert_to_llm()
|
||||
│ Input: [UserMessage(...)]
|
||||
│ Output: [UserMessage(...)]
|
||||
│
|
||||
├─► stream_fn() - LLM API
|
||||
│ Input: model, Context(...), config
|
||||
│ Output: AssistantMessage with ToolCall[]
|
||||
│ role: "assistant"
|
||||
│ content: [
|
||||
│ TextContent("I'll check the directory for you."),
|
||||
│ ToolCall("tool", "tc_123", "bash", Dict("command" => "ls -la"), nothing)
|
||||
│ ]
|
||||
│ usage: Usage(input=100, output=20, ...)
|
||||
│ stop_reason: "done"
|
||||
│
|
||||
├─► executeToolCalls()
|
||||
│ Input: AssistantMessage with ToolCall[]
|
||||
│ Output: ToolResultMessage[]
|
||||
│ role: "toolResult"
|
||||
│ tool_call_id: "tc_123"
|
||||
│ tool_name: "bash"
|
||||
│ content: [TextContent("file1.md\nfile2.md\n")]
|
||||
│ is_error: false
|
||||
│
|
||||
└─► Append to context.messages
|
||||
|
||||
↓
|
||||
|
||||
Final Conversation History:
|
||||
[
|
||||
UserMessage("user", [TextContent("Hello, what's in the current directory?")], ...),
|
||||
AssistantMessage("assistant", [
|
||||
TextContent("I'll check the directory for you."),
|
||||
ToolCall("tool", "tc_123", "bash", Dict("command" => "ls -la"), nothing)
|
||||
], "openai", "openai", "gpt-4", Usage(...), "done", nothing, ...),
|
||||
ToolResultMessage("toolResult", "tc_123", "bash", [TextContent("file1.md\nfile2.md\n")], ..., false, ...),
|
||||
]
|
||||
```
|
||||
|
||||
### Example 2: Tool Call Execution → Tool Result
|
||||
|
||||
```
|
||||
ToolCall from AssistantMessage
|
||||
│
|
||||
├─ type: "tool"
|
||||
├─ id: "tc_123"
|
||||
├─ name: "bash"
|
||||
├─ arguments: Dict("command" => "ls -la")
|
||||
└─ partial_json: nothing
|
||||
↓
|
||||
prepareToolCall(tool_call)
|
||||
↓
|
||||
Finds tool by name "bash"
|
||||
↓
|
||||
before_tool_call hook (optional)
|
||||
Input: BeforeToolCallContext(...)
|
||||
Output: BeforeToolCallResult(block=false) or nothing
|
||||
↓
|
||||
validateToolArguments(tool_call)
|
||||
Input: Dict("command" => "ls -la")
|
||||
Output: Dict("command" => "ls -la")
|
||||
↓
|
||||
Return: PreparedToolCall("prepared", tool_call, bash_tool, validated_args)
|
||||
↓
|
||||
executePreparedToolCall(prepared)
|
||||
↓
|
||||
tool.execute("tc_123", Dict("command" => "ls -la"), signal, on_update)
|
||||
↓
|
||||
Bash tool executes "ls -la" command
|
||||
Returns: AgentToolResultMutable(
|
||||
content: [TextContent("file1.md\nfile2.md\n")],
|
||||
details: BashToolDetails(...),
|
||||
usage: nothing,
|
||||
added_tool_names: nothing,
|
||||
terminate: nothing
|
||||
)
|
||||
↓
|
||||
finalizeExecutedToolCall(executed)
|
||||
↓
|
||||
after_tool_call hook (optional)
|
||||
Input: AfterToolCallContext(...)
|
||||
Output: AfterToolCallResult(...) or nothing
|
||||
↓
|
||||
Return: FinalizedToolCallOutcome(
|
||||
tool_call: ToolCall(...),
|
||||
result: AgentToolResultMutable(...),
|
||||
is_error: false
|
||||
)
|
||||
↓
|
||||
createToolResultMessage(finalized)
|
||||
↓
|
||||
Return: ToolResultMessage(
|
||||
role: "toolResult",
|
||||
tool_call_id: "tc_123",
|
||||
tool_name: "bash",
|
||||
content: [TextContent("file1.md\nfile2.md\n")],
|
||||
details: BashToolDetails(...),
|
||||
usage: nothing,
|
||||
added_tool_names: nothing,
|
||||
is_error: false,
|
||||
timestamp: Int64(...)
|
||||
)
|
||||
```
|
||||
|
||||
### Example 3: Custom Message Conversion
|
||||
|
||||
```
|
||||
BashExecutionMessage (custom, for logging)
|
||||
│
|
||||
role: "custom"
|
||||
command: "ls -la"
|
||||
output: "file1.md\nfile2.md\n"
|
||||
exit_code: 0
|
||||
cancelled: false
|
||||
truncated: false
|
||||
full_output_path: nothing
|
||||
timestamp: 1234567890
|
||||
exclude_from_context: false
|
||||
↓
|
||||
convertToLlmMessage(BashExecutionMessage)
|
||||
↓
|
||||
bashExecutionToText(msg)
|
||||
Output: "Ran `ls -la`\n```\nfile1.md\nfile2.md\n```\n"
|
||||
↓
|
||||
Return: UserMessage(
|
||||
"user",
|
||||
[TextContent("Ran `ls -la`\n```\nfile1.md\nfile2.md\n```\n")],
|
||||
1234567890
|
||||
)
|
||||
↓
|
||||
(Excluded if exclude_from_context = true)
|
||||
|
||||
────────────────────────────────────────────────────────────────────
|
||||
|
||||
CompactionSummaryMessage (custom, for history compression)
|
||||
│
|
||||
role: "compactionSummary"
|
||||
summary: "Previous 100 turns about Python programming"
|
||||
tokens_before: 15000
|
||||
timestamp: 1234567890
|
||||
↓
|
||||
convertToLlmMessage(CompactionSummaryMessage)
|
||||
↓
|
||||
Text = COMPACTION_SUMMARY_PREFIX + summary + COMPACTION_SUMMARY_SUFFIX
|
||||
Result: "<summary>\nPrevious 100 turns about Python programming\n</summary>"
|
||||
↓
|
||||
Return: UserMessage(
|
||||
"user",
|
||||
[TextContent("<summary>...\nPrevious 100 turns...\n</summary>")],
|
||||
1234567890
|
||||
)
|
||||
|
||||
## Summary
|
||||
|
||||
The type system in AgentCore.jl provides:
|
||||
|
||||
Reference in New Issue
Block a user