Now that we know how to hold a conversation, let's give the model a tool it can reach for.
A tool is a function the model is allowed to call. We describe what the function does and what arguments it takes. The model calls it when the sampled output points to it.
A tool definition has three fields: name, description, and parameters (a JSON Schema describing the arguments). The model emits toolCall events when the sampled output is a tool call. We handle the call ourselves and push the result back into history so the next call has the tool result in its input.
The shape declared with the SDK would look like the following:
const tools = [
{
name: "get_weather",
description: "Get current weather for a city",
parameters: {
type: "object",
properties: { city: { type: "string" } },
required: ["city"],
},
},
];Passing the tools array is what makes them available to the model:
const result = completion({
modelId,
history: [{ role: "user", content: "What's the weather in Tokyo?" }],
tools,
stream: true,
captureThinking: true,
});Arguments come back as a typed object matching the schema. Every time the model emits a tool call, we'd dispatch on event.call.name to run the matching function like so:
for await (const event of result.events) {
if (event.type === "toolCall") {
console.log(`▸ Tool: ${event.call.name}(${JSON.stringify(event.call.arguments)})`);
}
}The arguments come back as a parsed object matching our JSON Schema. We execute the function (call an API, query a database), then push { role: "tool", content: resultString } back into history so the model can synthesize the final answer.
Note:
captureThinking: trueis the option the first lesson in this chapter introduced. Without it, the model'sthinkingwould land in the samecontentDeltastream the tool call comes from and muddle the tool-call detection. The option keepsthinkingonthinkingDeltaevents, socontentDeltaonly carries the model's prose around the tool call. The lesson's loop ignoresthinkingDeltaso the runner's OUTPUT panel only shows the tool calls.
Note: tool support has to be enabled when loading the model. Set
modelConfig: { tools: true }on theloadModel()call, otherwise the model will not understand how to use the tools array.
tools array with one tool. Give it name, description, and parameters (JSON Schema).tools and captureThinking: true to completion() with a user question that requires the tool, stream result.events, and log toolCall events with the function name and arguments. thinkingDelta events arrive on the same stream and are ignored here so the runner's OUTPUT panel only shows the tool calls.await result.toolCalls to get the full list and push tool results back as {role: "tool"} messages for the next turn.$ Run your code to see results
$