feat(agent): generate TLDR summary instead of generic empty response message

When the LLM returns no response, the bot now provides a meaningful
summary of what was processed including:
- List of tools that were executed
- Number of iterations taken
- Truncated user message

This replaces the unhelpful message about increasing max_tool_iterations
with actual context about what the bot did.
This commit is contained in:
instax-dutta 2026-03-02 22:31:06 +05:30
parent 475d8f948b
commit ad070267fd

View file

@ -12,6 +12,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -518,7 +519,7 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
agent.Sessions.AddMessage(opts.SessionKey, "user", opts.UserMessage) agent.Sessions.AddMessage(opts.SessionKey, "user", opts.UserMessage)
// 4. Run LLM iteration loop // 4. Run LLM iteration loop
finalContent, iteration, err := al.runLLMIteration(ctx, agent, messages, opts) finalContent, iteration, executedTools, err := al.runLLMIteration(ctx, agent, messages, opts)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -528,7 +529,7 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
// 5. Handle empty response // 5. Handle empty response
if finalContent == "" { if finalContent == "" {
finalContent = opts.DefaultResponse finalContent = generateTLDR(opts.UserMessage, executedTools, iteration)
} }
// 6. Save final assistant message to session // 6. Save final assistant message to session
@ -621,9 +622,10 @@ func (al *AgentLoop) runLLMIteration(
agent *AgentInstance, agent *AgentInstance,
messages []providers.Message, messages []providers.Message,
opts processOptions, opts processOptions,
) (string, int, error) { ) (string, int, []string, error) {
iteration := 0 iteration := 0
var finalContent string var finalContent string
executedTools := []string{}
for iteration < agent.MaxIterations { for iteration < agent.MaxIterations {
iteration++ iteration++
@ -808,6 +810,9 @@ func (al *AgentLoop) runLLMIteration(
"iteration": iteration, "iteration": iteration,
}) })
// Track executed tools for TLDR generation
executedTools = append(executedTools, toolNames...)
// Build assistant message with tool calls // Build assistant message with tool calls
assistantMsg := providers.Message{ assistantMsg := providers.Message{
Role: "assistant", Role: "assistant",
@ -1350,3 +1355,39 @@ func extractParentPeer(msg bus.InboundMessage) *routing.RoutePeer {
} }
return &routing.RoutePeer{Kind: parentKind, ID: parentID} return &routing.RoutePeer{Kind: parentKind, ID: parentID}
} }
// generateTLDR generates a summary when the LLM returns an empty response.
// It provides context about what was processed instead of a generic message.
func generateTLDR(userMessage string, executedTools []string, iteration int) string {
var sb strings.Builder
if len(executedTools) > 0 {
sb.WriteString("Processed ")
sb.WriteString(strconv.Itoa(len(executedTools)))
sb.WriteString(" tool(s): ")
sb.WriteString(strings.Join(executedTools, ", "))
sb.WriteString(".")
} else {
sb.WriteString("Processed your request")
}
sb.WriteString(" (")
sb.WriteString(strconv.Itoa(iteration))
sb.WriteString(" iteration")
if iteration > 1 {
sb.WriteString("s")
}
sb.WriteString(")")
if len(userMessage) > 50 {
sb.WriteString(". Message: \"")
sb.WriteString(utils.Truncate(userMessage, 50))
sb.WriteString("...\"")
} else if userMessage != "" {
sb.WriteString(". Message: \"")
sb.WriteString(userMessage)
sb.WriteString("\"")
}
return sb.String()
}