diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 69e16b68..bd7b09ab 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -400,17 +400,24 @@ func (e *Engine) complete(ctx context.Context, state *State) (*Return, error) { } }() - // Limit the number of consecutive tool calls and responses. + // Limit the number of consecutive tool calls. // We don't want the LLM to call tools unrestricted or get stuck in an error loop. var messagesSinceLastUserMessage int for _, msg := range slices.Backward(state.Completion.Messages) { if msg.Role == types.CompletionMessageRoleTypeUser { break + } else if msg.Role == types.CompletionMessageRoleTypeAssistant { + for _, content := range msg.Content { + // If this message is requesting that a tool call be made, then count it towards the limit. + if content.ToolCall != nil { + messagesSinceLastUserMessage++ + break + } + } } - messagesSinceLastUserMessage++ } - // Divide by 2 because tool calls come in pairs: call and response. - if messagesSinceLastUserMessage/2 > maxConsecutiveToolCalls { + + if messagesSinceLastUserMessage > maxConsecutiveToolCalls { msg := fmt.Sprintf("We cannot continue because the number of consecutive tool calls is limited to %d.", maxConsecutiveToolCalls) ret.State.Completion.Messages = append(state.Completion.Messages, types.CompletionMessage{ Role: types.CompletionMessageRoleTypeAssistant,