تصور کنید در حال استفاده از یک جعبه سیاه هستید که با یک دستور ساده، نتایج شگفتانگیز میدهد اما هیچ ایدهای ندارید که در لایههای زیرین چه میگذرد. اگر میخواهید از سطح «کاربر» به سطح «مععمار» سامانههای هوش مصنوعی برسید، باید بدانید بسیاری از چارچوبهای حرفهای عملاً همین ابهام را ایجاد میکنند. ساختن برنامهها با چارچوبهای حرفهای AI اغلب حس استفاده از جعبه سیاهی را دارد که در آن فراخوانی متد .invoke() به شکلی جادویی یک نتیجه تولید میکند.
برای شکستن این لایه انتزاعی، یک توسعهدهنده یک چارچوب کوچک (Mini-framework) برای عاملها منتشر کرده است که هدف آن شبیهسازی ساختار داخلی سیستمهایی مانند LangGraph بدون استفاده از هیچ وابستگی خارجی (External Dependency) است. هدف اصلی این است که تمام «لولهکشیهای» زیرین — شامل ثبتکنندهها (Registry)، تنظیمات اعتبارسنجی شده، Mixinها، دکوراتورها، نشستها (Sessions)، استریمینگ، TypedDictها، پروتکلها و یک رابط خط فرمان (CLI) — به نمایش گذاشته شوند تا کل سیستم از طریق کد منبع قابل توضیح باشد.
بسیاری از یادگیرندگان با هوش مصنوعی عاملمحور (Agentic AI) — یعنی سیستمهایی که مثل یک کارمند مستقل، میتوانند تصمیم بگیرند و ابزارها را برای رسیدن به هدف به کار بگیرند — فقط به صورت تماسهای API با آن تعامل میکنند و نسبت به لولهکشیهای زیرین نابینا هستند. این شکاف دانشی باعث میشود وقتی کلاسهای ابزار شکست میخورند، عیبیابی دشوار شود یا توسعهدهنده نتواند توضیح دهد چرا اعتبارسنجی باید در یک «توصیفگر» (Descriptor) قرار بگیرد نه در متد __init__؛ یا اینکه چگونه ParamSpec ایمنی نوع (Type Safety) را در پشتههای دکوراتور حفظ میکند. در واقع، اتکای بیش از حد به مدلهای پیشرفته بدون درک این زیرساختها میتواند منجر به شکست سیستم شود؛ موضوعی که در تحلیل شکستهای عاملهای هوش مصنوعی به تفصیل بررسی شده است. با بازسازی این سیستمها از صفر، این پروژه الگوهای طراحی خاص پایتون را که معماریهای مقیاسپذیر عاملها را ممکن میسازد، آشکار میکند.
موتور محرک: ابزارهای خودثبتشونده
طبق اعلام سازنده، این چارچوب مشکل رایج «پیدا نشدن ابزار» (Tool not found) را — جایی که ابزاری در کد اضافه شده اما در یک دیکشنری دستی فراموش شده است — با حذف ثبتهای دستی حل کرده است. به جای استفاده از دیکشنریهای دستی، سیستم از متد __init_subclass__ در کلاس BaseTool استفاده میکند. این متد در زمان «تعریف کلاس» اجرا میشود و نه در زمان «نمونهسازی» (Instantiation). این بدان معناست که محیط اجرا (Runtime) به محض وارد کردن (Import) ماژول، از وجود تمام ابزارها آگاه میشود.
- کشف خودکار: ابزارهایی مانند SearchTool صرفاً با اعلام خود از طریق آرگومانهای کلاس مانند
tool_name="search"وstreamable=Trueثبت میشوند. به محض اینکه پایتون کلاس را تجزیه (Parse) کند، ابزار بهطور خودکار ثبت میشود. - طراحی شکست سریع (Fail-Fast): اگر توسعهدهنده فراموش کند آرگومان
tool_nameرا تعریف کند، سیستم بلافاصله در مرحله Import یک خطایTypeErrorایجاد میکند، نه اینکه در حین اجرا با یک شکست گیجکننده مواجه شود. - حل تعارض: کلاس ToolRegistry یک دیکشنری تخت از نوع
dict[str, type]را ذخیره میکند و اگر دو کلاس مختلف سعی کنند نام ابزار یکسانی را تصاحب کنند، خطایDuplicateToolErrorرا صادر میکند.

کنترل دقیق با توصیفگرهای داده
مقادیر اشتباه در تنظیمات که بهطور خاموش در حلقههای تکرار (Retry loops) پیش میروند، عامل اصلی دردهای عملیاتی در محیط تولید هستند. برای جلوگیری از این مورد، این چارچوب از توصیفگرهای داده (Data Descriptors) پایتون برای رهگیری متد __set__ استفاده میکند. این کار تضمین میکند که اعتبارسنجی در لحظه «مقداردهی» رخ دهد، نه در زمان «اجرا».
- IdentifierField: از یک عبارت منظم (
^[a-z][a-z0-9_-]*) استفاده میکند تا تضمین کند نام ابزارها شناسههای معتبر (حروف کوچک الفبایی و عددی) هستند. - IntegerRange: بررسی میکند که مقادیر دقیقاً عدد صحیح باشند و در بازه مشخصی قرار گیرند (مثلاً ۰ تا ۵ برای تعداد دفعات تلاش مجدد). اگر به جای عدد صحیح، یک مقدار Boolean پاس داده شود، صراحتاً خطای
TypeErrorمیدهد. - FloatRange: تضمین میکند که مهلتهای زمانی (Timeouts) بین ۰.۱ تا ۱۲۰.۰ ثانیه اعتبارسنجی شوند.
- BooleanField: یک بررسی استاندارد و اعتبارسنج شده برای تنظیماتی مانند
streaming_enabledفراهم میکند.
این توصیفگرها با استفاده از __slots__ در ToolConfig ادغام شدهاند تا بهرهوری حافظه افزایش یابد. این معماری به سیستم اجازه میدهد بر اساس تنظیمات، یک «پروفایل قابلیت اعتماد» (Reliability Profile) اختصاص دهد: تنظیماتی با بیش از ۳ بار تلاش مجدد و Timeout بیش از ۱۵ ثانیه، «تابآور» (Resilient) نامیده میشود؛ تنظیماتی با ۰ بار تلاش مجدد، «شکست سریع» (Fast-fail) است و هر مورد دیگر «متعادل» (Balanced) برچسب میخورد.
ترکیب رفتاری از طریق Mixins
به جای داشتن یک کلاس پایه حجیم و臃肿، سیستم از Mixinها استفاده میکند تا رفتارها را از طریق ترتیب تفکیک متدها (MRO) در پایتون ترکیب کند. کلاس BaseTool از LoggingMixin، RetryMixin و MetricsMixin ارثبری میکند. هر یک از این Mixinها بدون حالت (Stateless) هستند و از __slots__ = () برای به حداقل رساندن سربار حافظه در عین ارائه قابلیتهای تخصصی استفاده میکنند.
- LoggingMixin: یک متد محدود شده
self.log(message)فراهم میکند که بهطور خودکار هر ورودی لاگ را با نام ابزار پیشوند میزند تا فیلتر کردن گزارشها سادهتر شود. - RetryMixin: متد
self.with_retries(operation)را پیادهسازی میکند که هر تابع قابل فراخوانی (Callable) را در یک حلقه قرار میدهد. اگر عملیاتی شکست بخورد، یک هشدار ثبت میکند (مثلاًattempt 1/3 failed) و تا زمانی که حداکثر تعداد تلاشها تمام شود یا عملیات موفق شود، ادامه میدهد. - MetricsMixin: متد
self.record_metric()و یک شیءself.metricsرا ادغام میکند که توسط یک کلاس Slotted به نام ToolMetrics پشتیبانی میشود تا تعداد کل اجراها، تعداد شکستها و مدت زمان اجرا را ردیابی کند.
کاربران میتوانند زنجیره کامل ارثبری را در زمان اجرا از طریق CLI بررسی کنند. اجرای دستور python main.py describe search توالی MRO را نشان میدهد: SearchTool -> BaseTool -> LoggingMixin -> RetryMixin -> MetricsMixin -> ABC -> object.
ایمنی نوع و مدیریت چرخه حیات
دکوراتورهای ساده پایتون اغلب امضای نوع (Type Signatures) را پاک میکنند و باعث میشوند mypy به جای آرگومانهای واقعی تابع، عبارت Callable[..., Any] را ببیند. برای حل این مشکل، این پروژه از ParamSpec (به عنوان P) و TypeVar (به عنوان R) استفاده میکند. این کار تضمین میکند که وقتی ابزارها با دکوراتورهای @log_execution یا @measure_time تزیین میشوند، کامپایلر همچنان امضای کامل متد run() را تشخیص دهد.
هر بار اجرای ابزار در یک مدیر زمینه (Context Manager) به نام ExecutionSession قرار میگیرد. این مدیریتکننده چرخه حیات، موارد زیر را مدیریت میکند:
- شناسایی: تولید یک شناسه نشست منحصربهفرد (
session_id) با استفاده ازsession-uuid4().hex[:10]که درToolContextجریان مییابد و از طریقToolOutputخارج میشود تا ردیابی کامل (Traceability) ممکن شود. - ردیابی منابع: متد
__enter__زمان شروع را ثبت کرده و آغاز جلسه را لاگ میکند. از طریقsession.add_resource()، سیستم داراییهای زمان اجرا را ردیابی میکند. - خروج پاکیزه: متد
__exit__متدcleanup()را فراخوانی میکند تا منابع ردیابی شده را به ترتیب معکوس آزاد کند و مدت زمان کل جلسه را ثبت نماید. این متد مقدارFalseبرمیگرداند تا استثناها (Exceptions) بهطور عادی به فراخواننده منتقل شوند.
قراردادهای ساختاری و استریم
این چارچوب تفاوت میان کلاس پایه و قرارداد عملیاتی را با استفاده از ToolProtocol روشن میکند. با استفاده از @runtime_checkable و تایپینگ ساختاری (Structural Typing)، سیستم قراردادی ایجاد میکند که نیازمند متدهایی مانند execute()، stream() و run() است. این بدان معناست که هر ابزار شخصثالثی که ToolProtocol را پیادهسازی کند، حتی اگر از BaseTool ارثبری نکند، کاملاً با CLI سازگار است. در حالی که این معماری برای سیستمهای پیچیده است، گاهی اوقات سادهسازی بیش از حد با اسکریپتهای بَش در سناریوهای خاص، کارایی بیشتری را نشان میدهد.
برای خروجیها، سیستم از یک TypedDict به نام ToolOutput استفاده میکند تا تضمین کند هر نتیجه شامل این موارد است: tool (رشته)، content (رشته)، tokens (لیستی از رشتهها)، duration_ms (عدد اعشاری) و session_id (رشته).
سیستم دو مسیر اجرا را پشتیبانی میکند:
۱. استاندارد: متد execute() را فراخوانی میکند تا یک رشته کامل را برگرداند.
۲. استریمینگ: از یک Generator در متد stream() استفاده میکند تا توکنها را یکییکی تولید کند (مثلاً با تقسیم یک رشته بر اساس فاصلهها).
نکته کلیدی این است که BaseTool.run() هر دو مسیر را در یک بلوک try...finally قرار میدهد. این کار تضمین میکند که متد self.record_metric() تحت هر شرایطی (چه ابزار موفق شود و چه با شکست مواجه شود) فراخوانی شود و مشاهدهپذیری (Observability) مورد نیاز برای سیستمهای سطح تولید فراهم گردد.
این تحلیل عمیق معماری، تمرکز را از «چگونه از یک عامل استفاده کنیم» به «چگونه موتور را بسازیم که عامل را اجرا کند» تغییر میدهد. این پروژه نشان میدهد که پیچیدگی چارچوبهای تولیدی، جادو نیست، بلکه مجموعهای از الگوهای منضبط پایتون — مانند توصیفگرها برای اعتبارسنجی و پروتکلها برای توسعهپذیری — است که برای پایداری طراحی شدهاند.
این پروژه اولین بخش از یک سری ساخت ۱۶ هفتهای است. پس از این پیریزی پایتون، این دوره از طریق یک برنامه جامع پیش خواهد رفت: پردازش زبان طبیعی (NLP)، جاسازیها (Embeddings)، داخلیاتی مدلهای زبانی بزرگ (LLM Internals)، بازیابی تقویتشده (RAG) و در نهایت استقرار چندعاملی از طریق پروتکل زمینه مدل (MCP).
گام بعدی شما
- بررسی مخزن کد این پروژه برای درک نحوه پیادهسازی
__init_subclass__جهت حذف ثبت دستی ابزارها. - جایگزینی اعتبارسنجیهای ساده در
__init__با توصیفگرهای داده (Descriptors) برای افزایش پایداری ورودیها در پروژههای خود. - مطالعه مستندات
ParamSpecبرای جلوگیری از دست رفتن Type Hintها هنگام نوشتن دکوراتورهای سفارشی.
ama این تنها لایه اول از یک نقشه جامع است؛ در گامهای بعدی، این مسیر از مفاهیم پایه پایتون به سمت دنیای پیچیده NLP و استقرار چندعاملی با پروتکل MCP حرکت خواهد کرد.




گفتگو