تصور کنید برنامهنویسی هستید که یک عامل خودکار را در محیط عملیاتی مدیریت میکند و ناگهان متوجه میشوید یک تراکنش مالی دو بار تکرار شده، اما لاگهای سیستم فقط عبارت «موفق» یا «ناموفق» را نشان میدهند. این تاریکی در لایهی اجرا، کابوسی برای عیبیابی است؛ وقتی یک درخواست ۱۲ ثانیه طول میکشد و یک تلاش مجدد (Retry) خاموش را فعال میکند، تیم توسعه هرگز نمیفهمد عملیات یکبار انجام شده یا دوبار.
همانطور که در تحلیل قبلی ما دربارهی تلههای محیط عملیاتی و اینکه چگونه این تلهها میتوانند باعث افزایش سرسامآور هزینههای استنتاج مدلهای زبانی شوند اشاره کردیم، مشکل اصلی اغلب نبود قابلیت مشاهده (Observability) در مرز ابزارهاست. وقتی یک عامل (Agent) — شبیه به کارمندی که دسترسی به ابزارهای مختلف دفتر دارد تا کارهای شما را پیش ببرد — با سرویسهای خارجی تعامل میکند، شکاف بین «قصد مدل» و «عمل سرویس» جایی است که اکثر خطاها در آن پنهان میشوند.
زمینه شکست
یک عامل را در نظر بگیرید که برای طبقهبندی یک تیکت پشتیبانی، باید سه ابزار را فراخوانی کند: جستوجوی اطلاعات مشتری، بررسی وضعیت پرداخت و در نهایت ایجاد یک تسک. اگر یکی از این فراخوانیها متوقف شود یا دچار تأخیر شود، لاگها ممکن است دو ورودی متفاوت با request_idهای مختلف را نشان دهند، اما این لاگها هرگز شفاف نمیکنند که آیا تسک واقعاً یکبار ایجاد شده است یا دوبار. این چالشها یادآور نرخ شکست بالای مدلهای زبانی در تحلیل دقیق فراخوانی ابزارهاست که نشان میدهد تکیه بر خروجی خام مدل بدون لایهی نظارتی، ریسک خطای عملیاتی را افزایش میدهد.
در این ساختار، نمودار ذهنی جریان به این شکل است: مدل $ \rightarrow $ آداپتور ابزار $ \rightarrow $ سرویس خارجی $ \rightarrow $ پاسخ $ \rightarrow $ مدل. طبق این منطق، رسید باید در لایهی آداپتور (Adapter) — یعنی همان لایهی سازگارساز که زبان مدل را به زبان سرویس ترجمه میکند — قرار بگیرد. اگر شما فقط در سرویس خارجی لاگ بگیرید، بستر و زمینه تصمیمگیری عامل را از دست میدهید. از سوی دیگر، اگر بخواهید همه چیز را در پرامپت ثبت کنید، هزینههای توکن و نویز دادهها به شدت و با سرعت افزایش مییابد.
کالبدشکافی یک رسید
به نقل از راهنمای فنی منتشر شده در dev.to در ۱۳ سپتامبر ۲۰۲۶، راهکار بهینه، پیادهسازی یک «رسید اجرایی» (Execution Receipt) در آداپتور ابزار است. به جای تکیه بر لاگهای سرویسهای خارجی یا ثبت کل پرامپت، آداپتور برای هر تلاش (Attempt) یک شیء دادهای حداقلی تولید میکند.
یک رسید کاربردی باید شامل نشانگرهای فنی خاصی برای تضمین قابلیت ردیابی باشد. یک رکورد مفید میتواند به این شکل باشد:{ "run_id": "run_82f", "tool_call_id": "call_17", "tool": "lookup_customer", "attempt": 2, "status": "ok", "started_at": "2026-09-13T02:00:00Z", "duration_ms": 842, "input_hash": "sha256:...", "output_summary": {"fields": ["customer_id", "plan"]}, "error_class": null }.
اجزای کلیدی این ساختار عبارتند از:
- شناسهها: یک
run_idوtool_call_idمنحصربهفرد برای گروهبندی تمام تلاشهای مربوط به یک درخواست. - عملکرد: برچسب زمانی
started_atو مقدارduration_msکه با استفاده از یک ساعت یکنواخت (Monotonic Clock) اندازهگیری شده است. - نتیجه: طبقهبندی وضعیت به دستههای مشخص (موفق/ok، تایماوت/timeout، خطای قابل تکرار/retryable_error یا خطای نهایی/terminal_error).
- یکپارچگی دادهها: استفاده از هش ورودی (SHA-256) به جای ذخیره کل متن ورودی، و ارائه خلاصهای از فیلدهای خروجی به جای کپی کامل پاسخ.
این ساختار مانع از تبدیل شدن لاگها به یک پایگاه داده دوم از اطلاعات حساس میشود و در عین حال یک ردپای حسابرسی (Audit Trail) شفاف ایجاد میکند. برای مثال، در مورد حسابرسی ایمیلهای خودکار، رسید میتواند به شناسه پیام متصل شود در حالی که محتوای اصلی ایمیل به صورت جداگانه نگهداری میشود.
پیادهسازی قرارداد حداقلی
آداپتور باید یک قرارداد یکسان و یکپارچه را بر تمام ابزارها تحمیل کند. این لایه باید پیش از هرگونه اجرا، tool_call_id را تولید کند، زمان شروع را علامتگذاری نماید و رسید را در یک خروجی «فقط-افزودنی» (Append-only) ثبت کند. نکته حیاتی این است که آداپتور در نهایت فقط نتایجی را به مدل برمیگرداند که طبق قرارداد ابزار مجاز است.
این تفکیک باعث ایجاد یک جداسازی سالم میشود: مدل زبانی بزرگ (LLM) — مثل کتابخانهداری که میلیاردها صفحه را خوانده و حالا با همان لحن جواب میدهد — فقط تصمیم میگیرد که چه چیزی درخواست شود، اما آداپتور تصمیم میگیرد چه چیزی ثبت شود، کدام فیلدها ماسک شوند و کدام خطاها قابلیت تکرار دارند. این رویکرد در واقع بخشی از استراتژی مدیریت جریانهای کاری ساختاریافته برای مقیاسپذیری عاملهاست تا از هرجومرج در تعاملات مدل با ابزارها جلوگیری شود.
مدیریت اثرات جانبی
تایماوتها بهویژه خطرناک هستند چون تضمین نمیکنند که سرور عملیات را اجرا نکرده است. برای جلوگیری از پرداختهای تکراری یا ارسال پیامهای مکرر، این راهنما توصیه میکند از کلیدهای همتوانسازی (Idempotency Keys) استفاده شود که یا از run_id و tool_call_id مشتق شدهاند و یا کلیدی صریح هستند که توسط سرویس پذیرفته میشوند.
جریان پیشنهادی به این ترتیب است: شروع $ \rightarrow $ تایماوت $ \rightarrow $ پرسوجوی وضعیت (State Query) $ \rightarrow $ تکرار ایمن. اگر پرسوجوی وضعیت ممکن نیست، رسید باید عملیات را «نامعلوم» (Unknown) علامت بزند، نه «ناموفق»؛ زیرا تکرار یک عملیات با وضعیت نامعلوم میتواند منجر به تکرار خطرناک تراکنشها شود.
بسیار حیاتی است که رسیدهای تمام تلاشها را که توسط tool_call_id گروهبندی شدهاند، حفظ کنید. بازنویسی یا جایگزینی تلاش اول، دقیقاً همان شواهدی را پاک میکند که برای توضیح یک حادثه فنی به آنها نیاز دارید.
چکلیست پیادهسازی
پیش از استقرار در محیط عملیاتی، موارد زیر را بررسی کنید:
- آیا هر فراخوانی دارای یک شناسه پایدار و
run_idاست؟ - آیا خطاهای قابل تکرار از خطاهای نهایی (Terminal) تفکیک شدهاند؟
- آیا عملیاتهای دارای اثر جانبی (Side-effect) از همتوانسازی استفاده میکنند؟
- آیا رسید شامل مدتزمان، شماره تلاش و کلاس خطا است؟
- آیا ورودیها و خروجیهای حساس ماسک یا خلاصه شدهاند؟
- آیا میتوانید توالی اتفاقات را بدون نیاز به کل پرامپت بازسازی کنید؟
- آیا یک سیاست نگهداری (Retention Policy) تعریف شده و راهی برای جستوجو بر اساس نوع ابزار وجود دارد؟
این تغییر، فرض بنیادی نظارت بر عاملها را عوض میکند و مسئولیت لاگ را از حافظه مدل به یک قرارداد فنی سختگیرانه و فقط-افزودنی منتقل میکند. با جداسازی آنچه LLM تصمیم میگیرد از آنچه آداپتور ثبت میکند، تیمها میتوانند دادههای حساس را ماسک کرده و منطق تکرار را بدون آلوده کردن بستر (Context) مدل کنترل کنند.
برای توسعهدهنده، این یعنی عیبیابی دیگر به شهود یا خواندن هزاران خط تاریخچه مدل وابسته نیست. شما اکنون میتوانید توالی دقیق اتفاقات را با فیلتر کردن یک tool_call_id خاص در تمام تلاشهای آن بازسازی کنید.
گام بعدی شما
- الگوی رسید را ابتدا روی یک ابزار «فقط-خواندنی» (Read-only) پیاده کنید تا پایداری آن را بسنجید.
- برای ابزارهای دارای اثر جانبی، سناریوی تایماوت، پاسخ دیرهنگام و تکرار را شبیهسازی کنید تا تأیید شود که منطق همتوانسازی و «وضعیت نامعلوم» شما از اقدامات تکراری جلوگیری میکند.
- یک سیاست نگهداری (Retention Policy) برای رسیدها تعریف کنید تا حجم دادههای ذخیره شده مدیریت شود.
اما مدیریت این رسیدها در مقیاس هزاران عامل همزمان، چالشهای جدیدی در زیرساخت ایجاد میکند — به تحلیل ما دربارهی بهینهسازی پایگاههای داده برداری مراجعه کنید.




گفتگو