گوگل در گامی جدید برای ساده‌سازی توسعه برنامه‌های هوش مصنوعی API کاربران (Agents API) را به صورت پیش‌نمایش برای جنکیت (Genkit)، چارچوب متن‌باز خود جهت ساخت برنامه‌های فُل‌استک (full-stack) AI منتشر کرد. این انتشار به توسعه‌دهندگان امکان می‌دهد تا با یک انتزاع واحد، از چت‌بات‌های ساده تا جریان‌های کار چندعامله (multi-agent) پیچیده را مدیریت کنند.

یک انتزاع، تمام مقیاس‌ها: از پاسخ تک‌مرحله تا وظایف طولانی‌مدت

فلسفه طراحی جنکیت بر پایه "یک انتزاع که بدون تعویض اولیه‌ها (primitives) مقیاس‌پذیر است" استوار است. همان شیء Agent قادر است:

  • یک پاسخ تک‌مرحله (one-shot) تولید کند.
  • یک گفتگوی چندنوبته جریان‌یافته (streamed multi-turn) را هدایت نماید.
  • اجرای ابزاری را برای تأیید انسان (human-in-the-loop) متوقف سازد.
  • یک وظیفه جدا شده (detached task) طولانی‌مدت را در پس‌زمینه مدیریت کند.

تیم‌های توسعه دیگر نیازی ندارند با رشد ویژگی‌ها، بین مؤلفه‌های مختلف چارچوب جابجا شوند؛ یک API واحد تمام سناریوها را پوشش می‌دهد. پیش‌نمایش فعلی برای تایپ‌اسکریپت (TypeScript) و گو (Go) عرضه شده و پشتیبانی از پایتون و دارت در نقشه راه قرار دارد.

تفکیک حالت سفارشی و آرتیفکت‌ها: معماری داده‌های تمیز

جنکیت دو دسته داده را که در اکثر چارچوب‌ها در هم آمیخته شده‌اند، جدا می‌کند:

  • حالت سفارشی (Custom State): داده‌های تایپ‌شده برنامه که منطق نوبت بعدی را هدایت می‌کنند (مثلاً وضعیت گردش کار، لیست وظایف، موجودیت‌های انتخاب‌شده).
  • آرتیفکت‌ها (Artifacts): خروجی‌های تولیدی که کاربر به طور مستقل بازبینی، دانلود یا نسخه‌بندی می‌کند (گزارش‌ها، پچ‌های کد، برنامه‌های سفر).

ابزارها از طریق جلسه فعال هر یک را به‌روزرسانی می‌کنند و جنکیت تغییرات را به‌صورت زنده به کلاینت استریم (stream) می‌کند.

دو مسیر برای ماندگاری حالت (State Persistence)

۱. مدیریت سروری (Server-Managed) با Session Store

با پیکربندی یک ذخیره‌گاه جلسه، پیام‌ها، حالت سفارشی و آرتیفکت‌ها به عنوان عکس‌های فوری (snapshots) ذخیره شده و کلاینت‌ها با sessionId مجدداً متصل می‌شوند. جنکیت به طور پیش‌فرض ذخیره‌گاه‌های زیر را ارائه می‌دهد:

  • Firestore: برای تولید چندنمونه (multi-instance) و مقیاس‌پذیری بالا.
  • در حافظه (In-memory): مناسب توسعه و تست سریع.
  • مبتنی بر فایل (File-based): برای تست‌های محلی.

علاوه بر این، یک رابط قابل اتصال (pluggable interface) برای پیاده‌سازی‌های سفارشی وجود دارد.

۲. مدیریت کلاینتی (Client-Managed) برای اقامت داده و حریم خصوصی

بدون ذخیره‌گاه، سرور حالت کامل را برمی‌گرداند و کلاینت در هر نوبت آن را بازمی‌فرستد. این رویکرد برای جلسات زودگذر (ephemeral) یا برنامه‌هایی با محدودیت‌های سخت اقامت داده (data residency) ایده‌آل است.

ابنِزر دان (Ebenezer Don)، مهندس هوش مصنوعی: "این رویکرد برای برنامه‌هایی که سرور نباید داده‌های کاربر را ماندگار کند، بی‌نظیر است. هزینه‌ی آن افزایش بار شبکه (payload size) با رشد گفتگو است."


نمودار معماری Genkit Agents API با Detached Turns و Human-in-the-Loop

دو قابلیت متمایز در منظر چارچوب‌های عامله‌محور

نوبت‌های جدا شده (Detached Turns): אסینکرونیسم واقعی بدون WebSocket

با detach() کلاینت می‌تواند یک وظیفه را آغاز کند، قطع اتصال کند و بعداً برای نتایج نظرسنجی (poll) کند. عامل در سمت سرور کار را ادامه داده و پیشرفت را در عکس‌های فوری ثبت می‌کند که هر کلاینتی می‌تواند بخواند. این الگو نیاز به WebSocket، صف وظیفه جداگانه یا نگه‌داشتن اتصال باز را از بین می‌برد.

const chat = reportAgent.chat({ sessionId: 'report-123' });
const task = await chat.detach('Write the quarterly market report.');
savePendingSnapshot(task.snapshotId);
for await (const snapshot of task.poll({ intervalMs: 1000 })) {
  renderStatus(snapshot.status);
  if (snapshot.status === 'completed') renderMessages(snapshot.state.messages);
}

این قابلیت کارهای تحقیقاتی طولانی، برنامه‌ریزی چندمرحله و گردش‌کارهای پر از ابزار را عملی می‌سازد.

ابزارهای قابل وقفه (Interruptible Tools): کنترل انسان در حلقه با امنیت ضد تقلب

وقتی یک ابزار به عنوان interruptible علامت‌گذاری می‌شود، عامل در میان اجرا متوقف شده، اقدام معلق را به کلاینت برمی‌گرداند و تنها پس از تأیید یا رد کاربر ادامه می‌یابد. Runtime گواهینامه (resume payload) را با تاریخچه جلسه اعتبارسنجی می‌کند تا از تزریق ورودی‌های جعلی جلوگیری نماید.

مثال در گو (Go):

runShell := genkitx.DefineInterruptibleTool(g, "run_shell",
  "Run a shell command after a safety check.",
  func(ctx context.Context, input ShellInput, confirm *Confirmation) (ShellOutput, error) {
    if isRisky(input.Command) {
      if confirm == nil {
        return ShellOutput{}, tool.Interrupt(ShellInterrupt{
          Command: input.Command, Reason: "The command can modify files.",
        })
      } else if !confirm.Approved {
        return ShellOutput{}, errors.New("user rejected shell command execution")
      }
    }
    return execute(input.Command)
  })

چرا جنکیت برای تیم‌های مدرن جذاب است؟

  • توسعه سریع: یک API برای تمام پیچیدگی‌ها.
  • انعطاف استقرار: اجرا در پردازش (in-process) یا به عنوان سرویس HTTP.
  • رعایت انطباق (Compliance): گزینه مدیریت کلاینتی برای حریم خصوصی داده.
  • استفاده از زیرساخت موجود: بدون نیاز به очеред جدید یا WebSocket برای کارهای طولانی.

برای مطالعه مستندات کامل و نمونه‌های کد به مستندات رسمی جنکیت در فایربیس مراجعه کنید.