Tools

Open core/tools.ts. You should see the following code already:

core/tools.ts
import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import dotenv from "dotenv";
import { z } from "zod";

dotenv.config();

async function main() {
  const location = "London";
  const result = await generateText({
    model: openai("gpt-4o"),
    prompt: `You are a funny chatbot. users location: ${location}`,
  });
}

main().catch(console.error);

Define a tool called weather.

core/tools.ts
import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import dotenv from "dotenv";
import { z } from "zod";

dotenv.config();

async function main() {
  const location = "London";
  const result = await generateText({
    model: openai("gpt-4o"),
    prompt: `You are a funny chatbot. users location: ${location}`,
    tools: { 
      weather: {}, 
    }, 
  });
}

main().catch(console.error);

Provide a description for the tool.

core/tools.ts
import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import dotenv from "dotenv";
import { z } from "zod";

dotenv.config();

async function main() {
  const location = "London";
  const result = await generateText({
    model: openai("gpt-4o"),
    prompt: `You are a funny chatbot. users location: ${location}`,
    tools: {
      weather: {
        description: "Get the weather for the user's location", 
      },
    },
  });
}

main().catch(console.error);

Note: the description is very important because it is what the model will use to decide whether or not to use the tool.

Import Zod and define a Zod schema that describes the parameters necessary for the tool to run. Pass this schema to the parameters key.

core/tools.ts
import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import dotenv from "dotenv";
import { z } from "zod"; 

dotenv.config();

async function main() {
  const location = "London";
  const result = await generateText({
    model: openai("gpt-4o"),
    prompt: `You are a funny chatbot. users location: ${location}`,
    tools: {
      weather: {
        description: "Get the weather for the user's location",
        parameters: z.object({ 
          location: z.string().describe("the user's location"), 
        }), 
      },
    },
  });
}

main().catch(console.error);

Note: you can optionally describe your parameters using the .describe function. This will ensure the model has the appropriate context to produce a great generation.

Define an execute function.

core/tools.ts
import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import dotenv from "dotenv";
import { z } from "zod";

dotenv.config();

async function main() {
  const location = "London";
  const result = await generateText({
    model: openai("gpt-4o"),
    prompt: `You are a funny chatbot. users location: ${location}`,
    tools: {
      weather: {
        description: "Get the weather for the user's location",
        parameters: z.object({
          location: z.string().describe("the user's location"),
        }),
        execute: async ({ location }) => {  
          // await getWeather(location)
          const temperature = Math.floor(Math.random() * 31); 
          return { temperature }; 
        },
      },
    },
  });
}

main().catch(console.error);

Note: This is the function that will be run if the model decides to use the tool.

Check if the model called the tool.

core/tools.ts
import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import dotenv from "dotenv";
import { z } from "zod";

dotenv.config();

async function main() {
  const location = "London";
  const result = await generateText({
    model: openai("gpt-4o"),
    prompt: `You are a funny chatbot. users location: ${location}`,
    tools: {
      weather: {
        description: "Get the weather for the user's location",
        parameters: z.object({
          location: z.string().describe("the user's location"),
        }),
        execute: async ({ location }) => {
          // await getWeather(location) 
          const temperature = Math.floor(Math.random() * 31); 
          return { temperature };
        },
      },
    },
  });

  if (result.toolResults && result.toolCalls) { 
  } 
}

main().catch(console.error);

Note: the SDK will not automatically send the Tool result to another model call to summarise.

Import and call streamText passing in the users' location and the weather of their current location (toolResult).

core/tools.ts
import { openai } from "@ai-sdk/openai";
import { generateText, streamText } from "ai";
import dotenv from "dotenv";
import { z } from "zod";

dotenv.config();

async function main() {
  const location = "London";
  const result = await generateText({
    model: openai("gpt-4o"),
    prompt: `You are a funny chatbot. users location: ${location}`,
    tools: {
      weather: {
        description: "Get the weather for the user's location",
        parameters: z.object({
          location: z.string().describe("the user's location"),
        }),
        execute: async ({ location }) => {
          // await getWeather(location) 
          const temperature = Math.floor(Math.random() * 31); 
          return { temperature };
        },
      },
    },
  });

  if (result.toolCalls && result.toolResults) {
    const joke = await streamText({ 
      model: openai("gpt-4o"), 
      prompt: `Tell me a joke that incorporates ${location}
               and it's current temperature (${result.toolResults[0].result.temperature})`, 
    }); 
  }
}

main().catch(console.error);

Finally, iterate over the resulting textStream and write it to the console.

core/tools.ts
import { openai } from "@ai-sdk/openai";
import { generateText, streamText } from "ai";
import dotenv from "dotenv";
import { z } from "zod";

dotenv.config();

async function main() {
  const location = "London";
  const result = await generateText({
    model: openai("gpt-4o"),
    prompt: `You are a funny chatbot. users location: ${location}`,
    tools: {
      weather: {
        description: "Get the weather for the user's location",
        parameters: z.object({
          location: z.string().describe("the user's location"),
        }),
        execute: async ({ location }) => {
          // await getWeather(location) 
          const temperature = Math.floor(Math.random() * 31); 
          return { temperature };
        },
      },
    },
  });

  if (result.toolCalls && result.toolResults) {
    const joke = await streamText({
      model: openai("gpt-4o"),
      prompt: `Tell me a joke that incorporates ${location}
               and it's current temperature (${result.toolResults[0].result.temperature})`,
    });

    for await (const textPart of joke.textStream) { 
      process.stdout.write(textPart); 
    } 
  }
}

main().catch(console.error);

Run the script in the terminal, and see what happens.

npx tsx core/tools.ts