fix: wire asyncCallback to PublishInbound for CI result delivery
The asyncCallback in runLLMIteration was a no-op that only logged. For spawn this didn't matter (SubagentManager.runTask does its own PublishInbound), but create_pr's CI goroutine had no way to deliver results back to the conductor. Now asyncCallback publishes a system inbound message with senderID="async:<tool>" so processSystemMessage injects it into the conductor's session history. The conductor sees the CI result on its next turn. https://claude.ai/code/session_01WWttNE5xShanYD6PhMzgKz
This commit is contained in:
parent
13bc44a3a8
commit
4db47e9588
1 changed files with 27 additions and 12 deletions
|
|
@ -2614,20 +2614,35 @@ func (al *AgentLoop) runLLMIteration(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create async callback for tools that implement AsyncTool
|
// Create async callback for tools that implement AsyncTool.
|
||||||
// NOTE: Following openclaw's design, async tools do NOT send results directly to users.
|
// The callback publishes a system inbound message so processSystemMessage
|
||||||
// Instead, they notify the agent via PublishInbound, and the agent decides
|
// injects the result into the conductor's session history. The conductor
|
||||||
// whether to forward the result to the user (in processSystemMessage).
|
// sees it on its next turn and decides whether to notify the user.
|
||||||
|
toolName := tc.Name // capture for goroutine
|
||||||
asyncCallback := func(callbackCtx context.Context, result *tools.ToolResult) {
|
asyncCallback := func(callbackCtx context.Context, result *tools.ToolResult) {
|
||||||
// Log the async completion but don't send directly to user
|
content := result.ForLLM
|
||||||
// The agent will handle user notification via processSystemMessage
|
if content == "" {
|
||||||
if !result.Silent && result.ForUser != "" {
|
content = result.ForUser
|
||||||
logger.InfoCF("agent", "Async tool completed, agent will handle notification",
|
|
||||||
map[string]any{
|
|
||||||
"tool": tc.Name,
|
|
||||||
"content_len": len(result.ForUser),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
if content == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.InfoCF("agent", "Async tool completed, publishing to conductor",
|
||||||
|
map[string]any{
|
||||||
|
"tool": toolName,
|
||||||
|
"content_len": len(content),
|
||||||
|
"is_error": result.IsError,
|
||||||
|
})
|
||||||
|
|
||||||
|
pubCtx, pubCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer pubCancel()
|
||||||
|
_ = al.bus.PublishInbound(pubCtx, bus.InboundMessage{
|
||||||
|
Channel: "system",
|
||||||
|
SenderID: fmt.Sprintf("async:%s", toolName),
|
||||||
|
ChatID: fmt.Sprintf("%s:%s", opts.Channel, opts.ChatID),
|
||||||
|
Content: fmt.Sprintf("Async tool '%s' completed.\n\nResult:\n%s", toolName, content),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report toolcall state to canvas.
|
// Report toolcall state to canvas.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue