
مسارات تدقيق مقاومة للعبث لوكلاء الذكاء الاصطناعي: سجلات Runtime Records مترابطة بسلسلة تجزئة (hash-chained)، بدون تبعيات، وقابلة للتحقق من قبل أي شخص.
مسارات تدقيق مقاومة للتلاعب لوكلاء الذكاء الاصطناعي — سجلات وقت التشغيل المتسلسلة هاشيًا، تُعرض كتقرير وقت التشغيل يمكن لعملائك التحقق منه بأنفسهم.
كل إجراء يلتقطه نظام التتبع الخاص بك (استدعاءات الأدوات، استدعاءات النموذج، الوصول إلى البيانات، الموافقات) يصبح سجل وقت تشغيل واحد في سجل إضافي فقط ومتسلسل هاشيًا؛ وتقرير وقت التشغيل هو تلك السلسلة معروضة كصفحة HTML تعيد حساب سلسلة الهاش في متصفح القارئ وتعرض ما تعرضه من السجلات التي تحققت منها (للتحقق الذي لا يعتمد على كود الصفحة نفسها، شغّل halo verify على ملف JSONL). أي طرف يحمل نقطة تحقق من السلسلة يمكنه التحقق من أن السجلات حتى تلك النقطة لم تُعدَّل منذ أخذها، دون الوثوق بمن أنتجها — نقطة التحقق تلك هي الجزء الحامل للثقل: السلسلة وحدها مقاومة للتلاعب ضد الجميع باستثناء الطرف المشغّل للمسجّل (LIMITS.md §1). عندما يسأل فريق الأمن لدى العميل "ماذا فعل وكيلك ببياناتنا؟"، تسلّمهم رابطًا بدلًا من فقرة. مراجعات الأمن تطرح بالفعل أسئلة الذكاء الاصطناعي بجانب قائمة SOC 2 — وبشكل متزايد تأتي تلك الأسئلة من ISO 42001، ومواد حفظ السجلات في قانون الذكاء الاصطناعي الأوروبي، واستبيانات العملاء الخاصة. اليوم لا يزال الضمان المكتوب يمر. الرهان وراء هذا المشروع هو أنه لن يمر طويلًا.
مُشار إليه في Help Net Security (أغسطس 2026).
صيغة السجل مفتوحة ومجانية للتنفيذ. هذه الحزمة هي التنفيذ المرجعي: المسجّل، والمدقّق، وعميل الشاهد، وخادم التقرير.
تستخدم halo-record، أو تفكر في ذلك؟ أخبرني من أنت ولأي غرض → من يستخدم halo-record؟
يُطلب منك وضع مسجّل داخل وكيلك. لا ينبغي أن تأخذ ذلك على الثقة:
pip install halo-record يثبّت حزمة واحدة بالضبط.halo serve --verify-email (يرسل رمزًا لمرة واحدة واسم موضوع التقرير، عبر SMTP من خلال الخادم الذي تهيّئه في $HALO_SMTP_HOST، إلى العنوان الذي يدخله عارض التقرير). جميعها معطّلة ما لم تستدعها؛ لا تخرج أي محتويات سجلات أخرى من بنيتك التحتية.summaries=False) لا يحتفظ بأي ملخص على الإطلاق. التنقيح بأفضل جهد (تعبير نمطي على صيغ الأسرار والبيانات الشخصية الشائعة بالإضافة إلى مُلتقط إنتروبيا شامل): تعامل معه كدفاع في العمق، لا كضمان. حقول النتائج التي توفرها بما يتجاوز summary تُفحص وتُقنَّع بنفس الأنماط، لكن لا تُقطع إلى 200 حرف (LIMITS §13).ما يثبته كل طبقة — التمييز الحامل للثقل في هذا المشروع (LIMITS.md §1): سلسلة تحملها بنفسك تثبت أن السجلات لم تُحرَّر، نسبةً إلى رأس يحمله شخص بالفعل؛ فقط نقاط التحقق المحفوظة خارج المشغّل تثبت أن أيا منها لم يُحذف؛ ولا هاش يثبت أن كل إجراء قد التُقط.
| الادعاء | سلسلة محفوظة ذاتيًا | + نقاط تحقق خارجية | + التقاط موثوق |
|---|---|---|---|
| كشف التحريرات على أثر مُثبَّت | ✔ | ✔ | ✔ |
| كشف إعادة كتابة التاريخ المُلتزم به | — | ✔ | ✔ |
| كشف نقاط التحقق المفقودة/المتأخرة | — | ✔ (وتيرة متفق عليها) | ✔ |
| إثبات تسجيل كل إجراء | — | — | يعتمد على حدود الالتقاط |
شاهد واحدًا قبل أن تثبّت: تقرير وقت تشغيل نموذجي — بيانات خيالية، سلسلة حقيقية، ونصّه البرمجي يعيد حساب سلسلة الهاش للسجلات المضمّنة في متصفحك عند فتحه.
لا حاجة لوكيل. مع uv، لا شيء لتثبيته:
uvx --from halo-record halo demo --serve
أو الطريقة الكلاسيكية:
pip install halo-record
halo demo --serve
إما أن يقوم ببناء بائع وكيل دعم خيالي مع عميلين، ويشهد السلاسل (مع ملف شاهد محلي يقوم مقام شاهد خارج المشغّل — انظر LIMITS.md §1)، ويقدّم تقارير Runtime المُقيّدة الخاصة بهم، ويفتح وحدة تحكم المشغّل في متصفحك. ثم جرّب اختبار العبث: احذف سطرًا من أحد ملفات .jsonl وأعد التحميل. يكتشفه التقرير.
سطر واحد عند الحدود:
from halo_record import trace
agent = trace(run_my_agent, profile="my-agent", log="audit.jsonl") # wraps your entrypoint; records the run boundary to ./audit.jsonl — add record_call() or a framework adapter at each tool boundary to capture individual calls
يُشحن أيضًا غلاف تسهيلي from halo import ... — لكن اسم halo على PyPI يخص حزمة مؤشر طرفية غير ذات صلة، وإذا كانت تلك الحزمة مثبّتة فإنها تفوز عند الاستيراد. أما halo_record فهو غير ملتبس، لذا تستخدمه الأمثلة.
بدون log=، تذهب السجلات إلى ~/.halo/my-agent.jsonl (سلسلة واحدة لكل وكيل). يختم الغلاف حدود التشغيل؛ والأدلة موجودة في السجلات لكل استدعاء. التقطها باستخدام محوّل إطار عمل (المصفوفة أدناه) — أو صراحةً، وهو ما يُظهر أيضًا كيفية ارتباط التفويض:
from halo_record import Recorder, record_call
rec = Recorder("audit.jsonl")
with record_call(rec, "crm.lookup", {"account": "acct-9"}) as call: # one sealed record per tool call
call.result = crm.lookup("acct-9")
with record_call(rec, "payments.refund", {"amount": 120},
parent_id=rec.last_record_id()) as call: # child links to the action that spawned it
call.result = payments.refund(120)
ثم اعرض التقرير:
halo report audit.jsonl -o report.html # one chain -> HTML that re-verifies in the browser
halo serve ./records --port 8721 # all tenants, gated per customer
ترقية دليل خُدِم لأول مرة بواسطة 0.2.45؟ يعيد halo serve قراءة كل منحة سابقة عند بدء التشغيل. تُعزل المنحة على ملف لا تحمل سجلاته أي معرّف موضوع (ملف Recorder عادي مثل agent.jsonl) وتُطبع عند كل بدء تشغيل مع أمر halo grant الذي يعيد إصدارها — انظر LIMITS.md §17, "Serving a directory first served by 0.2.45".
ينتهي البدء السريع عندما تنظر إلى تقرير وقت التشغيل Runtime Report الخاص بوكيلك في المتصفح. إذا حصلت على ملف JSONL وبدون تقرير، فهناك خطأ ما: افتح issue.
إذا تحققت طبقة حماية أو سياسة من الإجراء، يمكن أن يرافق حكمها السجل — كتلة اختيارية تسجّل ما قررته البوابة، مختومة في سلسلة التجزئة مثل كل حقل آخر:
from halo_record import build
build("tool_call", "security", tool="payments.refund",
verification={"status": "allowed", "verifier": "gate/1.2",
"policy_ref": "sha256:1f3a...",
"checked_at": "2026-08-01T12:00:00Z"})
ملاحظة تسمية واحدة: تُصدِّر الحزمة دالة record (المُزيِّن)، والتي تحجب وحدة halo_record.record على كائن الحزمة. استورد من مسار الوحدة مباشرةً عندما تريد محتوياتها الداخلية — from halo_record.record import build — بدلاً من import halo_record.record as record.
والتي تُختَم في السجل على النحو التالي:
"verification": {"status": "allowed", "verifier": "gate/1.2", "policy_ref": "sha256:1f3a...", "checked_at": "2026-08-01T12:00:00Z"}