Skip to main content
Here’s how to set up tool calling in Next.js. Make sure you have ai and zod installed.

Install ai sdk and zod

npm install ai zod
In your backend, where your agent is running, import tool and stepCountIs from ai and import zod. Note: you probably already imported streamText and ModelMessage
import { streamText, ModelMessage, tool, stepCountIs } from 'ai';
import z from 'zod'
Inside the callback of your layercode streamResponse in the case of a message received, initialize a tool. For instance, weather
  const weather = tool({
    description: 'Get the weather in a location',
    inputSchema: z.object({
      location: z.string().describe('The location to get the weather for')
    }),
    execute: async ({ location }) => ({
      location,
      temperature: 72 + Math.floor(Math.random() * 21)
    })
  });
Then set
tools: {
  weather
}
as a property inside streamText You should also set these properties
toolChoice: 'auto',
stopWhen: stepCountIs(10),
You can find more info in the ai sdk docs. Once you have this, make sure your prompt mentions the tool is available. For example add “you can use the weather tool to find the weather for a given location.” And now, it should let you query the weather and you’ll see it’s a different temperature (between 72 and 92) each time because it has some randomness in the function.

Next steps: telling the user that tool calling is happening

One thing many many developers wish to do is update the user that tool calling is happening so they don’t expect an immediate response. To do this, your tools can notify the client that there is a tool call happening. This guide will show you how you can do that.

Sending speech to the user to tell them a call is happening.

If you anticipate a long tool call, you may want to send a spoken message to them, such as “just a moment, let me grab that for you.”. With ai sdk, you can do that by calling Layercode’s stream.tts at the start of your execute function. Note that the tool must be defined inside your Layercode streamResponse callback function so that it has access to stream.
        const weather = tool({
          description: 'Get the weather in a location',
          inputSchema: z.object({
            location: z.string().describe('The location to get the weather for')
          }),
          execute: async ({ location }) => {
            stream.tts("Just a moment, let me grab that for you.");
            // do something to get the weather

            return {
              location,
              temperature: 72 + Math.floor(Math.random() * 21) - 10
            };
          }
        });
I