Tool Calling / Function Calling — এজেন্ট কীভাবে বাইরের জগতের সাথে কাজ করে
শেখার ডায়েরি

Tool Calling / Function Calling — এজেন্ট কীভাবে বাইরের জগতের সাথে কাজ করে

Z
জাহিদ হাসান তন্ময়
২৮ সেপ্টেম্বর, ২০২৬
9 মিনিটের পড়া
🇬🇧 Read in English
|
0 views
অডিও ওভারভিউ ও পডকাস্ট
~১ মিনিট কুইক ওভারভিউ
0%

আগের পোস্টে এজেন্টের ভেতরটা খুলে চারটা অংশ দেখিয়েছিলাম — Brain, Memory, Tools আর সব জোড়া লাগানো Loop। Tools নিয়ে ওখানে মাত্র কয়েক লাইন লিখেছিলাম। এবার সেই বাক্সের ভেতরে ঢুকব: শুধু লেখা তৈরি করতে পারা একটা মডেল কীভাবে হঠাৎ আজকের আবহাওয়া দেখতে পারে বা টাকা কনভার্ট করে দিতে পারে।

কোনো tool ছাড়া একটা সাধারণ চ্যাটবটকে জিজ্ঞেস করুন, “ঢাকায় এখন আবহাওয়া কেমন, আর আজ ৫০০ ডলার কত টাকা?” সে দুটোরই উত্তর দিয়ে দেবে, কোনো দ্বিধা ছাড়াই। তাপমাত্রাটা হবে আন্দাজ। বিনিময় হারটা হবে মডেল যখন ট্রেন হয়েছিল তখনকার কোনো সংখ্যা, অথচ বলা হবে যেন সেটা আজকের। যা বলল তার একটাও কোনো আসল তথ্যের সাথে মিলিয়ে দেখা হয়নি।

Tool Calling আসলে কী?

Tool calling, যাকে function calling-ও বলা হয়, এমন একটা ব্যবস্থা যেখানে language model শুধু লেখা তৈরি করার বদলে একটা নির্দিষ্ট, আগে থেকে বানানো ফাংশন structured argument সহ চাইতে পারে। আপনার কোড সেই ফাংশনটা আসল ডেটা দিয়ে চালায় আর ফলাফল ফেরত পাঠায়, মডেল সেটা পড়ে বাকি উত্তর দেয়। শুধু লিখতে পারা একটা মডেলকে যাচাই করতে, হিসাব করতে আর কাজ করতে পারা মডেলে বদলে দেয় এই একটা জিনিসই।

একটা Tool-এর ভেতরে কী থাকে

Tool-এর সংজ্ঞা মডেলকে কোড লিখতে শেখায় না। সে শুধু জানায় সে কী চাইতে পারে, তিনটা অংশে:

  • name — ছোট্ট একটা identifier, যেমন get_weather।
  • description — সহজ ভাষায় লেখা, ঠিক কখন এটা ব্যবহার করতে হবে। মডেল কখনো আপনার কোড পড়ে না, শুধু এই লেখাটাই পড়ে, তাই এটা এমন এক পাঠকের জন্য লেখা API ডকুমেন্টেশনের মতো কাজ করে যে কিছু জিজ্ঞেস করার সুযোগ পায় না।
  • input_schema — একটা JSON Schema, যেখানে argument-গুলো কী, কী টাইপ, আর কোনগুলো required তা লেখা থাকে।

এই তিনটার যেকোনো একটা অস্পষ্ট রাখলে মডেল হয় দরকারি tool এড়িয়ে যায়, নয় ভুল tool বেছে নেয়। tool calling-এর এই অংশটার সাথে কোডের কোনো সম্পর্ক নেই, পুরোটাই স্পষ্ট লেখার ব্যাপার।

এক Turn-এ দুটো Tool: Parallel Call কীভাবে কাজ করে

মডেলের একটা মাত্র response একটা tool চাওয়ার মধ্যেই সীমাবদ্ধ থাকে না। কোনো প্রশ্নের জন্য দুটো আলাদা তথ্য লাগলে, মডেল একটা tool চেয়ে ফলাফলের জন্য অপেক্ষা করে তারপর আরেকটা চাওয়ার বদলে একই turn-এ দুটোই চাইতে পারে।

📊 Architecture DiagramArchitecture Flow
Interactive diagram rendering...
flowchart TD
    U[ব্যবহারকারী একসাথে দুটো জিনিস জিজ্ঞেস করে] --> B[Brain মেসেজ পড়ে]
    B -->|আবহাওয়া লাগবে| W[get_weather]
    B -->|টাকার হিসাব লাগবে| C[convert_currency]
    W --> R[দুটো ফলাফলই জমা হয়]
    C --> R
    R --> B2[Brain দুটো ফলাফলই পড়ে]
    B2 --> F[একটাই চূড়ান্ত উত্তর]
System architecture specification and node flow: flowchart TD U[ব্যবহারকারী একসাথে দুটো জিনিস জিজ্ঞেস করে] --> B[Brain মেসেজ পড়ে] B -->|আবহাওয়া লাগবে| W[get_weather] B -->|টাকার হিসাব লাগবে| C[convert_currency] W --> R[দুটো ফলাফলই জমা হয়] C --> R R --> B2[Brain দুটো ফলাফলই পড়ে] B2 --> F[একটাই চূড়ান্ত উত্তর]

Flow-এর সারসংক্ষেপ: Brain এক turn-এই একাধিক tool চাইতে পারে। আপনার কোড প্রতিটা চালায়, সবগুলোর ফলাফল রেডি না হওয়া পর্যন্ত অপেক্ষা করে, আর সবকিছু একসাথে ফেরত পাঠায়, তারপর Brain এগিয়ে যায়।

এটা অনেকটা এক ফাঁকে দুটো errand সারার মতো — বাজারের লিস্টে দুধ আর ডিম দুটোই লেখা থাকলে দোকানদার দুটো আলাদা ট্রিপে না গিয়ে একবারেই দুটো তাক থেকে জিনিস তুলে ফেরত আসেন। মডেলও তেমনি একবারে যতগুলো তথ্য দরকার সব চেয়ে নেয়, একটা একটা করে জিজ্ঞেস করে না।

শেষ কথাটা যতটা সাধারণ শোনাচ্ছে, ততটা নয়। একই turn-এ মডেল যতগুলো tool চায়, প্রতিটার উত্তর ঠিক পরের মেসেজেই দিতে হয়, প্রতিটার id মিলিয়ে। একটা বাদ পড়লে কথোপকথনই আর এগোতে পারে না — এই নিয়েই একটু পরে আসছি।

মডেলকে কোন Tool ব্যবহার করতে বলবেন

ডিফল্টভাবে মডেল নিজেই ঠিক করে কোনো tool লাগবে কিনা, লাগলে কোনটা — একে বলে auto, আর প্রায় সব ক্ষেত্রেই এটাই ঠিক আছে। আরও নিয়ন্ত্রণ চাইলে তিনটা অপশন আছে:

  • { type: 'any' } — মডেলকে অবশ্যই কোনো না কোনো tool চাইতে হবে, কোনটা সেটা সে ঠিক করবে।
  • { type: 'tool', name: 'get_weather' } — মডেলকে এই নির্দিষ্ট tool-ই চাইতে হবে।
  • { type: 'none' } — এই turn-এ মডেল কোনো tool চাইতে পারবে না, যদিও tool-এর তালিকা তখনও যুক্ত থাকে। শেষ ধাপে যখন শুধু পরিষ্কার লেখা উত্তর চান, তখন এটা কাজে লাগে।

একটা সতর্কতা জেনে রাখুন ব্যবহার করার আগে: any বা নির্দিষ্ট নাম দিয়ে জোর করা extended thinking-এর সাথে একসাথে চলে না। thinking চালু থাকলে ওই turn-এ শুধু auto আর none-ই সমর্থিত।

একটা কাজের উদাহরণ: দুটো Tool, একটা প্রশ্ন

এই এজেন্ট আবহাওয়া আর টাকার হিসাব — দুটো আলাদা tool দিয়ে উত্তর দেয়, একটা দিয়ে নয়। npm install @anthropic-ai/sdk দিয়ে SDK ইনস্টল করুন, ANTHROPIC_API_KEY সেট করুন, ফাইলটা agent/tool-calling.ts নামে সেভ করে npx tsx agent/tool-calling.ts চালান।

ts
// agent/tool-calling.ts
import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic();

const weatherData: Record<string, { condition: string; temp_c: number }> = {
  Dhaka: { condition: 'humid and cloudy', temp_c: 31 },
  Chittagong: { condition: 'light rain', temp_c: 29 },
};

const rates: Record<string, number> = {
  USD_BDT: 122.5,
  BDT_USD: 1 / 122.5,
};

const tools: Anthropic.Tool[] = [
  {
    name: 'get_weather',
    description:
      'Get the current weather condition and temperature in Celsius for a named city. Use this whenever the user asks about weather, temperature, or whether it will rain somewhere.',
    input_schema: {
      type: 'object',
      properties: {
        city: { type: 'string', description: 'City name, e.g. Dhaka' },
      },
      required: ['city'],
    },
  },
  {
    name: 'convert_currency',
    description:
      'Convert an amount from one currency to another using the current exchange rate. Use this whenever the user asks how much money is worth in a different currency.',
    input_schema: {
      type: 'object',
      properties: {
        amount: { type: 'number' },
        from: { type: 'string', description: 'Three-letter currency code, e.g. USD' },
        to: { type: 'string', description: 'Three-letter currency code, e.g. BDT' },
      },
      required: ['amount', 'from', 'to'],
    },
  },
];

function getWeather(city: string) {
  const data = weatherData[city];
  return data ? { city, ...data } : { error: `no weather data for ${city}` };
}

function convertCurrency(amount: number, from: string, to: string) {
  const rate = rates[`${from}_${to}`];
  if (!rate) return { error: `no exchange rate for ${from} to ${to}` };
  return { amount, from, to, converted: Math.round(amount * rate * 100) / 100, rate };
}

function execute(name: string, input: Record<string, unknown>): unknown {
  try {
    if (name === 'get_weather') return getWeather(String(input.city));
    if (name === 'convert_currency') {
      return convertCurrency(Number(input.amount), String(input.from), String(input.to));
    }
    return { error: 'unknown tool' };
  } catch (err) {
    return { error: String(err) };
  }
}

async function runAgent(userText: string): Promise<string> {
  const messages: Anthropic.MessageParam[] = [{ role: 'user', content: userText }];

  for (let step = 0; step < 5; step++) {
    const response = await client.messages.create({
      model: 'claude-sonnet-5',
      max_tokens: 1024,
      tools,
      messages,
    });

    messages.push({ role: 'assistant', content: response.content });

    if (response.stop_reason !== 'tool_use') {
      return response.content.flatMap((b) => (b.type === 'text' ? [b.text] : [])).join('');
    }

    const results: Anthropic.ToolResultBlockParam[] = [];
    for (const block of response.content) {
      if (block.type === 'tool_use') {
        const output = execute(block.name, block.input as Record<string, unknown>);
        results.push({ type: 'tool_result', tool_use_id: block.id, content: JSON.stringify(output) });
      }
    }
    messages.push({ role: 'user', content: results });
  }

  return 'Stopped: step limit reached';
}

runAgent("What's the weather in Dhaka, and how much is 500 USD in BDT?").then(console.log);

একই বাক্যে ঢাকার আবহাওয়া আর টাকার হিসাব দুটোই জিজ্ঞেস করুন — ওপরের loop একবারই চলে, response-এ দুটো tool_use ব্লক আসে, get_weather আর convert_currency দুটোই চলে, আর দুটো ফলাফলই একটামাত্র মেসেজে ফেরত যায়, তারপর মডেল উত্তর লেখে।

যে ভুলে একটা পুরো ডিবাগিং সেশন গেছে

এই এজেন্টের প্রথম সংস্করণে tool ছিল মাত্র একটা। আমার loop response.content.find(b => b.type === 'tool_use') দিয়ে একটামাত্র tool request খুঁজে বের করত, কারণ আমার ধারণা ছিল একটার বেশি কখনোই আসবে না। যতক্ষণ শুধু একটা প্রশ্ন জিজ্ঞেস করেছি, ততক্ষণ ঠিকঠাক চলেছে।

তারপর convert_currency যোগ করলাম, আর এমন একটা প্রশ্ন জিজ্ঞেস করলাম যাতে দুটো tool-ই দরকার। মডেল ঠিকই একই response-এ দুটোই চাইল। আমার কোড প্রথমটা খুঁজে পেল, তার উত্তর দিল, আর দ্বিতীয়টা চুপচাপ বাদ দিয়ে দিল। পরের call-এ ভুল উত্তর আসেনি; API সরাসরি আটকে দিল, ঠিক যে tool id-টার জন্য কোনো ফলাফল যায়নি সেটা দেখিয়ে দিয়ে, আর ততক্ষণ থামল না যতক্ষণ না প্রতিটা খোলা tool call-এর উত্তর যায়। এটা কোনো নরমসরম নিয়ম না যেটা ছোট ভুল মাফ করে দেয়; নিয়মটা কড়া: প্রতিটা tool_use ব্লকের ঠিক পরের মেসেজেই একটামাত্র মিলে যাওয়া tool_result থাকতে হবে। আমার loop শুধু প্রথমটার হিসাব রাখছিল, সবগুলোর নয়; তাই সমাধান ছিল একটাই ধরে নেওয়া বন্ধ করা, আর মডেল আসলে যতগুলো ব্লক পাঠিয়েছে তার সবগুলোর ওপর দিয়ে ঘুরে আসা।

এই ভুলটা প্রথমবার ধরাই যায়নি, কারণ error message-টা লগে অনেক নিচে চাপা পড়েছিল অন্য সব লাইনের ভেতরে। এরপর থেকে নতুন কোনো tool যোগ করার সাথে সাথেই আমি অন্তত একবার এমন একটা প্রশ্ন দিয়ে টেস্ট করি যাতে একসাথে একাধিক tool দরকার হয়, খালি একটা একটা করে টেস্ট করে সন্তুষ্ট হই না।

Tool Calling-এ সাধারণ ভুল

  • শুধু প্রথম tool call পড়া। ওপরেই বলা হলো — সবসময় প্রতিটা tool_use ব্লকের ওপর দিয়ে ঘুরুন, সংখ্যা এক ধরে নেবেন না।
  • একে অন্যের সাথে মিলে যাওয়া description। দুটো tool-এর description যদি একই ধরনের request-এর জন্য মানানসই মনে হয়, মডেলকে আন্দাজ করতে হয়। দুটো tool-এর পার্থক্য নিজের মাথায় বুঝিয়ে বলতে হলে, description এমনভাবে লিখুন যাতে একজন অচেনা মানুষকেও আলাদা করে জিজ্ঞেস করতে না হয়।
  • Schema-তে অস্পষ্ট একক। “amount: number” লিখে কোন মুদ্রায় বা কোন স্কেলে তা না বললে মডেল আন্দাজ করে নেয়। description-এই লিখে দিন: from-এ যে মুদ্রার নাম আছে, সেই মুদ্রার amount, ফরম্যাট করা কোনো string নয়।
  • একটা tool-এ অনেক optional parameter। পনেরোটা optional field-ওয়ালা একটা tool ঠিকভাবে ভরা কঠিন, দুই-তিনটা করে required field থাকা তিনটা ছোট tool-এর চেয়ে। সুবিধার্থে নয়, গঠন অনুযায়ী আলাদা করুন।

এরপর

Tool calling এজেন্টকে হাত দেয় — কিছু নিয়ে হাত বাড়ানো আর কাজ করার ক্ষমতা। এরপর যেটা লাগে তা হলো প্রতিবার prompt-এ সরাসরি না বলা তথ্যও জানার একটা উপায় — সেটাই খুলে দেখার পরের ধাপ।

প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী (FAQ)

Tool Calling আর Function Calling কি একই জিনিস?

হ্যাঁ, দুটো নামে একই ব্যবস্থা। “Function calling” পুরোনো নাম, যখন tool মানেই ছিল আপনার লেখা একটা সাধারণ ফাংশন। “Tool calling” নামটা এখন বেশি চলে, কারণ tool মানে সবসময় আপনার কোড না-ও হতে পারে, যেমন web search-এর মতো hosted কোনো ক্ষমতাও tool হতে পারে। আপনি যে কোড লেখেন সেখানে দুটোই একই রকম কাজ করে: নাম, description, schema, আর ফেরত পাঠানো একটা ফলাফল।

Tool call ব্যর্থ হলে কি পুরো কথোপকথন ভেঙে পড়ে?

না, যদি আপনার কোড ব্যর্থতাটা ধরে সেটাকেই tool result হিসেবে ফেরত পাঠায়, বিনা হ্যান্ডেল করা error ছুঁড়ে না দিয়ে। কী ভুল হয়েছে সহজ ভাষায় লিখুন, চাইলে ফলাফলটাকে error হিসেবে চিহ্নিত করুন, আর মডেলকে ঠিক করতে দিন এরপর কী করবে: অন্য argument দিয়ে আবার চেষ্টা, ব্যবহারকারীর কাছে বাকি তথ্য চাওয়া, বা স্পষ্ট করে বলা যে এই request পূরণ করা যাচ্ছে না।

প্রতিটা কাজের জন্য কি আলাদা tool লাগবে?

না, যদি কাজগুলোর গঠন একই রকম হয়। কাছাকাছি ধরনের কাজ একটা tool-এর ভেতরেই রাখা যায়, action: 'add' | 'remove'-এর মতো একটা parameter দিয়ে। required argument সত্যিই আলাদা হয়ে গেলে তখন আলাদা tool বানান। মডেল পুরো tool-এর তালিকা পড়েই বেছে নেয়, তাই কাছাকাছি দেখতে অনেকগুলো tool থাকলে বাছাই সহজ হয় না, বরং কঠিন হয়।

img2
img2

img1
img1

thumbnail
thumbnail

img2
img2

img1
img1

thumbnail
thumbnail

🟢 ফ্রিল্যান্স ও কনট্রাক্ট প্রজেক্টের জন্য উন্মুক্ত

কাস্টম ওয়েব অ্যাপ বা এআই অটোমেশন বানাতে চান?

আমি স্টার্টআপ ও আধুনিক ব্যবসার জন্য স্কেলেবল ফুল-স্ট্যাক ওয়েব অ্যাপ্লিকেশন (Next.js, React, Node, PostgreSQL) এবং ইন্টেলিজেন্ট এআই এজেন্ট সলিউশন তৈরি করি। আপনার প্রজেক্টের আইডিয়া নিয়ে কথা বলা যাক!

ফুল-স্ট্যাক এমভিপি (MVP) ডেভেলপমেন্ট
অটোনোমাস এআই এজেন্ট ও এলএলএম ইন্টিগ্রেশন
পারফেক্ট এসইও ও সর্বোচ্চ পারফরম্যান্স
ক্লিন কোড ও মডার্ন আর্কিটেকচার

আর্টিকেলটি কি আপনার ভালো লেগেছে?

তন্ময়ের কাজকে সাপোর্ট করতে তালি (Clap) দিয়ে উৎসাহিত করুন!

0 views
Z

জাহিদ হাসান তন্ময়

সফটওয়্যার ডেভেলপার

MERN ফুল-স্ট্যাক ডেভেলপার এবং AI এজেন্ট ডেভেলপার, ঢাকা, বাংলাদেশ। ওয়েব ডেভেলপমেন্ট, রিঅ্যাক্ট, লারাভেল এবং আমার লার্নিং জার্নি নিয়ে লিখছি।

Related Articles

Stay Updated

Subscribe to get insights on full-stack architecture, AI agent engineering, and web development.