Termination
Loops need a stop condition. The agent has three: the model returns content with no tool calls, the completion reports finish_reason == "stop", or the iteration counter runs out. Getting the first two right is what makes the agent feel responsive instead of chatty.
if len(choice.Message.ToolCalls) > 0 {
// more tools, keep going
continue
}
if choice.FinishReason == "stop" || choice.Message.Content != "" {
return strings.TrimSpace(choice.Message.Content), nil
}
// else: iterate again and hope the next call produces either tools or contentThe second condition has an OR on purpose. Some providers return an empty finish_reason while still producing content. Leaning on either signal keeps the agent working across OpenAI-compatible endpoints.
Ordering exercise: Order the checks
Loading practice…
Quiz: Quiz
Loading practice…