diff options
| author | Ben Sima <ben@bensima.com> | 2025-12-12 21:45:53 -0500 |
|---|---|---|
| committer | Ben Sima <ben@bensima.com> | 2025-12-12 21:45:53 -0500 |
| commit | 862b10aa05ef66af5a88f307e6209ce10185bbcf (patch) | |
| tree | d1e0fe0217a0a9e46378d397c745c9cb54775f77 | |
| parent | 49f6fe47e19c42b87615dd2d75e53f43331e00ab (diff) | |
fix: prompt for text response when agent returns empty after tool calls
When the LLM returned empty content after executing tools, the agent
would complete with an empty message. Now both agent loops (LLM-based
and Provider-based) detect this case and inject a prompt asking the
LLM to provide a response to the user.
| -rw-r--r-- | Omni/Agent/Engine.hs | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/Omni/Agent/Engine.hs b/Omni/Agent/Engine.hs index fe3b3d5..dab1329 100644 --- a/Omni/Agent/Engine.hs +++ b/Omni/Agent/Engine.hs @@ -667,18 +667,24 @@ runAgent engineCfg agentCfg userPrompt = do unless (Text.null assistantText) <| engineOnAssistant engineCfg assistantText case msgToolCalls msg of - Nothing -> do - engineOnActivity engineCfg "Agent completed" - engineOnComplete engineCfg - pure - <| Right - <| AgentResult - { resultFinalMessage = msgContent msg, - resultToolCallCount = totalCalls, - resultIterations = iteration + 1, - resultTotalCost = newCost, - resultTotalTokens = newTokens - } + Nothing + | Text.null (msgContent msg) && totalCalls > 0 -> do + engineOnActivity engineCfg "Empty response after tools, prompting for text" + let promptMsg = Message ToolRole "Please provide a response to the user." Nothing Nothing + newMsgs = msgs <> [msg, promptMsg] + loop llm tools' toolMap newMsgs (iteration + 1) totalCalls newTokens newCost toolCallCounts testFailures editFailures + | otherwise -> do + engineOnActivity engineCfg "Agent completed" + engineOnComplete engineCfg + pure + <| Right + <| AgentResult + { resultFinalMessage = msgContent msg, + resultToolCallCount = totalCalls, + resultIterations = iteration + 1, + resultTotalCost = newCost, + resultTotalTokens = newTokens + } Just [] -> do engineOnActivity engineCfg "Agent completed (empty tool calls)" engineOnComplete engineCfg @@ -886,18 +892,24 @@ runAgentWithProvider engineCfg provider agentCfg userPrompt = do unless (Text.null assistantText) <| engineOnAssistant engineCfg assistantText case Provider.msgToolCalls msg of - Nothing -> do - engineOnActivity engineCfg "Agent completed" - engineOnComplete engineCfg - pure - <| Right - <| AgentResult - { resultFinalMessage = Provider.msgContent msg, - resultToolCallCount = totalCalls, - resultIterations = iteration + 1, - resultTotalCost = newCost, - resultTotalTokens = newTokens - } + Nothing + | Text.null (Provider.msgContent msg) && totalCalls > 0 -> do + engineOnActivity engineCfg "Empty response after tools, prompting for text" + let promptMsg = Provider.Message Provider.ToolRole "Please provide a response to the user." Nothing Nothing + newMsgs = msgs <> [msg, promptMsg] + loopProvider prov toolApis' toolMap newMsgs (iteration + 1) totalCalls newTokens newCost toolCallCounts testFailures editFailures + | otherwise -> do + engineOnActivity engineCfg "Agent completed" + engineOnComplete engineCfg + pure + <| Right + <| AgentResult + { resultFinalMessage = Provider.msgContent msg, + resultToolCallCount = totalCalls, + resultIterations = iteration + 1, + resultTotalCost = newCost, + resultTotalTokens = newTokens + } Just [] -> do engineOnActivity engineCfg "Agent completed (empty tool calls)" engineOnComplete engineCfg |
