Open in
একটি টুল ইন্টিগ্রেশন (API) তৈরি করুন
কথোপকথনের মাঝখানে আপনার এজেন্টকে আপনার API কল করতে দিন — ডেটাবেসে অনুসন্ধান, টিকিট তৈরি, অর্ডার খোঁজা।
একটি টুল ইন্টিগ্রেশন হলো একটি পুনঃব্যবহারযোগ্য HTTP এন্ডপয়েন্ট, যা একটি এজেন্ট কলের সময় আহ্বান করতে পারে। আপনি ThunderPhone-কে টুলের একটি JSON-schema বিবরণ এবং একটি এন্ডপয়েন্ট URL দেন; কথোপকথনের ভিত্তিতে এজেন্ট কখন এটি কল করবে তা নির্ধারণ করে, এবং ThunderPhone তার সার্ভার থেকে বহির্গামী HTTP অনুরোধ করে ও প্রতিক্রিয়াটি এজেন্টকে ফেরত দেয়।
এই গাইডে শুরু থেকে শেষ পর্যন্ত একটি আবহাওয়া-অনুসন্ধান টুল তৈরি করা দেখানো হয়েছে।
একটি টুলের গঠন
দুটি অংশ:
- স্কিমা — একটি OpenAI-ধাঁচের ফাংশন সংজ্ঞা
(
{type: "function", function: {name, description, parameters}}), যা LLM-কে জানায় টুলটি কী করে এবং এটি কী আর্গুমেন্ট গ্রহণ করে। - এন্ডপয়েন্ট — LLM টুলটি ব্যবহার করার সিদ্ধান্ত নিলে ThunderPhone-এর সার্ভার যে URL-এ কল করে। অনুরোধটি হলো JSON POST, যেখানে LLM-এর নির্বাচিত আর্গুমেন্টগুলো বডি হিসেবে থাকে।
1. একটি এডিটর বেছে নিন
Connections → APIs খুলুন, API সংযোগ তৈরি বা সম্পাদনা করুন, প্যারামিটার এডিটরটি JSON-এ পরিবর্তন করুন এবং সেখানে ফরম্যাটটি যোগ করুন।
POST /v1/integrations দিয়ে স্পেক তৈরি করুন, অথবা
PATCH /v1/integrations/{id} দিয়ে এটি আপডেট করুন।
উভয় পথই একটি সংরক্ষিত ইন্টিগ্রেশন তৈরি করে। সংরক্ষণের পর সেই ইন্টিগ্রেশনটি
এজেন্টের সঙ্গে সংযুক্ত করুন। Agents API-তে লেখারযোগ্য ইনলাইন tools
ফিল্ড নেই। এই গাইডে ইন্টিগ্রেশন API পথ ব্যবহার করা হয়েছে।
2. ইন্টিগ্রেশন তৈরি করুন
curl -X POST https://api.thunderphone.com/v1/integrations \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"display_name": "Weather API",
"spec": {
"type": "function",
"function": {
"name": "get_weather",
"description": "Return the current weather for a zip code.",
"parameters": {
"type": "object",
"properties": {
"zip": { "type": "string", "description": "5-digit US ZIP code" }
},
"required": ["zip"]
}
}
},
"endpoint_url": "https://api.example.com/weather",
"endpoint_method": "GET",
"headers": [
{ "key": "X-Api-Key", "value": "your-provider-key" }
]
}'ফেরত পাওয়া id (একটি UUID) সংরক্ষণ করুন।
ঠিকানা প্যারামিটারে format: "email" ঘোষণা করুন
যে প্যারামিটার একটি ইমেল ঠিকানা গ্রহণ করে, তার স্কিমায় তা উল্লেখ করা উচিত:
"email": { "type": "string", "format": "email", "description": "The caller's email address" }format শুধু একটি ইঙ্গিতের চেয়েও বেশি কিছু। সমাধানকৃত ইমেল স্কিমার ক্ষেত্রে, আপনার endpoint কল হওয়ার আগে ThunderPhone মানটি trim করে, ডোমেইনকে ছোট হাতের অক্ষরে রূপান্তর করে, স্বতন্ত্র ইংরেজি শব্দ at, dot, underscore, dash, এবং hyphen-কে তাদের সংশ্লিষ্ট অক্ষরে রূপান্তর করে এবং @, ., _, ও --এর ঠিক আশপাশের whitespace সরিয়ে দেয়। ট্রান্সক্রিপ্টে ইতিমধ্যেই আক্ষরিক @ থাকুক বা না থাকুক, শব্দগুলোর অর্থ একই থাকে:
"john dot smith at gmail dot com" হয়ে যায়
john.smith@gmail.com।
অভ্যন্তরীণ অন্য যেকোনো whitespace নীরবে জোড়া দেওয়ার পরিবর্তে প্রত্যাখ্যান করা হয়। কথ্য বিভাজক শব্দগুলো শুধু ইংরেজির জন্য প্রযোজ্য; অ-ইংরেজি বা অচেনা ফাঁকা-স্থানযুক্ত ফর্ম বন্ধ অবস্থায় ব্যর্থ হয়। বৈধ আন্তর্জাতিকীকৃত ডোমেইন এবং SMTPUTF8 local part গ্রহণ করা হয়। Punycode ইনপুট Punycode-ই থাকে এবং Unicode ডোমেইন ইনপুট parser normalization-এর পরেও Unicode-ই থাকে, তাই আপনার API কলারের দেওয়া প্রচলিত উপস্থাপনাটি পায়। চূড়ান্ত মানটি অবৈধ হলে, টুলটি কল করা হয় না। এজেন্ট invalid_email_argument পায়, যা তাকে কলারের সঙ্গে বানান নিশ্চিত করতে এবং আক্ষরিক ঠিকানাটি পুনরায় পাঠাতে বলে।
বাদ দেওয়া ঐচ্ছিক ইমেল অপরিবর্তিত থাকে। null, খালি স্ট্রিং, বা শুধু whitespace-যুক্ত স্ট্রিংও অপরিবর্তিত থাকে যখন প্রপার্টিটি ঐচ্ছিক বা nullable হয়; একই মানগুলো প্রয়োজনীয়, non-nullable ইমেলের ক্ষেত্রে প্রত্যাখ্যান করা হয়।
#/$defs/email এবং #/definitions/email-এর মতো স্থানীয় schema reference, পাশাপাশি anyOf, oneOf, এবং allOf, cycle ও depth limit সহ পরিদর্শন করা হয়। non-local বা সমাধান-অযোগ্য $ref একটি পরিচিত enforcement সীমাবদ্ধতা এবং অপরিবর্তিত অবস্থায় পাঠানো হয়; একইভাবে, যে কলের tool snapshot-এ ব্যবহারযোগ্য schema নেই সেটিও অপরিবর্তিত অবস্থায় পাঠানো হয়। gate প্রয়োগ করতে হলে ইমেল schema স্থানীয় রাখুন।
প্রয়োগকৃত ইমেল format ছাড়া প্যারামিটারগুলো মডেল যেভাবে তৈরি করেছে ঠিক সেভাবেই পাঠানো হয়।
সমর্থিত format হলো date-time, time, date, duration, email, hostname, ipv4, ipv6, এবং uuid; বর্তমানে শুধু email স্বাভাবিকীকরণ ও প্রয়োগ করা হয়।
3. endpoint স্যান্ডবক্সে পরীক্ষা করুন
ইন্টিগ্রেশনটি কোনো এজেন্টের সঙ্গে লিঙ্ক করার আগে, সংযোগ নিশ্চিত করতে ThunderPhone-এর সার্ভার থেকে একটি signed request পাঠান:
curl -X POST https://api.thunderphone.com/v1/integrations/test-request \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/weather?zip=94110",
"method": "GET",
"headers": { "X-Api-Key": "your-provider-key" }
}'{
"ok": true,
"status": 200,
"elapsed_ms": 187,
"response_headers": { "content-type": "application/json" },
"response_preview": "{\"temperature_f\": 64, ...}"
}এই পরীক্ষা ThunderPhone-এর SSRF guard-ও শক্তিশালী করে — localhost বা private IP range-এ অনুরোধ করলে 400 code=url_not_allowed ফেরত আসে।
4. একটি এজেন্টের সঙ্গে ইন্টিগ্রেশন লিঙ্ক করুন
এজেন্ট তৈরি বা আপডেট করার সময় integration_ids ব্যবহার করে সংযুক্ত করুন:
curl -X PATCH https://api.thunderphone.com/v1/agents/12 \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"integration_ids": ["f9b5a1a4-..."]
}'আপনি একটি এজেন্টের সঙ্গে একাধিক ইন্টিগ্রেশন লিঙ্ক করতে পারেন। এজেন্টের prompt নাম ধরে সেগুলোর উল্লেখ করতে পারে — কলার পরিস্থিতি সম্পর্কে জিজ্ঞাসা করলে "get_weather ব্যবহার করুন" — অথবা স্কিমার বিবরণ থেকে পরোক্ষভাবে সেগুলো শনাক্ত করতে পারে।
5. এন্ডপয়েন্ট বাস্তবায়ন করুন
এজেন্ট টুলটি আহ্বান করলে, ThunderPhone আপনার endpoint_url-এ একটি স্বাক্ষরিত POST পাঠায়:
POST /weather HTTP/1.1
Host: api.example.com
X-Api-Key: your-provider-key
X-ThunderPhone-Signature: <HMAC-SHA256 hex>
X-ThunderPhone-Call-ID: 987654321
Content-Type: application/json
{"zip": "94110"}
আপনার সার্ভার JSON দিয়ে উত্তর দেয়, যা LLM-এ ফেরত পাঠানো হয়:
{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}LLM সেই উত্তর গ্রহণ করে এবং কলারকে মানুষের বোধগম্য একটি সারাংশ বলে।
6. লুপ পরীক্ষা করুন
এজেন্টের বিরুদ্ধে একটি মাইক সেশন চালান এবং আপনার টুল যে প্রশ্নটি পরিচালনা করে তা জিজ্ঞাসা করুন ("94110-এ আবহাওয়া কেমন?")। কলের ট্রান্সক্রিপ্টে সম্পূর্ণ আদান-প্রদান দেখা যায়:
{
"call_id": 987654321,
"transcripts": [
{ "role": "user",
"content": "What's the weather in 94110?" },
{ "role": "tool_call",
"content": "{\"tool_call\": \"get_weather\", \"arguments\": {\"zip\": \"94110\"}}" },
{ "role": "tool_response",
"content": "{\"tool_name\": \"get_weather\", \"response\": {\"temperature_f\": 64, \"condition\": \"Partly cloudy\"}}" },
{ "role": "agent",
"content": "It's 64 degrees and partly cloudy." }
]
}আপনি এটি
GET /v1/calls/{call_id}/transcript দিয়ে আনতে পারেন;
প্রতি-এন্ট্রির সময় এবং অডিও অফসেটসহ কাঁচা ইভেন্ট স্ট্রিমটি রয়েছে
GET /v1/calls/{call_id}/history-এ।
সাধারণ সমস্যা
এজেন্ট কখনও টুলটি কল করে না
LLM টুলের বিবরণের ভিত্তিতে সিদ্ধান্ত নেয়। কলারের প্রশ্ন বিবরণের সঙ্গে না মিললে, মডেল টুলটি আহ্বান করবে না। বিবরণটি আরও নির্দিষ্ট করুন (প্রচলিত সমার্থক শব্দ ও বাক্যরীতি যোগ করুন) অথবা এজেন্টের prompt-এ স্পষ্টভাবে উল্লেখ করুন ("কলার আবহাওয়া সম্পর্কে জিজ্ঞাসা করলে, get_weather ব্যবহার করুন।")।
টুল অতিরিক্ত ডেটা ফেরত দেয়
6 kB-এর বেশি উত্তর ট্রান্সক্রিপ্ট প্রিভিউতে সংক্ষিপ্ত করা হয়। LLM-এর প্রয়োজনীয় ফিল্ডগুলোই ফেরত দিন — আপনার সম্পূর্ণ সারি নয়।
টাইমআউট
টুল এন্ডপয়েন্টে ডিফল্ট 10-সেকেন্ডের টাইমআউট থাকে। আরও সময় লাগলে, অ্যাসিঙ্ক্রোনাসভাবে পরিচালনা করুন: {"status": "pending", "request_id": "..."} ফেরত দিন এবং আলাদা টুল কলের মাধ্যমে ফলাফল দেখান।
সংস্করণ নিয়ন্ত্রণ
প্রতিটি ইন্টিগ্রেশন PATCH একটি নতুন রিভিশন তৈরি করে। কে কী পরিবর্তন করেছে দেখতে
GET /v1/integrations/{id}/versions পরিদর্শন করুন। আপনি কোনো টুলের স্কিমা নষ্ট করলে, পুরোনো একটি স্ন্যাপশট আবার PATCH করে নিজে থেকে রোল ব্যাক করতে পারেন।