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.

agent/agent.go
go
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 content

The 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…