---
title: "এজেন্টের ধাপ ও হ্যান্ডঅফ"
description: "একটি এজেন্টকে নিজস্ব নির্দেশনা, টুল এবং সংগৃহীত মানসহ বিভিন্ন ধাপে ভাগ করুন এবং কল চলাকালীন এজেন্টদের মধ্যে কল হস্তান্তর করুন।"
---

একটি একক prompt মডেলকে পুরো কাজটি একসঙ্গে দেয়। **ধাপসমূহ** এটিকে একবারে কলের একটি পর্যায় দেয়: প্রতিটি ধাপের নিজস্ব নির্দেশনা, নিজস্ব টুল, শব্দে শব্দে বলার জন্য একটি ঐচ্ছিক লাইন এবং পরবর্তী ধাপে যাওয়ার আগে সংগ্রহ করতে হবে এমন মান থাকে। **হ্যান্ডঅফ** আপনার প্রতিষ্ঠানের অন্য এজেন্টকে কলের মাঝখানে দায়িত্ব নিতে দেয়, ট্রান্সক্রিপ্ট অক্ষত রেখে, যাতে কলারকে কখনও নিজেদের কথা পুনরাবৃত্তি করতে না হয়।

প্রতিটি এজেন্ট একটি একক prompt হিসেবে শুরু হয়। আপনি ধাপ বা হ্যান্ডঅফ যোগ না করা পর্যন্ত এতে কিছুই পরিবর্তিত হয় না।

## ধাপসমূহ নাকি একক prompt?

| ধাপসমূহ ব্যবহার করুন যখন | একক prompt রাখুন যখন |
| --- | --- |
| কলে এমন পর্যায় আছে যা নির্দিষ্ট ক্রমে ঘটতে হবে: যাচাই, তারপর বুকিং। | কথোপকথনটি উন্মুক্ত: FAQ, রিসেপশন, সাধারণ সহায়তা। |
| এজেন্ট পরবর্তী ধাপে যাওয়ার আগে একটি মান অবশ্যই সংগ্রহ করতে হবে। | নির্দিষ্ট ক্রমে কিছু সংগ্রহ করার প্রয়োজন নেই। |
| কোনো নিয়ম কখনও শিথিল করা যাবে না, যেমন "18 বছরের কম বয়সী কলারদের অভিভাবকের কাছে পাঠান"। | প্রতিটি শাখার জন্য মডেলের বিচারবোধ যথেষ্ট ভালো। |
| কলের নির্দিষ্ট একটি সময়ে lookup চালাতে হবে। | কলার চাইলে যেকোনো সময় টুল কল করা যায়। |
| কলের একটি অংশ ভিন্ন এজেন্টের জন্য নির্ধারিত, যার নিজস্ব prompt ও ভয়েস আছে। | একটি persona সবকিছু পরিচালনা করে। |

ধাপসমূহ কোনো স্ক্রিপ্টেড ফোন ট্রি নয়। একটি ধাপের মধ্যে মডেল একক prompt-এর মতোই কথোপকথন পরিচালনা করে। ধাপটি নির্ধারণ করে এটি কী নিয়ে কাজ করছে, কোন টুল ব্যবহার করতে পারে এবং ধাপ ছাড়ার আগে কী প্রয়োজন।

## ধাপভিত্তিক এজেন্ট কীভাবে তৈরি হয়

কোনো এজেন্টে ধাপ থাকলে, তার `prompt`-এ থাকে **শেয়ার করা নির্দেশনা**: persona এবং নিয়ম, যা প্রতিটি ধাপে প্রযোজ্য। প্রতিটি ধাপ এর ওপর নিজস্ব নির্দেশনা যোগ করে। প্রতিটি টার্নে মডেল শেয়ার করা নির্দেশনা, বর্তমান ধাপের নাম ও নির্দেশনা এবং এখন পর্যন্ত সংগৃহীত মানগুলো দেখে।

বিল্ডারে এজেন্টটিকে **একক prompt** থেকে **ধাপসমূহ**-এ পরিবর্তন করুন। আপনি প্রতিটি ধাপের জন্য তার নাম, নির্দেশনা, বলার লাইন, টুল, সংগৃহীত মান ও ট্রানজিশনসহ একটি কার্ড, একটি হ্যান্ডঅফ পিকার এবং ধাপগুলোর একটি শুধু-পঠনযোগ্য ফ্লো গ্রাফ পাবেন। একক prompt-এ ফিরে গেলে একটি সমতল করা prompt পাওয়া যায়, যা শেয়ার করা নির্দেশনা ও প্রতিটি ধাপকে একত্র করে।

API-এর মাধ্যমে `steps` এবং `handoffs` হলো
[agent](/api-reference/agents)-এর ফিল্ড। প্রতিটি এজেন্ট ফিল্ডের মতো, একটি `PATCH` এগুলোকে draft-এ stage করে; `POST /v1/agents/{agent_id}/deploy` এগুলোকে live করে। `"steps": null` পাঠালে এজেন্টটি আবার একক prompt-এ ফিরে যায়। টেস্ট কল এবং **কথা বলুন** draft চালায়।

<Tip>
  [copilot](/bn/guides/ask-the-copilot) একটি বর্ণনা থেকে ধাপ তৈরি করতে পারে
  ("বুকিংয়ের আগে জন্মতারিখ যাচাই করে এমন একটি ধাপ যোগ করুন") এবং অন্য ধাপগুলো স্পর্শ না করে একটি ধাপ সম্পাদনা করতে পারে।
</Tip>

### ধাপের ফিল্ড

| ফিল্ড | অর্থ |
| --- | --- |
| `id` | আবশ্যক। ছোট হাতের অক্ষর, সংখ্যা এবং আন্ডারস্কোর; একটি অক্ষর দিয়ে শুরু হতে হবে; সর্বোচ্চ 40 অক্ষর। এজেন্টের মধ্যে অনন্য। |
| `name` | আবশ্যক প্রদর্শন নাম, 1 থেকে 80 অক্ষর। |
| `instructions` | আবশ্যক, সর্বোচ্চ 20,000 অক্ষর। `prompt`-এর মতো `{{var}}` [কল ভেরিয়েবল](/bn/guides/call-variables) সমর্থন করে। |
| `say` | ধাপে প্রবেশের সময় শব্দে শব্দে বলার জন্য ঐচ্ছিক লাইন, সর্বোচ্চ 1,000 অক্ষর। `{{var}}` সমর্থন করে। |
| `tools` | `null` ধাপটিকে এজেন্টের সঙ্গে সংযুক্ত প্রতিটি টুল দেয়। একটি তালিকা ধাপটিকে নাম অনুসারে সেই টুলগুলোতে সীমাবদ্ধ করে। `end_call` এবং `transfer_call`-এর মতো বিল্ট-ইন অ্যাকশন প্রতিটি ধাপে এজেন্টের সেটিংস অনুসরণ করে। |
| `collect` | ধাপটি সর্বোচ্চ 20টি মান সংগ্রহ করে। প্রতিটির একটি `name`, একটি `type`, একটি `description` এবং `required` থাকে (ডিফল্ট `true`)। |
| `on_enter_tool` | ঐচ্ছিক টুলের নাম, ধাপে প্রবেশের সময় স্বয়ংক্রিয়ভাবে কল করা হয়। [Webhook ধাপসমূহ](#webhook-steps) দেখুন। |
| `transitions` | ধাপটি পরবর্তী কোথায় যেতে পারে তার ক্রমানুসার তালিকা। [ট্রানজিশন](#transitions) দেখুন। |
| `global_when` | ঐচ্ছিক। ধাপটিকে যেকোনো ধাপ থেকে পৌঁছানো যায় এমন করে। [গ্লোবাল ধাপসমূহ](#global-steps) দেখুন। |
| `voice` | এই ধাপের জন্য ঐচ্ছিক ভয়েস id। এজেন্ট কাস্টম ভয়েস কনফিগারেশন ব্যবহার করলে উপেক্ষা করা হয়। |

গ্রাফটি নিজেই হলো `{"start_step": "<step id>", "steps": [...]}`। কলটি
`start_step`-এ শুরু হয়।

## ট্রানজিশন

প্রতিটি ট্রানজিশনে `to`, একটি ধাপ id, এবং নিচের ঠিক একটিই থাকে:

- **`when`**: স্বাভাবিক ভাষা, এবং **মডেল সিদ্ধান্ত নেয়**। এজেন্ট একটি অন্তর্নির্মিত `go_to_step` টুল পায়, যেখানে এটি যে ধাপগুলোতে যেতে পারে সেগুলোর তালিকা থাকে এবং প্রতিটি `when` সেটি বেছে নেওয়ার কারণ হিসেবে থাকে।
- **`condition`**: সংগৃহীত মানের ওপর একটি নিয়ম, এবং **কোড সিদ্ধান্ত নেয়**। মডেল এটি এড়িয়ে যেতে বা কথার মাধ্যমে এর ব্যতিক্রম ঘটাতে পারে না।
- **`"always": true`**: যাচাই ছাড়াই এগিয়ে যান। কোড আগে সিদ্ধান্ত নেয়: কোনো ধাপে প্রবেশ করার সঙ্গে সঙ্গে, অথবা তার প্রয়োজনীয় মানগুলো সংগ্রহ হয়ে গেলে, মডেল `when` বেছে নেওয়ার আগেই প্রথম মিলে যাওয়া `condition` বা `always` ট্রানজিশন কার্যকর হয়। তাই `always`-কে শর্তগুলোর ফলব্যাক হিসেবে তাদের পরে রাখুন, অথবা একটি ধাপকে সরাসরি পরের ধাপের সঙ্গে যুক্ত করতে একে একা রাখুন। `always` থাকা কোনো ধাপ কখনও `when` পছন্দের জন্য অপেক্ষা করে না।

একটি `condition` হলো `{"value": <collected name or dotted path>, "op": <op>, "target": <literal>}`:

| `op` | মানটি সত্য হয় যখন |
| --- | --- |
| `eq`, `ne` | `target`-এর সমান হয়, অথবা সমান হয় না |
| `lt`, `lte`, `gt`, `gte` | `target`-এর চেয়ে কম, সর্বোচ্চ, বেশি, অথবা কমপক্ষে হয় |
| `in`, `not_in` | `target` তালিকার মানগুলোর একটি হয়, অথবা একটি নয় |
| `exists`, `missing` | সংগ্রহ করা হয়েছে, অথবা করা হয়নি (`target` নেই) |

`eq`, `ne`, `in` এবং `not_in` ফাঁকা স্থান বাদ দিয়ে টেক্সটকে বড়-ছোট হাতের অক্ষর বিবেচনা না করে তুলনা করে। সংখ্যা হিসেবে সংখ্যার তুলনা হয় এবং তারিখ `YYYY-MM-DD` স্ট্রিং হিসেবে তুলনা হয়। যে মান কখনও সংগ্রহ করা হয়নি, সেটি `missing` ছাড়া প্রতিটি op-কে false করে।

`when` এবং `global_when`-কে বলার মতো কিছু হিসেবে নয়, বরং একটি শর্ত হিসেবে লিখুন, যেমন "কলার একটি অ্যাপয়েন্টমেন্ট বুক করতে চান"। এজেন্ট এগুলোকে অভ্যন্তরীণ রাউটিং নোট হিসেবে দেখে এবং এগুলো কখনও উচ্চারণ না করতে বা ধাপ পরিবর্তন করছে বলে উল্লেখ না করতে নির্দেশিত থাকে।

মডেল যখন `go_to_step` কল করে:

1. ধাপের প্রতিটি `required` মান উপস্থিত থাকতে হবে। কোনোটি অনুপস্থিত থাকলে, মডেলকে বলা হয় কোনটি অনুপস্থিত, এবং এটি কলারের কাছে তা চায়।
2. মানগুলো সংরক্ষণ করা হয়।
3. `condition` এবং `always` ট্রানজিশনগুলো ক্রমানুসারে পরীক্ষা করা হয়। প্রথম মিলটিই কার্যকর হয়।
4. অন্যথায় এজেন্ট মডেলের বেছে নেওয়া ধাপে যায়।
5. কিছুই না মিললে এবং মডেল কোনো ধাপের নাম না বললে, এজেন্ট যেখানে আছে সেখানেই থাকে।

একটি [গ্লোবাল ধাপে](#global-steps) যাওয়া ব্যতিক্রম: কলার বিষয় পরিবর্তন করেছেন, তাই বর্তমান ধাপে প্রয়োজনীয় মান অনুপস্থিত থাকলেও এবং সেই ধাপের শর্তগুলো পরীক্ষা করার আগেই এটি এগিয়ে যায়।

কোনো ধাপে প্রবেশের প্রতিবারও `condition` এবং `always` ট্রানজিশন পরীক্ষা করা হয়, তাই কোড-নির্ধারিত ধাপগুলোর একটি ক্রম একবারেই সম্পন্ন হয়। এই শৃঙ্খল থামে:

- এই রানে ইতিমধ্যে পরিদর্শন করা কোনো ধাপে;
- 8 হপের পরে;
- এমন একটি ধাপে যেখানে এখনও প্রয়োজনীয় মান সংগ্রহ করতে হবে, যদি না ধাপটিতে একটি `on_enter_tool` থাকে (একটি webhook ধাপ সবসময় তার ফলাফলের ভিত্তিতে রাউট করে)।

শুধু যে ধাপে শৃঙ্খল থামে, সেই ধাপের `say` লাইনটি উচ্চারিত হয়।

ট্রানজিশনবিহীন একটি ধাপ **চূড়ান্ত**। এজেন্ট সেখানে শেষ করে এবং তার স্বাভাবিক অন্তর্নির্মিত অ্যাকশন ব্যবহার করে কল শেষ করে বা ট্রান্সফার করে।

## মান সংগ্রহ

একটি ধাপের যা প্রয়োজন, তা `collect`-এ তালিকাভুক্ত করুন। মডেল `go_to_step` কল করার সময় মানগুলো পাঠায়, এবং কলের বাকি সময়জুড়ে সেগুলো উপলভ্য থাকে।

| `type` | ধারণ করে |
| --- | --- |
| `string` | যেকোনো টেক্সট |
| `number` | একটি সংখ্যা |
| `boolean` | `true` অথবা `false` |
| `date` | `YYYY-MM-DD` হিসেবে একটি তারিখ |

সংগৃহীত মান কলের কনটেন্ট। এগুলো ট্রান্সক্রিপ্টের পাশে কলে দেখা যায় এবং একই সংরক্ষণ, মুছে ফেলা ও রিড্যাকশন নিয়ম অনুসরণ করে। এজেন্টের কল রেকর্ডিং বন্ধ থাকলে, সংগৃহীত মান সংরক্ষণ করা হয় না বা webhook-এ পাঠানো হয় না; তবে ধাপের টাইমলাইন থাকে। দেখুন [কলে এটি কোথায় দেখবেন](#where-to-see-it-on-a-call)।

## বলার লাইন

এজেন্ট ধাপে প্রবেশ করলে `say` ঠিক যেমন লেখা আছে তেমনই বলা হয়। এরপর মডেল একই উত্তরে নতুন ধাপে কথোপকথন চালিয়ে যায়, কারণ এটি জানে যে লাইনটি এইমাত্র বলা হয়েছে, তাই এটি সেটি পুনরাবৃত্তি করে না। অভিবাদন, আবশ্যিক প্রকাশনা এবং নির্দিষ্ট বাক্যবিন্যাসের জন্য `say` ব্যবহার করুন, আর উত্তরের বাকি অংশ মডেলের ওপর ছেড়ে দিন।

শুরুর ধাপের `say` হলো এজেন্টের প্রারম্ভিক লাইন, যখন কোনো সম্মতি ঘোষণার পরে এজেন্ট প্রথমে কথা বলে। কলার আগে কথা বললে, এটি কোনো IVR বা ভয়েসমেইল অভিবাদনের জন্য নয়, ব্যক্তির উদ্দেশ্যে এজেন্টের প্রথম উত্তর শুরু করে।

`__previous__` বা হ্যান্ড-ব্যাকের মাধ্যমে কল কোনো ধাপে ফিরে এলে সেই ধাপের `say` আবার বলা হয় না। এটি যেভাবে শোনানো উচিত সেভাবে লিখুন: ভয়েস ভুল পড়তে পারে এমন যেকোনো কিছু বানান করে লিখুন। বলার লাইন `{{var}}` কল ভেরিয়েবল সমর্থন করে, কিন্তু সংগৃহীত মান সমর্থন করে না।

## Webhook ধাপ

`on_enter_tool`-কে এজেন্টের কোনো একটি টুলে সেট করুন; ধাপে প্রবেশের সঙ্গে সঙ্গেই এটি চলবে, মডেলের জন্য অপেক্ষা না করে। এর আর্গুমেন্ট হলো সেই সংগৃহীত মানগুলো, যেগুলোর নাম টুলের প্যারামিটারের নামের সঙ্গে মেলে। ফলাফলটি `<tool>_result` নামে একটি সংগৃহীত মান হিসেবে সংরক্ষিত হয়, 4 KB-তে সংক্ষিপ্ত করা হয়, এবং ধাপের `condition` ও `always` ট্রানজিশন সঙ্গে সঙ্গেই পরীক্ষা করা হয়, যাতে লুকআপ নিজ ফলাফলের ভিত্তিতে কল রাউট করতে পারে।

সংরক্ষিত মানটিতে দুটি ক্ষেত্র থাকে:

| ক্ষেত্র | ধারণ করে |
| --- | --- |
| `status` | আপনার এন্ডপয়েন্ট ফেরত দেওয়া HTTP স্ট্যাটাস কোড। |
| `response` | রেসপন্স বডি। |

`lookup_account_result.response.<field>` দিয়ে বডির কোনো ক্ষেত্রে রাউট করুন এবং `lookup_account_result.status` দিয়ে স্ট্যাটাস কোডে রাউট করুন।

লুকআপ সর্বোচ্চ 8 সেকেন্ড চলে, অথবা টুলের নিজস্ব টাইমআউট যদি এর চেয়ে কম হয়। এটি 3 সেকেন্ডের বেশি সময় নিলে, কলার যাতে নীরবতায় না থাকেন সেজন্য এজেন্ট একটি সংক্ষিপ্ত লাইন বলে। আপনার এন্ডপয়েন্ট 400 বা তার বেশি স্ট্যাটাস ফেরত দিলে, অথবা সময়মতো উত্তর না দিলে, এজেন্ট কলারকে জানায় যে এটি এই মুহূর্তে তা পরীক্ষা করতে পারেনি এবং যা করতে পারে তা চালিয়ে যায়।

## গ্লোবাল ধাপ

`global_when`-সহ একটি ধাপে যেকোনো ধাপ থেকে পৌঁছানো যায়, যখনই সেই বিবরণ প্রযোজ্য হয়। `when`-এর মতোই মডেল সিদ্ধান্ত নেয়। কলার যেকোনো সময় তুলতে পারেন এমন বিষয়ের জন্য এটি ব্যবহার করুন: বিলিং-সংক্রান্ত প্রশ্ন, মানুষের সঙ্গে কথা বলার অনুরোধ, অভিযোগ।

গ্লোবাল ধাপে `"to": "__previous__"`-সহ একটি ট্রানজিশন কলটিকে তার আগের সক্রিয় ধাপে ফিরিয়ে দেয়, যাতে কলার যেখানে থেমেছিলেন সেখান থেকেই শুরু করতে পারেন। ধাপটি পুনরায় চালু হয়: এর `on_enter_tool` আবার চলে না, এর `say` পুনরাবৃত্তি হয় না, এবং এজেন্ট নতুন করে শুরু না করে এটি চালিয়ে যায়।

## হস্তান্তর

`handoffs` আপনার প্রতিষ্ঠানের অন্যান্য এজেন্টের তালিকা দেয়, যারা কলটি গ্রহণ করতে পারে:

```json
[{"agent_id": 413, "when": "The caller asks about billing or a refund"}]
```

এজেন্টটি ওই এজেন্ট ও কারণগুলোর জন্য একটি অন্তর্নির্মিত `hand_off` টুল পায়। ট্রানজিশনের মতোই, প্রতিটি `when` একটি অভ্যন্তরীণ রাউটিং নোট, যা কখনও উচ্চারণ করা হয় না।

হস্তান্তরের সময়, এজেন্টটি কলারকে তারা কোথায় যাচ্ছেন তা জানিয়ে নিজের কণ্ঠে একটি ছোট লাইন বলে, যেমন "অবশ্যই, আমি আপনাকে আমাদের বিলিং টিমের কাছে পাঠিয়ে দিচ্ছি"। এরপর লক্ষ্য এজেন্টের prompt, ধাপ, টুল ও কণ্ঠ নিয়ন্ত্রণ নেয় এবং একই ট্রান্সক্রিপ্টে কল চলতে থাকে। নতুন এজেন্ট সংক্ষেপে নিজের পরিচয় দেয় এবং কলারের শেষ অনুরোধের উত্তর দেয়; এটি ট্রান্সফারের ঘোষণা দেয় না। এরপর থেকে লক্ষ্য এজেন্টের নলেজ বেস উপলভ্য থাকে।

কোনো কল প্রথমবার একটি এজেন্টে পৌঁছালে, সেটি ওই এজেন্টের `start_step`-এ শুরু হয়: ধাপটির `on_enter_tool` চলে এবং এর `say` উচ্চারিত হয়। কলটি আগে পরিদর্শন করা কোনো এজেন্টের কাছে ফেরত হস্তান্তর হলে, সেই এজেন্ট `on_enter_tool` না চালিয়ে, তার `say` পুনরাবৃত্তি না করে বা আবার নিজের পরিচয় না দিয়ে যে ধাপে ছিল সেখান থেকেই চালিয়ে যায়। সংগৃহীত মান কলের প্রতিটি এজেন্টের সঙ্গে শেয়ার করা হয়।

- একটি লক্ষ্য এজেন্টকে একই প্রতিষ্ঠানের এজেন্ট হতে হবে এবং কোনো এজেন্ট নিজেকে হস্তান্তর করতে পারে না।
- কল-স্তরের সবকিছু কলের উত্তর দেওয়া এজেন্টের সঙ্গেই থাকে: পণ্য, ভাষা, কে আগে কথা বলে, ভয়েসমেইল, সম্মতির ঘোষণা এবং অন্যান্য সব কল সেটিং।
- লক্ষ্য এজেন্ট আরও হস্তান্তর করতে পারে, এবং আগের এজেন্টের কাছেও ফিরিয়ে দিতে পারে। একটি কল সর্বোচ্চ 8টি এজেন্টে পৌঁছাতে পারে।
- একটি টেস্ট কল আপনার পরীক্ষিত এজেন্টের ড্রাফট চালায়। এটি যেসব এজেন্টে হস্তান্তর করে, তারা তাদের ডিপ্লয় করা সংস্করণ চালায়।
- দুটি এজেন্টের একই নামে কিন্তু ভিন্ন সংজ্ঞার টুল থাকলে, কলের জন্য কেবল একটি রাখা হয় এবং উত্তর দেওয়া এজেন্টেরটিই সবসময় অগ্রাধিকার পায়। আপনি সংরক্ষণ করার সময় বিল্ডার আপনাকে সতর্ক করে।
- একটি এজেন্টের ধাপ ছাড়াই হস্তান্তর থাকতে পারে। এর সম্পূর্ণ prompt অপরিবর্তিতভাবে ব্যবহার করা হয়।

`go_to_step` এবং `hand_off` ধাপ বা হস্তান্তর থাকা এজেন্টে সংরক্ষিত, তাই আপনার নিজস্ব টুলে এই নামগুলো ব্যবহার করা যাবে না।

## কলে এটি কোথায় দেখবেন

**কলের ইতিহাস**-এ কলটি খুলুন। ট্রান্সক্রিপ্টের পাশে একটি ধাপ টাইমলাইন দেখায় কলটি কোন কোন ধাপে প্রবেশ করেছে এবং কেন, আর সংগৃহীত মানগুলোও এর সঙ্গে তালিকাভুক্ত থাকে।

[কল অবজেক্ট](/api-reference/calls#retrieve-a-call) এবং কল-সম্পন্ন ওয়েবহুক ([`telephony.complete` / `web.complete`](/bn/webhooks/call-complete)) `steps_trace` ও `collected_values` হিসেবে একই ডেটা বহন করে। ধাপবিহীন কলে দুটিই অনুপস্থিত থাকে।

```json
"steps_trace": [
  {"t_ms": 0, "agent": "a412", "step": "greet", "via": "start"},
  {"t_ms": 51230, "agent": "a412", "step": "verify", "via": "model"},
  {"t_ms": 98410, "agent": "a412", "step": "minor", "via": "condition"}
],
"collected_values": {"full_name": "Dana Reyes", "dob": "2010-04-02", "age": 15}
```

`agent` হলো `a`-এর পরের এজেন্ট ID। `via` বলে কলটি কী কারণে সরেছে:

| `via` | অর্থ |
| --- | --- |
| `start` | কলটি এই ধাপে শুরু হয়েছে। |
| `model` | মডেল `go_to_step`, একটি `when` বা একটি `global_when` দিয়ে ধাপটি বেছে নিয়েছে। |
| `condition` | একটি `condition` বা `always` ট্রানজিশন মিলে গেছে। |
| `on_enter` | একটি ওয়েবহুক ধাপের ফলাফলে একটি ট্রানজিশন মিলে গেছে। |
| `handoff` | অন্য একটি এজেন্ট নিয়ন্ত্রণ নিয়েছে। |

## ধাপ কোথায় চলে

ধাপগুলো **Spark**, **Bolt** এবং প্রতিটি **Storm** পণ্যে নেটিভভাবে চলে—ইনবাউন্ড, আউটবাউন্ড ও ক্যাম্পেইন কল, টেস্ট কল, এবং ওয়েব ও উইজেট কলে।

অন্য সব জায়গায়ও এজেন্ট কাজ করে, তবে কাঠামো ছাড়া: এটি একটি সমতল prompt চালায়, যা শেয়ার করা নির্দেশনা এবং প্রতিটি ধাপ ক্রমানুসারে একত্র করে। এতে অন্তর্ভুক্ত:

- পরীক্ষামূলক Bolt পণ্যগুলো;
- সংরক্ষিত এজেন্টের সেশনসহ [Realtime](/bn/guides/use-with-openai-realtime) সেশন;
- একটি [ডাইনামিক কল কনফিগ](/bn/guides/dynamic-call-config) ওয়েবহুক থেকে ফেরত আসা ইনলাইন কনফিগারেশন। `agent_id` ফেরত দেওয়া একটি ওয়েবহুক সেই এজেন্টের ধাপ ব্যবহার করে।

## সীমা

| সীমা | মান |
| --- | --- |
| প্রতি এজেন্টে ধাপ | 100 |
| প্রতি ধাপে সংগৃহীত মান | 20 |
| প্রতি এজেন্টে হ্যান্ডঅফ লক্ষ্য | 8 |
| একটি কলে পৌঁছানো যায় এমন এজেন্ট | 8 |
| `steps` JSON-এর আকার | 200 KB |
| ধাপের `instructions` | 20,000 অক্ষর |
| `say` লাইন | 1,000 অক্ষর |
| সংরক্ষিত `on_enter_tool` ফলাফল | 4 KB |

কোনো নিয়ম ভঙ্গ করে এমন সেভে ভুল ফিল্ডের পাথসহ `400` ফেরত আসে, যেমন
`steps.steps[2].transitions[0].to`। `tools` এবং `on_enter_tool`-এ থাকা টুলের নাম অবশ্যই এজেন্টের সঙ্গে সংযুক্ত টুল হতে হবে।

প্রতি ধাপে আলাদা ভাষা, মডেল এড়িয়ে যাওয়া স্ক্রিপ্টেড ধাপ এবং say লাইনের মধ্যে সংগৃহীত মান সমর্থিত নয়।

## ইমপোর্ট করা এজেন্ট

Retell, Bland, Vapi বা ElevenLabs থেকে [ইমপোর্ট করা](/bn/guides/import-agents) হলে মাল্টি-prompt এজেন্ট, ফ্লো, পাথওয়ে এবং ওয়ার্কফ্লো ধাপ হিসেবে আসে, আর স্কোয়াড ও এজেন্ট ট্রান্সফার ইমপোর্ট করা এজেন্টগুলোর মধ্যকার হ্যান্ডঅফ হিসেবে আসে। ইমপোর্ট করার আগে রিভিউ পেজে উভয়ই দেখা যায়।

## উদাহরণ: ডেন্টাল ইনটেক

ক্রম অনুযায়ী তিনটি ধাপ: অভিবাদন, রোগীর তথ্য সংগ্রহ, বুকিং।

```json
{
  "prompt": "You are Ava, the front desk assistant at Acme Dental. Be warm and brief. Ask one question at a time.",
  "steps": {
    "start_step": "greet",
    "steps": [
      {
        "id": "greet",
        "name": "Greeting",
        "instructions": "Greet the caller and ask how you can help.",
        "say": "Thanks for calling Acme Dental, this is Ava. How can I help you today?",
        "tools": null,
        "collect": [],
        "transitions": [
          {"to": "details", "when": "The caller wants to book an appointment"}
        ]
      },
      {
        "id": "details",
        "name": "Patient details",
        "instructions": "Ask for the caller's full name, date of birth and the reason for the visit. Read the date of birth back and ask the caller to confirm it.",
        "tools": null,
        "collect": [
          {"name": "full_name", "type": "string", "description": "Caller's full name", "required": true},
          {"name": "dob", "type": "date", "description": "Date of birth", "required": true},
          {"name": "reason", "type": "string", "description": "Reason for the visit", "required": true},
          {"name": "new_patient", "type": "boolean", "description": "First visit to the practice", "required": false}
        ],
        "transitions": [
          {"to": "book", "when": "The caller has confirmed their details"}
        ]
      },
      {
        "id": "book",
        "name": "Book",
        "instructions": "Offer the two earliest open slots from book_slot and book the one the caller picks. Confirm the date and time, then say goodbye and end the call.",
        "tools": ["book_slot"],
        "collect": [],
        "transitions": []
      }
    ]
  }
}
```

`PATCH /v1/agents/{agent_id}` দিয়ে এটি স্টেজ করুন, **কথা বলুন** দিয়ে চেষ্টা করুন, তারপর ডিপ্লয় করুন।
নাম, জন্মতারিখ এবং কারণ সংগ্রহ না হওয়া পর্যন্ত `details` ধাপ বুকিংয়ে হ্যান্ডঅফ করতে পারবে না; `new_patient` ঐচ্ছিক।

## উদাহরণ: বয়স-নিয়ন্ত্রিত শাখা

মডেল সবার সঙ্গে কথা বলতে পারে, কিন্তু কাকে বুক করা হবে তা কোড নির্ধারণ করে। বয়স সংগ্রহ করুন, তারপর মডেলের নিজস্ব পছন্দ বিবেচনা করার আগে সেটির ভিত্তিতে রাউট করুন।

```json
{
  "id": "verify",
  "name": "Verify age",
  "instructions": "Ask for the caller's age.",
  "tools": null,
  "collect": [
    {"name": "age", "type": "number", "description": "Caller's age in years", "required": true}
  ],
  "transitions": [
    {"to": "guardian", "condition": {"value": "age", "op": "lt", "target": 18}},
    {"to": "book", "when": "The caller has given their age"}
  ]
}
```

যে কলার পনেরো বলে, মডেল যা-ই নির্ধারণ করুক না কেন, সে `guardian`-এ যায়।
অন্য সবাই `book`-এ যায়। উভয়ই গ্রাফের অন্যত্র সাধারণ ধাপ।

## উদাহরণ: অ্যাকাউন্ট লুকআপ webhook ধাপ

কলার একটি অ্যাকাউন্ট নম্বর দেন, পরবর্তী ধাপে প্রবেশ করার সময় লুকআপ চলে,
এবং এর ফলাফল রুট নির্বাচন করে। সংক্ষিপ্ততার জন্য `not_found`, `collections` এবং `support`
ধাপগুলো বাদ দেওয়া হয়েছে।

```json
[
  {
    "id": "identify",
    "name": "Identify",
    "instructions": "Ask for the caller's account number and read it back digit by digit.",
    "tools": null,
    "collect": [
      {"name": "account_number", "type": "string", "description": "Account number", "required": true}
    ],
    "transitions": [
      {"to": "lookup", "when": "The caller has confirmed their account number"}
    ]
  },
  {
    "id": "lookup",
    "name": "Look up account",
    "instructions": "Tell the caller what you found on their account and ask how you can help.",
    "tools": ["lookup_account"],
    "collect": [],
    "on_enter_tool": "lookup_account",
    "transitions": [
      {"to": "not_found", "condition": {"value": "lookup_account_result.response.found", "op": "eq", "target": false}},
      {"to": "collections", "condition": {"value": "lookup_account_result.response.account_status", "op": "in", "target": ["past_due", "suspended"]}},
      {"to": "support", "when": "The caller needs help with an active account"}
    ]
  }
]
```

`lookup_account` `account_number` গ্রহণ করে, কারণ এর প্যারামিটারের নাম সেটিই।
রেসপন্স বডিতে `"found": false` থাকলে, কলটি `not_found`-এ যায়। এর `account_status`
`past_due` বা `suspended` হলে, এটি `collections`-এ যায়। একটি সক্রিয় অ্যাকাউন্ট
`lookup`-এ থাকে, যেখানে মডেল সহায়তা করে এবং `support`-এ এগিয়ে যায়। ব্যর্থ
লুকআপকে নিজস্ব ধাপে পাঠাতে, প্রথমে স্ট্যাটাসের শর্ত যোগ করুন: একটি ত্রুটি রেসপন্স
তার স্ট্যাটাস কোড সংরক্ষণ করে, তাই
`{"value": "lookup_account_result.status", "op": "gte", "target": 400}`
এটি শনাক্ত করে; আর টাইমআউট বা কোনো উত্তর না পাওয়া গেলে `"error"` সংরক্ষিত হয়, তাই
`{"value": "lookup_account_result.status", "op": "eq", "target": "error"}`
সেটি শনাক্ত করে।

## উদাহরণ: ফ্রন্ট ডেস্ক থেকে বিলিং

দুইটি এজেন্ট। ফ্রন্ট ডেস্ক (এজেন্ট `412`) প্রতিটি কলের উত্তর দেয় এবং বিলিং
সংক্রান্ত প্রশ্নগুলো নিজস্ব prompt, টুল এবং ভয়েসসহ একটি বিলিং এজেন্টের (এজেন্ট `413`) কাছে হস্তান্তর করে।

ফ্রন্ট ডেস্কে:

```json
{
  "handoffs": [
    {"agent_id": 413, "when": "The caller asks about a bill, a payment or a refund"}
  ]
}
```

বিলিং এজেন্টে, যাতে এটি কলারকে আবার ফিরিয়ে দিতে পারে:

```json
{
  "handoffs": [
    {"agent_id": 412, "when": "The billing question is resolved and the caller needs something else"}
  ]
}
```

ফ্রন্ট ডেস্ক সংক্ষিপ্ত একটি লাইন বলে, যেমন "আমি আপনাকে আমাদের বিলিং
টিমের সঙ্গে সংযুক্ত করছি", এবং বিলিং এজেন্ট নিজের পরিচয় দেয় ও ফ্রন্ট ডেস্ক
যেখান থেকে কথোপকথনটি ছেড়েছিল সেখান থেকেই শুরু করে। বিলিং ফিরিয়ে দিলে, ফ্রন্ট ডেস্ক
কলারকে আবার অভিবাদন না জানিয়ে আগের অবস্থান থেকেই চালিয়ে যায়। কলের পণ্য,
ভাষা, সম্মতি ঘোষণা এবং অন্যান্য কল সেটিংস ফ্রন্ট ডেস্কের সঙ্গেই থাকে,
কারণ সেটিই উত্তর দিয়েছিল।

বিলিংয়ের যদি শুধু নিজস্ব নির্দেশনা লাগে, নিজস্ব এজেন্ট না লাগে, তাহলে ফ্রন্ট ডেস্কে
এর বদলে একটি গ্লোবাল ধাপ ব্যবহার করুন। প্রশ্নের উত্তর দেওয়া হলে, কলটি কলার যে ধাপে ছিল
সেই ধাপেই ফিরে যায়:

```json
{
  "id": "billing",
  "name": "Billing questions",
  "instructions": "Answer questions about bills and payments. Offer to send a payment link by email.",
  "tools": null,
  "collect": [],
  "transitions": [
    {"to": "__previous__", "when": "The billing question is answered"}
  ],
  "global_when": "The caller asks about a bill or payment at any point"
}
```

## পরবর্তী ধাপ

<CardGroup cols={2}>
  <Card title="Prompting নির্দেশিকা" icon="pen" href="/bn/guides/prompting">
    ফোনে কার্যকর থাকে এমন শেয়ার করা নির্দেশনা এবং ধাপের নির্দেশনা লিখুন।
  </Card>
  <Card title="একটি টুল ইন্টিগ্রেশন তৈরি করুন" icon="code" href="/bn/guides/build-tool-integration">
    আপনার ধাপ এবং webhook ধাপগুলো যে টুলগুলো কল করে, সেগুলো তৈরি করুন।
  </Card>
  <Card title="আপনার এজেন্টদের পরীক্ষা করুন" icon="flask" href="/bn/guides/test-agents">
    ডিপ্লয় করার আগে প্রতিটি শাখায় একই পরিস্থিতিগুলো চালান।
  </Card>
  <Card title="এজেন্ট API" icon="robot" href="/api-reference/agents">
    প্রতিটি এজেন্ট ফিল্ড, খসড়া এবং ডিপ্লয়।
  </Card>
</CardGroup>
