The tool dispatcher
When the model decides to use a tool, it returns an assistant message with a tool_calls array instead of a Content string. Each entry has an id, the function name, and a JSON string of arguments. Your job is to find the matching Go function, run it, and append a tool-role message back to the conversation with the result.
One tool round-trip
How a single tool call flows from request to dispatch to the next turn.
if len(choice.Message.ToolCalls) > 0 {
for _, tc := range choice.Message.ToolCalls {
tool := a.findTool(tc.Function.Name)
var result string
if tool == nil {
result = fmt.Sprintf("error: unknown tool %q", tc.Function.Name)
} else {
out, terr := tool.Run(tc.Function.Arguments)
if terr != nil {
result = fmt.Sprintf("error: %v\n%s", terr, out)
} else {
result = out
}
}
messages = append(messages, Message{
Role: "tool",
ToolCallID: tc.ID,
Name: tc.Function.Name,
Content: result,
})
}
continue
}Errors from the tool become content on a tool-role message. The model sees the failure and can correct itself. Panicking the Go process would be wrong.
ToolCallID matches the id emitted by the model inside tool_calls. When a single turn contains more than one tool call, the id is how the model pairs each result with the request it made. Skip the id and the next response goes sideways, because the model cannot tell which tool output answers which call.
Quiz: Quiz
Loading practice…