Sử Dụng Tools & Function Calling

Cách agent gọi tools, function calling pattern, và tích hợp với OpenAI API

Tool Use Design Pattern

Tool Use là pattern quan trọng nhất trong AI Agents — cho phép LLM vượt ra ngoài việc generate text để thực sự tương tác với thế giới bên ngoài.

Khi Nào Cần Tool Use?

  • Data Retrieval: Truy vấn database, search APIs, đọc files
  • Code Execution: Chạy code, xử lý data
  • Workflow Automation: Gửi email, tạo tickets, deploy
  • Customer Support: Truy vấn CRM, knowledge base

Function Calling: Cơ Chế Hoạt Động

Function calling gồm 3 bước:

1. Định nghĩa functions (schema) → Gửi cho LLM
2. LLM quyết định function nào cần gọi + arguments
3. Code thực thi function → Trả kết quả về LLM

Bước 1: Định Nghĩa Tool Schema

import OpenAI from "openai";

const client = new OpenAI();

const tools: OpenAI.ChatCompletionTool[] = [
  {
    type: "function",
    function: {
      name: "get_current_time",
      description: "Lấy thời gian hiện tại tại một thành phố",
      parameters: {
        type: "object",
        properties: {
          location: {
            type: "string",
            description: "Tên thành phố, ví dụ: 'Ho Chi Minh City'"
          }
        },
        required: ["location"]
      }
    }
  }
];

Bước 2: LLM Quyết Định Gọi Tool

const messages: OpenAI.ChatCompletionMessageParam[] = [
  { role: "user", content: "Mấy giờ rồi ở Sài Gòn?" }
];

const response = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages,
  tools,
  tool_choice: "auto" // LLM tự quyết định
});

// LLM trả về tool_calls thay vì text
const toolCalls = response.choices[0].message.tool_calls;
// → [{ function: { name: "get_current_time", arguments: '{"location":"Ho Chi Minh City"}' } }]

Bước 3: Thực Thi và Trả Kết Quả

// Implement actual function
function getCurrentTime(location: string): string {
  const timezones: Record<string, string> = {
    "ho chi minh city": "Asia/Ho_Chi_Minh",
    "tokyo": "Asia/Tokyo",
    "new york": "America/New_York"
  };

  const tz = timezones[location.toLowerCase()];
  if (!tz) return JSON.stringify({ error: "Unknown location" });

  const time = new Date().toLocaleString("vi-VN", { timeZone: tz });
  return JSON.stringify({ location, current_time: time });
}

// Xử lý tool calls
if (toolCalls) {
  // Thêm assistant message (chứa tool_calls)
  messages.push(response.choices[0].message);

  for (const call of toolCalls) {
    const args = JSON.parse(call.function.arguments);
    const result = getCurrentTime(args.location);

    // Thêm tool result
    messages.push({
      role: "tool",
      tool_call_id: call.id,
      content: result
    });
  }

  // Gọi LLM lần 2 với kết quả tool
  const finalResponse = await client.chat.completions.create({
    model: "gpt-4o-mini",
    messages
  });

  console.log(finalResponse.choices[0].message.content);
  // → "Hiện tại ở Sài Gòn là 15:30 chiều."
}

Tool Use Với Vercel AI SDK

Vercel AI SDK đơn giản hoá flow trên đáng kể:

import { generateText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";

const result = await generateText({
  model: openai("gpt-4o-mini"),
  tools: {
    getCurrentTime: tool({
      description: "Lấy thời gian hiện tại tại một thành phố",
      parameters: z.object({
        location: z.string().describe("Tên thành phố")
      }),
      execute: async ({ location }) => {
        const time = new Date().toLocaleString("vi-VN", {
          timeZone: "Asia/Ho_Chi_Minh"
        });
        return { location, current_time: time };
      }
    }),
    searchWeb: tool({
      description: "Tìm kiếm thông tin trên web",
      parameters: z.object({
        query: z.string().describe("Từ khoá tìm kiếm")
      }),
      execute: async ({ query }) => {
        // Tích hợp search API
        return { results: [`Kết quả cho: ${query}`] };
      }
    })
  },
  maxSteps: 5, // Agent loop tự động
  prompt: "Mấy giờ rồi ở Sài Gòn?"
});

console.log(result.text);
// Vercel AI SDK tự handle tool calling loop!

So Sánh: Raw OpenAI vs Vercel AI SDK

AspectOpenAI RawVercel AI SDK
Tool definitionJSON SchemaZod (type-safe)
Tool executionTự handle loopTự động (maxSteps)
Type safetyKhông (tự infer types)
StreamingTự implementBuilt-in
Multi-providerChỉ OpenAIOpenAI, Anthropic, Google…

Nhiều Tools Cùng Lúc

Agent thông minh khi có nhiều tools sẽ tự chọn tool phù hợp:

const result = await generateText({
  model: openai("gpt-4o-mini"),
  tools: {
    getWeather: tool({ /* ... */ }),
    searchFlights: tool({ /* ... */ }),
    bookHotel: tool({ /* ... */ }),
    translateText: tool({ /* ... */ })
  },
  maxSteps: 10,
  prompt: "Tìm cho tôi chuyến bay đi Tokyo tuần sau, thời tiết ra sao?"
  // Agent sẽ tự gọi: searchFlights + getWeather
});

Best Practices

1. Mô Tả Tool Rõ Ràng

// ❌ Xấu
tool({ description: "Tìm kiếm" })

// ✅ Tốt
tool({
  description: "Tìm kiếm sản phẩm trong database. Trả về danh sách sản phẩm kèm giá, mô tả, và rating."
})

2. Validate Input

parameters: z.object({
  email: z.string().email("Email không hợp lệ"),
  age: z.number().min(0).max(150),
  date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/)
})

3. Handle Errors Gracefully

execute: async ({ query }) => {
  try {
    const data = await fetchData(query);
    return { success: true, data };
  } catch (error) {
    return {
      success: false,
      error: "Không thể truy vấn dữ liệu. Vui lòng thử lại."
    };
  }
}

Tổng Kết

  • Function Calling là pattern nền tảng: Schema → LLM chọn tool → Execute → Return
  • Vercel AI SDK đơn giản hoá tool use với Zod schemas và auto tool loop
  • Mô tả tools rõ ràng, chi tiết để LLM chọn đúng tool
  • Luôn validate inputhandle errors gracefully