fix: resolve gemini empty content error and improve max iteration fallback

This commit is contained in:
Zilin Du 2026-02-27 09:21:41 -08:00
parent 3584c0c7be
commit 097b7a4412

View file

@ -424,7 +424,7 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
agent.Sessions.AddMessage(opts.SessionKey, "user", opts.UserMessage)
// 4. Run LLM iteration loop
finalContent, iteration, err := al.runLLMIteration(ctx, agent, messages, opts)
finalContent, iteration, sentUserContent, err := al.runLLMIteration(ctx, agent, messages, opts)
if err != nil {
return "", err
}
@ -434,12 +434,27 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
// 5. Handle empty response
if finalContent == "" {
finalContent = opts.DefaultResponse
if iteration >= agent.MaxIterations {
finalContent = "I've reached the maximum number of steps for this request. Please try breaking it down into smaller tasks."
} else if sentUserContent {
// We already sent content to the user (via tools), so we can suppress the default response
finalContent = ""
} else if iteration > 1 {
// Tools were executed but didn't send output, and LLM is silent.
// Use a generic success message instead of "no response to give" which sounds like an error.
finalContent = "Task completed."
} else {
finalContent = opts.DefaultResponse
}
}
}
// 6. Save final assistant message to session
agent.Sessions.AddMessage(opts.SessionKey, "assistant", finalContent)
agent.Sessions.Save(opts.SessionKey)
// Only save if meaningful (LLM might have returned empty string if it thought it was done)
if finalContent != "" {
agent.Sessions.AddMessage(opts.SessionKey, "assistant", finalContent)
agent.Sessions.Save(opts.SessionKey)
}
// 7. Optional: summarization
if opts.EnableSummary {
@ -447,7 +462,7 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
}
// 8. Optional: send response via bus
if opts.SendResponse {
if opts.SendResponse && finalContent != "" {
al.bus.PublishOutbound(bus.OutboundMessage{
Channel: opts.Channel,
ChatID: opts.ChatID,
@ -474,9 +489,10 @@ func (al *AgentLoop) runLLMIteration(
agent *AgentInstance,
messages []providers.Message,
opts processOptions,
) (string, int, error) {
) (string, int, bool, error) {
iteration := 0
var finalContent string
sentUserContent := false
for iteration < agent.MaxIterations {
iteration++
@ -591,7 +607,7 @@ func (al *AgentLoop) runLLMIteration(
"iteration": iteration,
"error": err.Error(),
})
return "", iteration, fmt.Errorf("LLM call failed after retries: %w", err)
return "", iteration, sentUserContent, fmt.Errorf("LLM call failed after retries: %w", err)
}
// Check if no tool calls - we're done
@ -700,6 +716,7 @@ func (al *AgentLoop) runLLMIteration(
ChatID: opts.ChatID,
Content: toolResult.ForUser,
})
sentUserContent = true
logger.DebugCF("agent", "Sent tool result to user",
map[string]any{
"tool": tc.Name,
@ -725,7 +742,7 @@ func (al *AgentLoop) runLLMIteration(
}
}
return finalContent, iteration, nil
return finalContent, iteration, sentUserContent, nil
}
// updateToolContexts updates the context for tools that need channel/chatID info.