DeepAgent

Vercel AI SDK

Use @deepagent/weather with Vercel AI SDK for weather-aware AI applications

Weather Tool - Vercel AI SDK Integration

Learn how to integrate the @deepagent/weather tool with the Vercel AI SDK for building weather-aware AI applications.

Prerequisites

Installation

npm install @deepagent/weather ai @ai-sdk/openai
yarn add @deepagent/weather ai @ai-sdk/openai
pnpm add @deepagent/weather ai @ai-sdk/openai

Environment Setup

WEATHER_API_KEY=your_weather_api_key_here
OPENAI_API_KEY=your_openai_api_key_here

Basic Integration

Tool Definition

import { WeatherClient } from '@deepagent/weather'
import { tool } from 'ai'
import { z } from 'zod'

export const weatherTool = tool({
  description: 'Get the weather in a location',
  inputSchema: z.object({
    location: z.string().describe('The location to get the weather for'),
  }),
  execute: async function ({ location }) {
    try {
      const cleanedLocation = location.trim().toLowerCase()
      const weather = new WeatherClient()
      const res = await weather.getCurrentWeather(cleanedLocation)

      if (!res || !res.current || !res.location) {
        return { error: 'Sorry, we don’t have weather data for that location.' }
      }

      return res;

    } catch (err: any) {
      const status = err?.response?.status || err?.status

      if (status === 400) {
        return {
          error: `Sorry, we don’t have weather data for "${location}".`,
        }
      }

      return {
        error: `Something went wrong while fetching weather for "${location}". Please try again later.`,
      }
    }
  }
});

Chat Completion with Tools

import { generateText } from 'ai'
import { openai } from '@ai-sdk/openai'

const result = await generateText({
  model: openai('gpt-4-turbo'),
  messages: [
    {
      role: 'user',
      content: 'What\'s the weather like in Tokyo today?'
    }
  ],
  tools: {
    getWeather: tool({
  description: 'Get the weather in a location',
  inputSchema: z.object({
    location: z.string().describe('The location to get the weather for'),
  }),
  execute: async function ({ location }) {
    try {
      const cleanedLocation = location.trim().toLowerCase()
      const weather = new WeatherClient()
      const res = await weather.getCurrentWeather(cleanedLocation)

      if (!res || !res.current || !res.location) {
        return { error: 'Sorry, we don’t have weather data for that location.' }
      }

      return res;

    } catch (err: any) {
      const status = err?.response?.status || err?.status

      if (status === 400) {
        return {
          error: `Sorry, we don’t have weather data for "${location}".`,
        }
      }

      return {
        error: `Something went wrong while fetching weather for "${location}". Please try again later.`,
      }
    }
  }
}),
  },
})

console.log(result.text)

Streaming with Tools

import { weatherTool } from '@/lib/weather';
import { openai } from '@ai-sdk/openai';
import { convertToModelMessages, streamText, UIMessage } from 'ai';

export const maxDuration = 30;

export async function POST(req: Request) {
  const { messages }: { messages: UIMessage[] } = await req.json();

  const result = streamText({
    model: openai('gpt-5'),
    system: 'You are a helpful assistant.',
    messages: convertToModelMessages(messages),
    toolChoice: 'auto',
    tools: {
      getWeather: weatherTool,
    },
  });

  return result.toUIMessageStreamResponse();
}

Next.js API Route Example

app/api/chat/route.ts
import { weatherTool } from '@/lib/weather';
import { openai } from '@ai-sdk/openai';
import { convertToModelMessages, streamText, UIMessage } from 'ai';

export const maxDuration = 30;

export async function POST(req: Request) {
  const { messages }: { messages: UIMessage[] } = await req.json();

  const result = streamText({
    model: openai('gpt-5'),
    system: 'You are a helpful assistant.',
    messages: convertToModelMessages(messages),
    toolChoice: 'auto',
    tools: {
      getWeather: weatherTool,
    },
  });

  return result.toUIMessageStreamResponse();
}

React Hook Usage

'use client';

import { useChat } from '@ai-sdk/react';
import {
  DefaultChatTransport,
  lastAssistantMessageIsCompleteWithToolCalls,
} from 'ai';
import { useState } from 'react';

export default function Chat() {
  const { messages, sendMessage } = useChat({
    transport: new DefaultChatTransport({
      api: '/api/chat',
    }),

    sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,

    async onToolCall({ toolCall }) {
      // Check if it's a dynamic tool first for proper type narrowing
      if (toolCall.dynamic) {
        return;
      }
    },
  });
  const [input, setInput] = useState('');

  return (
    <>
      {messages?.map(message => (
        <div key={message.id}>
          <strong>{`${message.role}: `}</strong>
          {message.parts.map(part => {
            switch (part.type) {
              // render text parts as simple text:
              case 'text':
                return part.text;

              case 'tool-getWeather': {
                const callId = part.toolCallId;

                switch (part.state) {
                  case 'input-streaming':
                    return (
                      <pre key={callId}>{JSON.stringify(part, null, 2)}</pre>
                    );
                  case 'input-available':
                    return (
                      <div key={callId}>
                        Getting weather information for {(part.input as any).location}...
                      </div>
                    );
                  case 'output-available':
                    return (
                      <div key={callId}>
                        Weather in {(part.input as any).location} city : {JSON.stringify(part.output, null, 2)}
                      </div>
                    );
                  case 'output-error':
                    return (
                      <div key={callId}>
                        Error getting weather for {(part.input as any).location}:{' '}
                        {part.errorText}
                      </div>
                    );
                }
                break;
              }
            }
          })}
          <br />
        </div>
      ))}

      <form
        onSubmit={e => {
          e.preventDefault();
          if (input.trim()) {
            sendMessage({ text: input });
            setInput('');
          }
        }}
      >
        <input value={input} onChange={e => setInput(e.target.value)} />
      </form>
    </>
  );
}

Best Practices

  1. Always handle errors gracefully - Weather APIs can be unreliable
  2. Cache responses - Avoid unnecessary API calls for the same location
  3. Validate location input - Ensure the location string is meaningful
  4. Rate limiting - Be mindful of API rate limits
  5. Fallback data - Consider providing cached or default weather information

Example Applications

  • Weather-aware travel planning chatbot
  • Smart home automation assistant
  • Agricultural advisory system
  • Event planning assistant with weather considerations