
আগের পোস্টে এজেন্ট turn আর সেশনের মাঝে কী মনে রাখে তা নিয়ে লিখেছিলাম। তাকে কী করতে হবে আর কী কী আছে তার হাতে, সেটাই যদি অস্পষ্ট ভাষায় লেখা থাকে, তাহলে নিখুঁত memory সিস্টেমও কাজে লাগে না — ঠিক সামনে থাকা tool-টাই যদি সে কখন ব্যবহার করবে না জানে, memory তাকে বাঁচাতে পারে না।
এজেন্টের জন্য prompt engineering সাধারণ চ্যাটবটকে prompt দেওয়ার চেয়ে আলাদা। একটা মাত্র উত্তরের জন্য নির্দেশ লেখার বদলে, আপনি এমন কিছু লিখছেন যা মডেল loop-এর প্রতিটা ধাপে নতুন করে পড়ে — তার role, ঠিক কখন কোন tool ব্যবহার করবে, তার সীমা কোথায়, আর কাজ শেষ মানে কী, সবকিছু। কোনো tool-এর trigger অস্পষ্ট রাখলে মডেল আন্দাজ করে; থামার শর্ত অস্পষ্ট রাখলে সে হয় খুব তাড়াতাড়ি থেমে যায়, নয়তো দরকারের চেয়ে বেশিক্ষণ চলতে থাকে।
সাধারণ Prompt বনাম এজেন্টের System Prompt
একটা সাধারণ prompt একটা জিনিস চায়, একবার বিচার হয়: “একটা প্রোডাক্ট description লিখে দাও,” পড়া হলো, শেষ। এজেন্টের system prompt একবার পড়া হয় না। এজেন্টের চারটা অংশ নিয়ে পোস্টে system prompt-কে চাকরির বিবরণ বলা হয়েছিল, এখানেও সেটাই সত্যি — শুধু এই চাকরির বিবরণ loop যতক্ষণ চলে, প্রতিটা ধাপে নতুন করে মডেলের হাতে তুলে দেওয়া হয়। একবারের জন্য লেখা কোনো prompt-এ একটা অস্পষ্ট নির্দেশের খরচ একটা খারাপ উত্তর। এজেন্টের system prompt-এ একই অস্পষ্টতার খরচ প্রতিটা ধাপে একটা করে খারাপ সিদ্ধান্ত, আর লম্বা কথোপকথনে এটা গড়ে মিলিয়ে যায় না — বরং জমতে থাকে।
একজন নতুন কর্মীকে ভাবুন, যাকে চাকরির প্রথম দিন একবার নিয়মাবলী বুঝিয়ে দেওয়া হয়, আর তারপর তিনি নিজের অভিজ্ঞতা দিয়ে বাকিটা সামলান — এটা সাধারণ prompt-এর মতো। এজেন্ট তার থেকে আলাদা: তাকে যেন প্রতিটা কাজের আগে আগের কোনো স্মৃতি ছাড়াই আবার সেই একই নিয়মাবলী হাতে ধরিয়ে দেওয়া হয়, আর সেই কাগজে যদি একটা লাইনও অস্পষ্ট থাকে, প্রতিটা কাজেই তিনি নতুন করে সেই একই জায়গায় আটকাতে পারেন।
flowchart LR
SP[System prompt-এর লেখা] --> T1[Step ১-এ নতুন করে পড়া]
SP --> T2[Step ২-এ নতুন করে পড়া]
SP --> T3[Step N-এ নতুন করে পড়া]
T1 --> R1{Trigger অস্পষ্ট?}
T2 --> R2{Trigger অস্পষ্ট?}
T3 --> R3{Trigger অস্পষ্ট?}
R1 -->|ভুল আন্দাজের ঝুঁকি| X1[সম্ভাব্য ভুল]
R2 -->|ভুল আন্দাজের ঝুঁকি| X2[সম্ভাব্য ভুল]
R3 -->|ভুল আন্দাজের ঝুঁকি| X3[সম্ভাব্য ভুল]Flow-এর সারসংক্ষেপ: একই system prompt-এর লেখা loop-এর প্রতিটা ধাপে নতুন করে পড়া হয়, তাই তার ভেতরের যেকোনো অস্পষ্টতা প্রতিবারই সমান ভুল আন্দাজের ঝুঁকি বহন করে, একবার না — অনেক ধাপ ধরে এই ঝুঁকি গড়ে মিলিয়ে যায় না, বরং জমতে থাকে।

একটা ভালো এজেন্ট Prompt-এ যে পাঁচটা জিনিস থাকা উচিত
Role। এজেন্ট আসলে কী, এক-দুই বাক্যে। জীবনী না — শুধু এতটুকু, যাতে মডেল বুঝতে পারে তাকে কোন ধরনের কাজ করতে বলা হচ্ছে, আর কোনটা তার আওতার বাইরে।
Tools, আর ঠিক কখন কোনটা ব্যবহার করবে। শুধু tool-এর নামের তালিকা যথেষ্ট না; মডেলের জানা দরকার কোন পরিস্থিতিতে কোনটা ডাকতে হবে। “ব্যবহারকারী X জিজ্ঞেস করলেই এটা ব্যবহার করুন” — এই ধরনের বাক্যই কাজ করে, আর এটা ঠিক তখনই সবচেয়ে বেশি গুরুত্বপূর্ণ হয়ে ওঠে যখন একই মেসেজের জন্য দুটো tool-ই যুক্তিসঙ্গত মনে হতে পারে।
সীমা। এজেন্ট কখনো কী করবে না: কোনো tool আসলে যা ফেরত দেয়নি এমন ডেটা বানিয়ে বলা, নিশ্চিত না করে কোনো ফিরিয়ে আনা যায় না এমন কাজ করে ফেলা, বা দেওয়া tool-এর বাইরে গিয়ে কাজ করা। আগের পোস্টগুলোর step limit আর আগে-পড়ো-পরে-লেখো নিয়মের একই চেতনা, শুধু এবার সেটা অনুমান করে নেওয়ার বদলে prompt-এই স্পষ্ট করে লেখা।
অনিশ্চয়তা সামলানো। জিজ্ঞেস করবে, আন্দাজ করবে, নাকি মানুষের কাছে পাঠাবে — অস্পষ্ট পরিস্থিতির জন্য স্পষ্টভাবে একটা বেছে দিন, প্রতিবার মডেলকে নিজে থেকে ঠিক করতে দেওয়ার বদলে।
“শেষ” মানে কী। একটা স্পষ্ট থামার শর্ত, যাতে এজেন্ট জানে কখন tool ডাকা বন্ধ করে শুধু উত্তর দেবে। এটা না থাকলে ঠিক সেই সমস্যাই হয় যা step limit না থাকলে হয়: এজেন্ট হয় কাজ শেষ হওয়ার আগেই থেমে যায়, নয়তো কাজে লাগার সীমা পেরিয়েও চলতে থাকে।
Tool Description-ও একটা Prompt
Tool calling নিয়ে পোস্টে এই কথাটা একবার বলা হয়েছিল: মডেল কোনো tool-এর কোড কখনো পড়ে না, শুধু তার description পড়ে, তাই এই field-টা নিজেই prompt engineering-এর একটা অংশ, আলাদা কোনো বিষয় না। এই সিরিজের আসল tool description-গুলো ফিরে দেখলেই প্যাটার্নটা স্পষ্ট হয়ে যায়। Memory নিয়ে পোস্টের add_expense-এর description ছিল: “Record one expense. Use it whenever the user says they spent money.” সেই trigger phrase-টা সত্যিকারের কাজ করছে। একই ফাইলের get_total-এর description ছিল: “Return the exact total of all recorded expenses in BDT.” কোনো trigger phrase-ই নেই — আর এটা পার পেয়ে গেছে শুধু এই কারণে যে সেই ছোট্ট toolset-এ “total”-এর সাথে গুলিয়ে ফেলার মতো আর কিছুই ছিল না।
আসল নিয়মটা তাই “সবসময় trigger phrase যোগ করো” নয়, সার্বজনীন একটা আদেশ হিসেবে: কোনো tool-এর নাম তার আশেপাশের tool থেকে যত কম আলাদা করা যায়, description-কে ততটাই বেশি কাজ করতে হয় পার্থক্য বোঝানোর জন্য। অনুরূপ শোনায় এমন একটা দ্বিতীয় tool মাথায় রেখে নতুন করে লিখলে, get_total হয়ে দাঁড়ায়: “Return the exact sum of every expense recorded so far, in BDT. Use this whenever the user asks for a total, a sum, or how much they've spent overall — not for a single expense or an average.” Tool-এর আচরণে কিছুই বদলায়নি। শুধু ভবিষ্যতের কোনো পাঠক — মানুষ হোক বা মডেল — যে বাক্যটা পড়ে একে get_average_expense-এর মতো কিছু থেকে আলাদা করবে, সেটাই বদলেছে।
গঠনমূলক একটা System Prompt, আর যাচাই করার একটা উপায়
npm install @anthropic-ai/sdk দিয়ে SDK ইনস্টল করুন, কোনো আসল এজেন্টে এটা জুড়তে চাইলে ANTHROPIC_API_KEY সেট করুন, ফাইলটা agent/prompt-template.ts নামে সেভ করে npx tsx agent/prompt-template.ts চালিয়ে শুধু checker-এর ফলাফল দেখুন।
// agent/prompt-template.ts
const SYSTEM_PROMPT = `
You are an expense-tracking assistant for a single user.
## Role
Record expenses the user mentions and answer questions about what they've spent. You do not give financial advice.
## Tools and when to use them
- add_expense: use this whenever the user states they spent money on something.
- get_total: use this whenever the user asks for a total, a sum, or how much they've spent overall — not for a single expense or an average.
- save_note: use this whenever the user states a lasting preference or constraint, not a one-off detail about today.
## Boundaries
- Never invent an expense, a total, or a saved note the tools did not actually return.
- Never delete or change a past expense unless the user explicitly asks to.
## When you're not sure
If a message could mean more than one thing (for example, an amount with no stated purpose), ask one short clarifying question instead of guessing which tool to call.
## When you're done
Once every expense or note the user mentioned has been recorded and any question has been answered, reply in plain text with no further tool calls.
`.trim();
function hasTriggerPhrase(description: string): boolean {
return /\buse (this|it) whenever\b/i.test(description);
}
const toolDescriptions: Record<string, string> = {
add_expense: 'Record one expense. Use it whenever the user says they spent money.',
get_total_before: 'Return the exact total of all recorded expenses in BDT.',
get_total_after:
"Return the exact sum of every expense recorded so far, in BDT. Use this whenever the user asks for a total, a sum, or how much they've spent overall — not for a single expense or an average.",
};
for (const [name, description] of Object.entries(toolDescriptions)) {
console.log(name, '->', hasTriggerPhrase(description) ? 'has trigger phrase' : 'MISSING trigger phrase');
}
console.log('\n--- system prompt preview ---');
console.log(SYSTEM_PROMPT);
SYSTEM_PROMPT হলো সেই পাঁচটা অংশ, আসল heading আকারে সাজানো, যা সরাসরি system:-এ পাঠানোর জন্য, tool-calling পোস্টের চেনা tool-আর-loop ধরনের পাশাপাশি। hasTriggerPhrase হলো যান্ত্রিকভাবে সত্যিই যাচাই করা যায় এমন একটা ছোট্ট, সৎ অংশ: কোনো description-এ স্পষ্ট “use this/it whenever” trigger আছে কিনা। Memory নিয়ে পোস্টের আসল get_total description আর তার নতুন সংস্করণের ওপর এটা চালালে ঠিক ওপরের ফাঁকটাই দেখা যায় — আসল সংস্করণ check-এ ফেল করে, নতুন সংস্করণ পাস করে, আর এর জন্য আসল কোনো মডেল দুটোর কোনটায় কেমন সাড়া দিত তা আন্দাজ করার দরকারই নেই।

এজেন্ট Prompt-এ সাধারণ ভুল
- System prompt-কে আলাদা অংশের বদলে একগাদা উপদেশের একটা ব্লক হিসেবে লেখা। “সহায়ক আর সতর্ক থাকো” লিখলে মডেল বুঝতে পারে না কখন কোনো tool ডাকবে বা কখন থামবে। গঠন জেতে, পরিমাণ না।
- Tool description একে অন্যের থেকে বিচ্ছিন্নভাবে লেখা। একা পড়লে ঠিকঠাক শোনানো একটা description, একই তালিকায় পাশের tool-এর description-এর সাথে বসালে গুলিয়ে যেতে পারে — একটা একটা করে না দেখে, একসাথে রিভিউ করুন।
- স্পষ্ট কোনো থামার শর্ত না থাকা। এটা না থাকলে মডেলকে শুধু প্রসঙ্গ দেখেই অনুমান করতে হয় কাজ শেষ কিনা, আর এটাই ঠিক সেই ধরনের আন্দাজ যা একটা স্পষ্ট prompt দূর করার কথা।
- আচরণ না বদলায় এমন সাধারণ উপদেশ দিয়ে prompt ভরিয়ে ফেলা। প্রতিটা বাড়তি বাক্য প্রতিটা ধাপে নতুন করে পড়া হয়। কোনো লাইন মডেলের কাজে আসলেই কিছু না বদলালে, সেটা জায়গা দখল করার যোগ্য না।
এরপর
একটা গঠনমূলক prompt এজেন্টকে বলে দেয় সে কী করতে পারে আর কখন। সে আসলেই সেই prompt ভালোভাবে অনুসরণ করছে কিনা — আর সেটা শুধু ধরে নেওয়ার বদলে কীভাবে মাপবেন — এটা নিয়ে আলাদা একটা পোস্ট লেখার মতো যথেষ্ট আছে।
প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী (FAQ)
ভালো করে লেখা একটা prompt কি ভালো tool design-এর বদলি হতে পারে?
না। স্পষ্ট একটা trigger phrase এমন একটা tool-এর input সত্যিই অস্পষ্ট হলে সেটা ঠিক করতে পারে না, আর নিখুঁতভাবে ডিজাইন করা একটা tool-ও মডেলকে কখন সেটা ধরতে হবে তা বলে দেওয়া দরকার। দুটো একই সমস্যার দুই আলাদা অর্ধেক সমাধান করে: tool design tool-calling পোস্ট থেকে, prompt-এর গঠন এখান থেকে।
এজেন্টের system prompt কত লম্বা হওয়া উচিত?
ঐ পাঁচটা অংশ ঢাকতে যতটা লাগে, তার বেশি না। “সহায়ক হও” বা “ভালো করে ভাবো”-র মতো সাধারণ উপদেশ প্রতিটা ধাপে নতুন করে পড়া হয়, অথচ মডেলের আসল আচরণে কিছুই বদলায় না। কোনো বাক্য role-এর বিবরণ, কোনো tool-এর trigger, কোনো সীমা, অনিশ্চয়তার নিয়ম, বা থামার শর্ত — এর কোনোটাই না হলে, সেটা সম্ভবত জায়গা পাওয়ার যোগ্য না।
আমার system prompt কি কোডের মতো করেই টেস্ট করা উচিত?
Deterministic অংশগুলো, হ্যাঁ — প্রতিটা tool description-এ স্পষ্ট একটা trigger আছে কিনা, এটা যাচাই করার মতো একটা property, আর এই পোস্টের ছোট্ট checker ঠিক সেটাই করে। মডেল বাস্তবে prompt কতটা ভালোভাবে অনুসরণ করছে, সেটা আলাদা ধরনের টেস্টিং, unit test-এর চেয়ে evaluation-এর কাছাকাছি, আর সেটা নিজেই আলাদা একটা বিষয় হিসেবে ভাবার মতো।
কাস্টম ওয়েব অ্যাপ বা এআই অটোমেশন বানাতে চান?
আমি স্টার্টআপ ও আধুনিক ব্যবসার জন্য স্কেলেবল ফুল-স্ট্যাক ওয়েব অ্যাপ্লিকেশন (Next.js, React, Node, PostgreSQL) এবং ইন্টেলিজেন্ট এআই এজেন্ট সলিউশন তৈরি করি। আপনার প্রজেক্টের আইডিয়া নিয়ে কথা বলা যাক!
আর্টিকেলটি কি আপনার ভালো লেগেছে?
তন্ময়ের কাজকে সাপোর্ট করতে তালি (Clap) দিয়ে উৎসাহিত করুন!
জাহিদ হাসান তন্ময়
সফটওয়্যার ডেভেলপার
MERN ফুল-স্ট্যাক ডেভেলপার এবং AI এজেন্ট ডেভেলপার, ঢাকা, বাংলাদেশ। ওয়েব ডেভেলপমেন্ট, রিঅ্যাক্ট, লারাভেল এবং আমার লার্নিং জার্নি নিয়ে লিখছি।