update
This commit is contained in:
+188
@@ -396,6 +396,7 @@ mutable struct yiemAgent <: agent # High-level agent wrapper
|
||||
sessionId::Union{String, Nothing} # Optional session identifier
|
||||
maxRetryDelayMs::Union{Int64, Nothing} # Maximum delay between retries (ms)
|
||||
parallelToolExecute::Bool # Default: false
|
||||
agentEventSink::Function # agent emits its status via this function
|
||||
end
|
||||
|
||||
"""
|
||||
@@ -419,6 +420,7 @@ on `inputChannel` and `followUpChannel` channels concurrently.
|
||||
- `sessionId::Union{String, Nothing}`: Optional session identifier (default: `nothing`)
|
||||
- `maxRetryDelayMs::Union{Int64, Nothing}`: Maximum delay between retries in milliseconds (default: `nothing`)
|
||||
- `parallelToolExecute::Bool`: Run tool calls in parallel (default: `false`)
|
||||
- `agentEventSink::Function`: Callback to receive agent events
|
||||
|
||||
# Returns
|
||||
- A new `yiemAgent` instance with an active background task
|
||||
@@ -444,6 +446,7 @@ function yiemAgent(
|
||||
sessionId::Union{String, Nothing}=nothing,
|
||||
maxRetryDelayMs::Union{Int64, Nothing}=nothing,
|
||||
parallelToolExecute::Bool=false,
|
||||
agentEventSink::Function,
|
||||
)
|
||||
# Create channels: input (user -> agent), followUp (async queue), output (agent -> user)
|
||||
inputChannel = Channel(16)
|
||||
@@ -467,6 +470,7 @@ function yiemAgent(
|
||||
sessionId,
|
||||
maxRetryDelayMs,
|
||||
parallelToolExecute,
|
||||
agentEventSink,
|
||||
)
|
||||
|
||||
# Spawn the background loop and attach it
|
||||
@@ -477,6 +481,190 @@ end
|
||||
|
||||
|
||||
|
||||
"""
|
||||
preparedToolCall(tool, toolCall, args)
|
||||
|
||||
Intermediate state between tool call validation and execution.
|
||||
Created after `prepareToolCall` succeeds; serves as the bridge to
|
||||
the execution phase. Keeping the resolved tool, original call
|
||||
metadata, and validated args together avoids repeated lookups and
|
||||
allows the execution phase to access all necessary data without
|
||||
carrying the full context through the call chain.
|
||||
|
||||
# Fields
|
||||
- `tool::agentTool`: The resolved tool definition from the context
|
||||
- `toolCall::agentToolCall`: The original tool call from the assistant
|
||||
- `args::any`: Validated (and coerced) argument values
|
||||
|
||||
# Examples
|
||||
```julia
|
||||
# After prepareToolCall succeeds, the agent holds a preparedToolCall
|
||||
prep = preparedToolCall(
|
||||
tool, # agentTool found in context.tools
|
||||
toolCall, # {id: "call_1", name: "search_wine", arguments: "{\"query\": \"red wine\"}"}
|
||||
validatedArgs # Dict("query" => "red wine")
|
||||
)
|
||||
```
|
||||
"""
|
||||
struct preparedToolCall
|
||||
tool::agentTool # The resolved tool definition from the context
|
||||
toolCall::agentToolCall # The original tool call from the assistant
|
||||
args::any # Validated (and coerced) argument values
|
||||
end
|
||||
|
||||
"""
|
||||
immediateOutcome(result, isError)
|
||||
|
||||
A tool call that was resolved without actual execution — either
|
||||
because the tool was not found, validation failed, or a
|
||||
`beforeToolCall` hook blocked the call. The result is produced
|
||||
immediately and emitted as a tool result message.
|
||||
|
||||
Returning an outcome instead of throwing an exception is intentional:
|
||||
it lets the agent feed the error back to the LLM as a tool result so
|
||||
the model can recover — for example, by re-issuing a tool call with
|
||||
corrected arguments after a validation failure.
|
||||
|
||||
# Fields
|
||||
- `result::agentToolResult`: The pre-computed tool result
|
||||
- `isError::bool`: Whether this outcome represents an error
|
||||
|
||||
# Examples
|
||||
```julia
|
||||
# Tool not found — immediate error
|
||||
immediateOutcome(
|
||||
createErrorToolResult("Tool search_wine not found"),
|
||||
true
|
||||
)
|
||||
|
||||
# beforeToolCall hook blocked execution
|
||||
immediateOutcome(
|
||||
createErrorToolResult("Tool execution was blocked"),
|
||||
true
|
||||
)
|
||||
```
|
||||
"""
|
||||
struct immediateOutcome
|
||||
result::agentToolResult # The pre-computed tool result
|
||||
isError::bool # Whether this outcome represents an error
|
||||
end
|
||||
|
||||
"""
|
||||
executedOutcome(result, isError)
|
||||
|
||||
A tool call that has been executed by `tool.execute()` but has not
|
||||
yet been through the `afterToolCall` hook. This intermediate state
|
||||
is necessary because the hook may mutate the result (content, usage,
|
||||
termination, error status). Keeping execution and finalization
|
||||
separate allows the hook to inspect the raw result and decide
|
||||
whether to transform it or replace it entirely.
|
||||
|
||||
# Fields
|
||||
- `result::agentToolResult`: The tool's execution result
|
||||
- `isError::bool`: Whether execution raised an error
|
||||
|
||||
# Examples
|
||||
```julia
|
||||
# Successful execution
|
||||
executedOutcome(
|
||||
agentToolResult([textContent("text", "Found 3 wines")], dict{any,any}(), dict{any,any}()),
|
||||
false
|
||||
)
|
||||
|
||||
# Execution error
|
||||
executedOutcome(
|
||||
createErrorToolResult("Connection timeout"),
|
||||
true
|
||||
)
|
||||
```
|
||||
"""
|
||||
struct executedOutcome
|
||||
result::agentToolResult # The tool's execution result
|
||||
isError::bool # Whether execution raised an error
|
||||
end
|
||||
|
||||
"""
|
||||
finalizedOutcome(toolCall, result, isError)
|
||||
|
||||
The complete outcome of a tool call after both execution and the
|
||||
`afterToolCall` hook. This is the final form used to construct
|
||||
the `toolResultMessage` emitted to the agent loop.
|
||||
|
||||
The three-phase design (prepare → execute → finalize) exists so
|
||||
that each phase has a single responsibility: preparation handles
|
||||
validation and gating, execution performs the actual work, and
|
||||
finalization applies post-processing hooks. This separation allows
|
||||
the agent loop to emit `toolExecutionEnd` events with the
|
||||
finalized data while keeping each phase independently testable
|
||||
and swappable.
|
||||
|
||||
# Fields
|
||||
- `toolCall::agentToolCall`: The original tool call reference
|
||||
- `result::agentToolResult`: The final tool result (post-afterToolCall)
|
||||
- `isError::bool`: Whether the call failed or was blocked
|
||||
|
||||
# Examples
|
||||
```julia
|
||||
# Normal successful finalization
|
||||
finalizedOutcome(tc, agentToolResult(content, details, usage, false), false)
|
||||
|
||||
# afterToolCall mutated result and set terminate
|
||||
finalizedOutcome(tc, agentToolResult(content, details, usage, true), false)
|
||||
```
|
||||
"""
|
||||
struct finalizedOutcome
|
||||
toolCall::agentToolCall # The original tool call reference
|
||||
result::agentToolResult # The final tool result (post-afterToolCall)
|
||||
isError::bool # Whether the call failed or was blocked
|
||||
end
|
||||
|
||||
"""
|
||||
agentToolCallBatch(messages, terminate)
|
||||
|
||||
A batch of tool result messages from executing one or more tool calls.
|
||||
The `terminate` flag indicates whether all tools in the batch
|
||||
requested termination, which causes the agent loop to stop
|
||||
processing further turns.
|
||||
|
||||
This flag is set by the tool implementation (not the end user) to
|
||||
signal that the agent should not call the LLM again. Typical use
|
||||
cases:
|
||||
|
||||
- Task completion: a tool like `deploy` or `submit` finishes its
|
||||
work and returns `terminate: true` so the agent stops instead
|
||||
of asking the LLM what to do next.
|
||||
- Unrecoverable error: a tool hits a fatal condition (e.g.
|
||||
database connection lost, auth token expired) and returns
|
||||
`terminate: true` so the agent stops with an error message
|
||||
rather than retrying.
|
||||
- Async handoff: a tool triggers a long-running external
|
||||
operation and wants the agent to stop now; the external system
|
||||
will later resume the agent via `continue()`.
|
||||
|
||||
If `terminate` is `false` (default), the agent loop feeds the tool
|
||||
results back to the LLM for another turn.
|
||||
|
||||
# Fields
|
||||
- `messages::Vector{toolResultMessage}`: Tool result messages for this batch
|
||||
- `terminate::Bool`: Whether the batch should terminate the loop
|
||||
|
||||
# Examples
|
||||
```julia
|
||||
# Batch of 3 tool results, no termination
|
||||
agentToolCallBatch(resultMessages, false)
|
||||
|
||||
# All tools requested termination
|
||||
agentToolCallBatch(resultMessages, true)
|
||||
|
||||
# Empty batch — terminate is false regardless
|
||||
agentToolCallBatch(toolResultMessage[], false)
|
||||
```
|
||||
"""
|
||||
struct agentToolCallBatch
|
||||
messages::vector{toolResultMessage} # Tool result messages for this batch
|
||||
terminate::bool # Whether the batch should terminate the loop
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user