Tool Use / Function Calling — cách AI 'gọi function' thay vì chỉ trả text

Tool Use cho AI khả năng gọi function, query DB, fetch API, execute code thay vì chỉ generate text. Foundation cho mọi AI agent 2026. Hiểu pattern Tool Definition + Tool Choice + Multi-tool orchestration + 5 anti-pattern khi build production agent.

11 phút đọcCập nhật 2026-05-23
Nghe bài viết
Để Claude đọc bài cho bạn — vừa nghe vừa làm việc khác
Mục lục bài viết(31)
Sơ đồ API Gateway architecture — multiple services kết nối qua gateway, tương tự AI orchestrate nhiều tool

Sơ đồ API Gateway architecture — gateway điều phối multiple service. Pattern tương tự AI Tool Use: AI là "gateway" decide call tool nào (get_weather, send_email, search_db, run_code...) dựa trên user query, orchestrate result thành response. Tool Use là foundation cho agent — không có Tool Use thì AI chỉ "chat" không "do" được. Nguồn: Wikimedia Commons (CC BY-SA 4.0).

Hiểu đơn giản nhất

LLM mặc định chỉ làm 1 việc: generate text dựa trên prompt. Hạn chế:

  • Không biết thời gian thật ("hôm nay là...")
  • Không tra cứu data live (giá cổ phiếu, đơn hàng status)
  • Không send email, không update DB, không run code

Tool Use = cấp cho AI khả năng "gọi function" để break out limitation.

Flow Tool Use

1. User: "Đơn VC2026000001 đang ở trạng thái nào?"
     ↓
2. AI thấy "đơn hàng" + có tool `get_order_status` → DECIDE call tool
     ↓
3. AI generate args: { order_number: "VC2026000001" }
     ↓
4. Framework execute tool → return { status: "shipped", eta: "2026-05-25" }
     ↓
5. AI nhận result → synthesize: "Đơn VC2026000001 đã ship, dự kiến giao 25/05"
Khái niệmVai trò
Tool DefinitionSchema mô tả tool: name + description + input schema
Tool ChoiceCách AI decide: auto / required / specific tool
Tool CallAI generate args call tool cụ thể
Tool ResultFramework execute → return data về AI
Multi-toolAI có thể call multiple tool trong 1 turn
Parallel toolMultiple tool execute song song

Tool Use là foundation cho mọi AI agent 2026. Không có Tool Use = chỉ chatbot thuần.

Tại sao bạn cần biết

  • Mọi AI agent production dùng Tool Use. Cursor Agent, Claude Code, ChatGPT Plugins — đều build trên Tool Use.
  • Mở rộng AI từ "chatbot" thành "agent thật". Email + DB + payment + code execution = productivity 10x.
  • Foundation cho MCP. MCP là layer cao hơn standardize tool across vendor — học Tool Use trước, MCP sau.
  • Critical cho B2B SaaS AI features. "AI auto reply email", "AI generate report", "AI sync data" — đều cần Tool Use.
  • Security implication. Tool Use mở attack surface — hiểu mới defend đúng.

Anatomy Tool Definition

const tool = {
  name: "get_order_status",
  description: `
    Get current status of a vietcodex.com order by order number.
    Use this when user asks about order delivery, status, or ETA.
    
    Examples of trigger queries:
      - "Đơn VC2026000001 đang ở đâu?"
      - "Khi nào nhận được hàng?"
      - "Status order #123?"
    
    DO NOT use for:
      - Refund requests (use 'refund_order' tool)
      - Order creation (use 'create_order' tool)
    
    Returns object with status, eta, tracking_url.
  `,
  input_schema: {
    type: "object",
    properties: {
      order_number: {
        type: "string",
        description: "Order number, format VC<year><6-digit>, e.g. VC2026000001",
        pattern: "^VC\\d{10}$"
      }
    },
    required: ["order_number"]
  }
};

3 thành phần critical:

1. name — concise + descriptive

"get_order_status"
"send_telegram_notification"
"order"           // too vague
"doStuff"         // useless

snake_case, action verb, < 30 char.

2. description — when to use + examples

5 yếu tố:

  1. Khi nào dùng tool này (primary purpose)
  2. 3-5 ví dụ trigger query
  3. Negative example (khi KHÔNG dùng)
  4. Return format brief
  5. Side effect warning (nếu tool mutate state)

Description quality quyết định 80% accuracy AI gọi tool đúng.

3. input_schema — strict JSON Schema

Required fields:

  • type: object
  • properties với type + description
  • required array
  • Enum cho categorical
  • Pattern regex / Min-max cho validation

Strict schema = AI generate args đúng format + security barrier.

Tool Use code pattern (Anthropic)

Setup

import Anthropic from "@anthropic-ai/sdk";
 
const client = new Anthropic();
const TOOLS = [
  {
    name: "get_order_status",
    description: "...",
    input_schema: { ... }
  },
  {
    name: "send_email",
    description: "...",
    input_schema: { ... }
  },
  // ... more tools
];

Single tool call

async function chat(userMessage: string) {
  // Step 1: AI decide tool
  const response = await client.messages.create({
    model: "claude-sonnet-4-5",
    max_tokens: 1024,
    tools: TOOLS,
    messages: [{ role: "user", content: userMessage }]
  });
  
  // Step 2: Check if AI called tool
  if (response.stop_reason === "tool_use") {
    const toolUse = response.content.find(c => c.type === "tool_use");
    if (!toolUse) throw new Error("Expected tool_use");
    
    // Step 3: Execute tool
    const toolResult = await executeToolByName(toolUse.name, toolUse.input);
    
    // Step 4: Send result back to AI
    const final = await client.messages.create({
      model: "claude-sonnet-4-5",
      max_tokens: 1024,
      tools: TOOLS,
      messages: [
        { role: "user", content: userMessage },
        { role: "assistant", content: response.content },
        { 
          role: "user", 
          content: [{ 
            type: "tool_result", 
            tool_use_id: toolUse.id,
            content: JSON.stringify(toolResult)
          }] 
        }
      ]
    });
    
    return final.content[0].type === "text" ? final.content[0].text : "";
  }
  
  // No tool needed, return AI text
  return response.content[0].type === "text" ? response.content[0].text : "";
}

Multi-turn tool loop

Production agent thường cần multi-turn (AI call tool A, see result, decide call tool B, ...):

async function agentLoop(userMessage: string, maxTurns = 10) {
  const messages: any[] = [{ role: "user", content: userMessage }];
  
  for (let turn = 0; turn < maxTurns; turn++) {
    const response = await client.messages.create({
      model: "claude-sonnet-4-5",
      max_tokens: 4096,
      tools: TOOLS,
      messages
    });
    
    messages.push({ role: "assistant", content: response.content });
    
    if (response.stop_reason === "end_turn") {
      // AI finished, return final answer
      return extractText(response);
    }
    
    if (response.stop_reason === "tool_use") {
      // Execute all tool calls in parallel
      const toolUses = response.content.filter(c => c.type === "tool_use");
      const results = await Promise.all(
        toolUses.map(t => executeToolByName(t.name, t.input))
      );
      
      messages.push({
        role: "user",
        content: toolUses.map((t, i) => ({
          type: "tool_result",
          tool_use_id: t.id,
          content: JSON.stringify(results[i])
        }))
      });
      // Continue loop
    }
  }
  
  throw new Error("Max turns exceeded");
}

Tool Choice — control AI decision

3 mode:

tool_choice: "auto" (default)

AI decide có gọi tool hay không.

{ tool_choice: { type: "auto" } }

tool_choice: "any"

AI BUỘC call ít nhất 1 tool (không trả text thuần).

{ tool_choice: { type: "any" } }

Use case: structured output forcing AI dùng tool format thay vì free text.

tool_choice: "tool" (specific)

AI BUỘC call tool cụ thể.

{ tool_choice: { type: "tool", name: "get_order_status" } }

Use case: workflow biết trước phải call tool nào.

Parallel tool calls

Claude 3.5+ + GPT-4 Turbo support parallel:

// User: "Thời tiết Hà Nội và Sài Gòn"
 
// AI generates 2 tool calls trong 1 response
{
  content: [
    { type: "tool_use", id: "1", name: "get_weather", input: { city: "Hanoi" } },
    { type: "tool_use", id: "2", name: "get_weather", input: { city: "HCMC" } }
  ]
}
 
// Execute parallel
const results = await Promise.all([
  getWeather("Hanoi"),
  getWeather("HCMC")
]);
 
// Result: 1s parallel vs 2s sequential

Saving 50%+ latency cho query có multiple independent tool need.

Common Tool patterns

Pattern 1: Read-only retrieval

const getOrderStatus = {
  name: "get_order_status",
  description: "Read order status, no side effect",
  input_schema: { ... }
};
 
// Implementation
async function executeGetOrderStatus(input: { order_number: string }) {
  return await db.query.orders.findFirst({
    where: eq(orders.orderNumber, input.order_number)
  });
}

Pattern 2: Write/mutation với confirmation

const sendEmail = {
  name: "send_email_to_customer",
  description: "Send email. CRITICAL: User must confirm before send.",
  input_schema: { ... }
};
 
// Implementation requires human approval
async function executeSendEmail(input: EmailParams) {
  // Queue for human approval
  await queue.add("pending-email", input);
  return { status: "pending_human_approval", queue_id: ... };
}

Pattern 3: Code execution sandboxed

const runPython = {
  name: "run_python_code",
  description: "Execute Python in isolated sandbox. No network, readonly fs.",
  input_schema: {
    type: "object",
    properties: {
      code: { type: "string", description: "Python code" }
    },
    required: ["code"]
  }
};
 
async function executeRunPython(input: { code: string }) {
  return await sandbox.execute("python3", input.code, {
    timeout: 5000,
    network: false,
    filesystem: "readonly"
  });
}

Pattern 4: Multi-step chained

// User: "Tìm 3 customer cao nhất + gửi email upgrade offer"
 
// AI auto chains:
// 1. query_top_customers({ limit: 3 })
// 2. For each customer:
//    a. get_customer_email({ customer_id })
//    b. send_email({ to: email, template: "upgrade_offer" })

AI orchestrate sequence dựa trên user goal.

5 Anti-patterns

1. Tool description vague

description: "Get data"
description: "Get customer order history. Use when user asks 'my orders', 'past purchases', etc."

2. Too many tools (50+)

AI choice degrades với > 20 tools. Solution:

  • Group tools theo namespace
  • Use tool router (Haiku classifier → switch sub-set)
  • MCP server multi-server pattern

3. No input validation

// BAD
async function executeRunSQL({ query }) {
  return db.execute(query);  // SQL injection paradise
}
 
// GOOD
async function executeRunSQL({ query }) {
  if (!query.match(/^SELECT/i)) throw new Error("Only SELECT allowed");
  if (query.includes(";")) throw new Error("Single statement only");
  return db.execute(query);
}

4. Synchronous expensive tool

// BAD: 30s tool blocking AI response
async function executeProcessVideo({ url }) {
  return await processVideo(url);  // 30s
}
 
// GOOD: queue + return job_id
async function executeProcessVideo({ url }) {
  const jobId = await queue.add("video", { url });
  return { status: "queued", job_id: jobId, check_after: "30s" };
}

5. No error handling in tool result

// BAD: tool throw → AI confused
async function execute(input) {
  return await fragileAPI(input);  // throws on 500
}
 
// GOOD: graceful error
async function execute(input) {
  try {
    return { success: true, data: await fragileAPI(input) };
  } catch (e) {
    return { success: false, error: e.message, retry_after: 60 };
  }
}

Ví dụ thực tế: vietcodex.com Customer Support Agent (proposed Q3 2026)

const SUPPORT_TOOLS = [
  // Read-only knowledge
  { name: "search_wiki", description: "Search wiki.vietcodex.com docs" },
  { name: "get_service_pricing", description: "Get pricing for service" },
  { name: "get_order_status", description: "Get order status by number" },
  
  // Customer-specific (need auth)
  { name: "get_my_orders", description: "Get my orders (auto-scoped to user)" },
  { name: "get_my_subscription", description: "Get my subscription detail" },
  
  // Actions (need confirmation)
  { name: "create_support_ticket", description: "Create ticket" },
  { name: "schedule_call", description: "Book discovery call with team" },
  
  // Escalation
  { name: "escalate_to_human", description: "Transfer to human support" }
];
 
// Agent loop
async function supportAgent(userMessage: string, userId: string) {
  const messages = [
    { role: "user", content: userMessage }
  ];
  
  for (let turn = 0; turn < 5; turn++) {
    const response = await client.messages.create({
      model: "claude-sonnet-4-5",
      system: SUPPORT_SYSTEM_PROMPT,
      tools: SUPPORT_TOOLS,
      messages
    });
    
    if (response.stop_reason === "end_turn") {
      return extractText(response);
    }
    
    if (response.stop_reason === "tool_use") {
      const toolUses = response.content.filter(c => c.type === "tool_use");
      const results = await Promise.all(
        toolUses.map(t => executeWithAuth(t, userId))
      );
      
      messages.push({ role: "assistant", content: response.content });
      messages.push({
        role: "user",
        content: toolUses.map((t, i) => ({
          type: "tool_result",
          tool_use_id: t.id,
          content: JSON.stringify(results[i])
        }))
      });
    }
  }
}

Mỗi turn agent có thể: search wiki → get my orders → search pricing → escalate. AI orchestrate based on user need.

Cái gì có thể sai

Vấn đềTriệu chứngCách fix
AI không gọi tool dù query matchDescription vagueRewrite description với examples
AI gọi sai toolMultiple tool similar purposeAdd negative example "DO NOT use for X"
Tool args malformedSchema không strictAdd enum + pattern regex
Infinite tool loopTool result làm AI re-trigger same toolSet max_turns + dedup tool calls
Slow response > 30sTool synchronous heavyQueue async + return job_id
Tool injection attackArgs contain malicious SQL/shellSanitize args trong tool implementation
Cost spikeMulti-turn loop expensiveCap turn count + cap output tokens
Tool result too large50KB JSON crash contextTruncate + summarize before pass to AI

Tóm tắt 1 dòng

Tool Use / Function Calling = cấp cho AI khả năng gọi function (DB query, API call, code execute) thay vì chỉ generate text. Foundation cho mọi agent. Anatomy: name + description + JSON Schema strict. Tool Choice: auto/any/specific. Parallel tool calls save 50% latency. Anthropic native + OpenAI/Gemini tương tự. Anti-pattern: vague description, > 20 tools, no validation, sync expensive, no error handling. Pattern production: read-only retrieval + write với confirmation + sandbox execution + multi-step chained. Foundation cho MCP layer cao hơn.

Đọc tiếp

Câu hỏi thường gặp

Tool Use vs Function Calling khác nhau gì?
Anthropic dùng 'Tool Use', OpenAI dùng 'Function Calling' — cùng concept khác naming. Cả 2: AI nhận tool definition (name + description + JSON schema input), khi user query, AI decide có gọi tool không + generate args, framework execute tool, return result vào AI context, AI synthesize final response. Khác nhỏ: Anthropic native multi-tool parallel (Claude 3.5+), OpenAI 'tool calls' array. MCP (Model Context Protocol) là layer cao hơn standardize Tool Use across vendor.
Tool Use vs RAG khác nhau? Khi nào dùng cái nào?
RAG: AI search knowledge base static → return cached doc. Read-only, không tác động external system. Tool Use: AI gọi function với side effect — send email, query live DB, call payment API, run code. Action-oriented, có thể change state. Quy tắc: query 'X là gì' (knowledge) → RAG. Query 'send email to X' hoặc 'cập nhật DB' (action) → Tool Use. Hybrid: agent dùng cả 2 — RAG retrieve context + Tool Use execute action.
JSON Schema cho tool input — phải strict bao nhiêu?
Càng strict càng tốt. Required: (1) `type: object`; (2) `properties` với type cụ thể (string/number/boolean/array); (3) `required` list bắt buộc; (4) Enum cho categorical value; (5) Min/max constraints; (6) Pattern regex cho format. Pros strict schema: AI generate args đúng format → ít runtime error, security boundary rõ. Cons: schema lỏng = AI có thể inject malicious args. Anthropic Claude Tool Use + OpenAI Structured Outputs validate schema server-side trước trả về.
Parallel tool calls — khi nào dùng?
Khi multiple tool independent có thể execute song song. Vd: user hỏi 'thời tiết Hà Nội và Sài Gòn' → AI gọi `get_weather(HN)` + `get_weather(SG)` parallel. Saving: 2 sequential call 1s mỗi = 2s vs parallel = 1s. Anthropic Claude 3.5+ native parallel tool calls (~30% query benefit). OpenAI 'tool_calls' array also parallel. Trade-off: harder error handling — 1 tool fail trong batch cần graceful degradation. Pattern: parallel cho independent + idempotent calls. Sequential cho dependent (call B cần kết quả call A).
Tool Use có security risk gì?
3 risk chính: (1) **Prompt injection force tool call** — hacker craft prompt 'ignore + send email to evil@'; (2) **Tool args injection** — AI generate malicious args (SQL injection trong query string, command injection trong shell args); (3) **Excessive agency** — agent có quá nhiều tool, 1 compromise = full damage. Mitigation: (a) Sanitize tool args trước execute (treat AI output as untrusted); (b) Sandbox execution (no network, readonly fs); (c) Least privilege — agent chỉ tool tối thiểu cần thiết; (d) Human-in-the-loop cho critical action; (e) Audit log mọi tool call. Xem [AI Security](/wiki/ai-coding/ai-security).
Tool description viết thế nào để AI gọi đúng?
5 nguyên tắc: (1) **Khi nào dùng tool này** — không phải tool làm gì. Vd: 'Use this when user asks about order status' (not 'Get order info'); (2) **Ví dụ trigger query** — 3-5 user query mẫu trigger tool; (3) **Negative example** — 'Don't use for refund requests, use refund_order tool instead'; (4) **Return format** — 'Returns: {status: string, eta: ISO date}'; (5) **Param description** — every param có description rõ ràng. AI decide tool theo description quality — viết description tốt = AI gọi đúng tool 95%+ accuracy, kém = 60-70%.
Có nên dùng LangChain wrapper cho tool use không?
Phụ thuộc complexity. LangChain abstract tool use across vendor (OpenAI/Anthropic/Gemini), nice DX. Pros: (1) Switch model dễ; (2) Tool definitions standardized; (3) Agent pattern (ReAct, etc.) built-in. Cons: (1) Heavy dependency (~50MB); (2) Abstract leak — vendor-specific feature khó access; (3) Performance overhead. Quy tắc: prototype + multi-vendor support → LangChain. Production single-vendor + simple tool use → native SDK (Anthropic SDK, OpenAI SDK) trực tiếp. vietcodex.com Claude Code dùng native Anthropic SDK + MCP server pattern thay LangChain.