الانتقال إلى المحتوى الرئيسي
ملف مواصفات الـ agent بالإصدار 2 (agent spec v2) هو ملف YAML أو JSON يصف agent كاملًا كبيانات عادية: الـ model، والتعليمات، والـ tools، وخوادم MCP، والـ skills، والذاكرة، والـ sub-agents، والـ handoffs، والـ guardrails، وقواعد الصلاحيات، والـ hooks، والمخرجات المنظَّمة، والـ triggers، و flow اختياري. Agent Forge والـ Agent Author وlousho dev كلها تقرأ هذه الصيغة وتكتبها. تحقّق من كائن spec بـ parseAgentSpecV2() (أو loadSpecV2() لملف)، ثم حوّله إلى agent حي بـ specV2ToAgent(). الـ spec الذي يضبط حقلًا لا يستطيع هذا الـ SDK تشغيله بعد يُرفَض بـ LOUSHO_SPEC_UNSUPPORTED بدل أن يفشل وقت التشغيل. الصيغة الأقدم ما زالت مدعومة - راجع الانتقال من v1 و مرجع v1.

مثال كامل

هذا هو templates/support-triage/spec.yaml، أحد القوالب المرفقة، كما هو تمامًا في المستودع:
أصغر spec يتكوّن من أربعة حقول. هذا المقطع يحلّل واحدًا ويشغّله على الـ provider المدمج mock، فيعمل بدون اتصال وبدون مفتاح API:

الحقول

كل حقول المستوى الأعلى، بترتيب الـ schema. الحقول غير المعروفة تفشل في التحقق مع تلميح “هل تقصد”؛ والحقول المعلَّمة بـ “غير مدعوم بعد” تفشل بـ LOUSHO_SPEC_UNSUPPORTED مع اسم الحقل.

مراجع الـ tools

كل عنصر في tools هو كائن واحد يحمل مفتاح نوع واحد فقط:
  • أسماء { builtin } تأتي من listBuiltinTools() (current_date، day_name، http_request، web_fetch، todo)؛ ويُفحَص options مقابل الـ schema الخاص بالـ tool نفسه.
  • { integration } واحد من github أو jira أو slack أو email؛ ويجب أن تكون بيانات الاعتماد السرية فيه SecretRefs، وليست نصوصًا حرفية أبدًا.
  • كل مرجع يمكن أن يحمل أيضًا id (معرّف العقدة tool:<id> الخاص به؛ والافتراضي هو اسم الـ builtin أو السجل أو الـ hosted، أو الاسم الأساسي للملف)، وapproval ('always' يسأل في كل استدعاء، و'never' لا يسأل أبدًا؛ و'auto' غير مدعوم بعد)، وdeferLoading (يبقى الـ tool مخفيًا حتى يجده tool_search). { hosted } و{ hub } يقبلان id فقط.
  • تثبيت version لمرجع من السجل وapproval: 'auto' يُرفَضان على أنهما غير مدعومين بعد.

الأسرار

السر في الـ spec مرجع، وليس قيمة أبدًا: { env: 'NAME' } يقرأ متغير بيئة، و{ secret: 'name' } يطلبه من مخزن أسرار المضيف. كلاهما يُحَل وقت البناء - { env } يقرأ host.env أولًا، ثم بيئة العملية؛ و{ secret } يستدعي host.resolveSecret (في Agent Forge، هي الأسماء تحت Settings > Secrets). الـ spec ملف في git ويُصدَّر، لذلك لا تصل القيم المحلولة إلى أيٍّ منهما. المرجع الذي لا قيمة له يفشل بـ LOUSHO_SPEC_SECRET_MISSING. تُقبَل SecretRefs في كل مكان توضع فيه بيانات اعتماد: env و headers وoauth.clientSecret في mcpServers، وcredentials لمرجع { integration }، وbearerToken لمرجع { openapi }، وsecret لـ trigger من نوع webhook، وsecrets لـ trigger من نوع channel، وauth لـ subagent بعيد.

الـ triggers

تسرد triggers ما يبدأ run من تلقاء نفسه. لكل عنصر id ثابت (معرّف العقدة trigger:<id> الخاص به) وtype: عمود runsUnder هو ما يعيده listTriggerTypes() لكل نوع. lousho dev يشغّل triggers الـ cron في الـ spec كـ schedules؛ والبقية تحتاج Studio أو الـ Worker.

الـ flows

يحمل flow قيمة AgentFlow - مسار عمل ثابت متعدد الخطوات يتبعه الـ run بدل حلقة agent عادية (راجع Flows). قاعدتان تُبقيان الـ flow المخزَّن قابلًا للتشغيل: كل خطوة تحتاج id صريحًا وفريدًا (معرّف العقدة flow:<id> الخاص بها، والمفتاح الذي تُربَط به الـ spans ونقاط الحفظ)، ولا تُقبَل إلا أشكال الخطوات القابلة للتنفيذ - sequence وparallel وoneOf وforEach وevaluator وllmCall وagent وapproval وtoolCall وsetVariable وreturn وend وthrow. الأشكال الخاصة بالمحرر فقط (step، bestOfAll، tool، uiComponent، condition، loop، وصيغ المحرر من oneOf وforEach وevaluator) تفشل بـ LOUSHO_SPEC_UNSUPPORTED. خطوة agent تسمّي self أو مفتاحًا من subagents.

معرّفات العقد

الـ canvas وفروقات الـ Author والـ telemetry تسمّي كل جزء من الـ spec بمعرّف ثابت: specNodeIds(spec) تحسبها كلها. عندما يمرّر المضيف exporter، تغلّفه specV2ToAgent بحيث يحمل كل span يصدره agent مبني من spec - الـ turns، واستدعاءات الـ tools، وتشغيلات الـ subagents، والـ handoffs، وفحوص الـ guardrails، وانتظار الموافقات وخطوات الـ flow - الخاصية lousho.node.id.

تحويل الـ spec إلى agent

specV2ToAgent(spec, host) تتحقق من الـ spec بـ parseAgentSpecV2، وتحوّل كل قسم، وتبني الـ agent بـ createAgent(). وهي async لأنها تقرأ ملفات تحت host.baseDir وتتصل بخوادم MCP الموجودة في الـ spec. الـ SpecAgentV2 الراجع هو الـ agent مع spec (الـ spec بعد التحقق)، وmcpServers (محلولة، مع توسيع مراجع الأسرار)، و toolNamesByRef؛ وagent.close() يقطع الاتصال بخوادم MCP التي اتصل بها. يوفّر SpecHost ما لا يستطيع الـ spec حمله: compileSpec(spec, host) تتوقف قبل ذلك بخطوة: تعيد { config, toolNamesByRef, mcpServers }، أي خيارات createAgent() فقط، لحالات بناء الـ agent بنفسك. أما specToAgent() من v1 فتبقى منفصلة: فهي متزامنة وتأخذ spec من v1، لا بيانات v2.

في المتصفح: lousho/spec

lousho/spec هو المدخل الآمن للمتصفح: الـ schemas الخاصة بـ v1 و v2، وأنواعها، والدوال المساعدة الخالصة، بدون أي استيراد node:* وبدون تحديد الـ provider، لذلك تستطيع حزمة Vite أو أي حزمة متصفح أخرى استيراده مباشرة. يصدّر agentSpecV2Schema وparseAgentSpecV2 وagentSpecV2JsonSchema و SPEC_FIELD_DESCRIPTIONS، وأنواع AgentSpecV2 والأقسام، وupgradeSpec، ودوال الأسرار ومراجع الـ tools المساعدة (isSecretRef، secretRefSchema، TOOL_REF_KINDS، toolRefSchema)، والكتالوجات (listModels، listGuardrails، listTriggerTypes)، وmemorySpecSchema، وskillRefSchema، وjsonSchemaToStandardSchema، وspecToCode، ودوال معرّفات العقد المساعدة (specNodeIds، nodeIdExporter، isNodeIdExporter، nodeIdIndexOf)، وflowProblems وflowSpecSchema، وtriggerSpecSchema، وagentSpecSchema من v1. الدوال الخاصة بـ Node فقط (specV2ToAgent، compileSpec، loadSpecV2، ومحلّلات الأقسام، وlistBuiltinTools) تبقى في جذر الحزمة.

الانتقال من v1

upgradeSpec(v1) تتحقق من spec بصيغة v1 (برسائل الخطأ الخاصة بـ v1) وتعيد بيانات v2؛ والمدخلات التي هي أصلًا بـ version: 2 تمر بدون تغيير. النتيجة لا يُعاد التحقق منها - مرّرها عبر parseAgentSpecV2() أو استخدم loadSpecV2(path)، التي تقرأ ملف .yaml أو .yml أو .json بأي من الإصدارين وتعيد دائمًا AgentSpecV2 بعد التحقق.
مطابقة الحقول، كما تطبّقها upgradeSpec(): ما تغيّر، باختصار:
  • prompt أصبح instructions، الذي يقبل أيضًا { file: 'instructions.md' }.
  • provider: { type, model } أصبح نصًا واحدًا model: '<type>/<model>'.
  • أسماء الـ tools بصيغة kebab أصبحت مراجع { builtin } بالأسماء بصيغة snake-case التي يراها الـ model: http -> http_request، current-date -> current_date، day-name -> day_name، web-fetch -> web_fetch. الأسماء الأخرى تمر بدون تغيير.
  • مفاتيح policy.* تنتقل إلى المستوى الأعلى: limits وaskQuestion وcompaction وflow تحتفظ بأسمائها؛ وrequiresApproval تصبح permissions، وguardrails تصبح guardrails، وhooks تصبح hooks.
  • الـ guardrails والـ triggers تحصل على معرّفات ثابتة (g1، t1، …) - وهي معرّفات العقد guard:/trigger: الخاصة بها.

القوالب

المجلدات الستة تحت templates/ أمثلة spec كاملة وعاملة؛ وشاشة Templates في Agent Forge تنشئ agent من أي منها.