Claude Memory Tool + Context Editing: شرح
١٤ يوليو ٢٠٢٦

ينسى عميل Claude كل شيء بمجرد انتهاء المحادثة، وتتعثر عمليات التشغيل الطويلة للعملاء (agentic runs) بسبب نتائج الأدوات الخاصة بها. تحل أداة ذاكرة Claude المشكلة الأولى من خلال مخزن يعتمد على الملفات يقرأه ويكتبه Claude بنفسه؛ بينما يحل تعديل السياق (Context Editing) المشكلة الثانية عن طريق مسح نتائج الأدوات القديمة في منتصف التشغيل12.
ملخص
ستقوم بربط @anthropic-ai/sdk الخاص بـ client.beta.messages.toolRunner() بميزتين أساسيتين: أداة ذاكرة Claude (memory_20250818، متاحة بشكل عام، بدون هيدر بيتا) حتى يتمكن Claude من حفظ الملاحظات في دليل /memories الذي يستمر عبر الجلسات، و تعديل السياق (clear_tool_uses_20250919، في مرحلة البيتا) بحيث يقوم العميل الذي يعمل لفترة طويلة بمسح نتائج الأدوات القديمة تلقائيًا بدلاً من تجاوز نافذة السياق الخاصة به12. ستقوم بتشغيل عمليتي Node منفصلتين لإثبات أن الذاكرة تنجو بالفعل في عملية جديدة، وسترى رسالة الخطأ الحقيقية التي تحصل عليها إذا حاولت القراءة خارج /memories. وقت التشغيل: Node 22+، @anthropic-ai/sdk@0.111.0. وقت البناء: 25-30 دقيقة.
ما ستتعلمه
- أي من الأشياء الأربعة التي يطلق عليها الناس "ذاكرة Claude" يغطيها هذا البرنامج التعليمي بالفعل، وأي ثلاثة يتجنبها عمدًا
- كيفية منح العميل دليل
/memoriesمستمر باستخدامBetaLocalFilesystemMemoryToolالجاهز، وكيفية كتابة المعالج الخاص بك للتخزين المخصص - كيفية إثبات بقاء الذاكرة عبر الجلسات من خلال تشغيل عمليتي Node مستقلتين مقابل نفس المخزن
- كيف تعمل استراتيجية
clear_tool_uses_20250919لتعديل السياق، ومعايير التكوين الدقيقة (trigger،keep،clear_at_least،exclude_tools) - الفرق بين تعديل السياق (مرئي للعميل، انتقائي) والضغط (Compaction) (من جانب الخادم، يستبدل السجل بالكامل) — وإهمال حقيقي تكشفه أنواع SDK نفسها والذي يغفله الكثير من التدوينات
- كيفية الجمع بين الذاكرة وتعديل السياق في استدعاء
toolRunner()واحد حتى يحفظ Claude ما يهم قبل مسح نتائج الأدوات القديمة
المتطلبات الأساسية
- Node.js 22 أو أحدث. Node 24 هو الإصدار الحالي Active LTS و Node 22 في Maintenance LTS وقت كتابة هذا التقرير3؛ تم بناء هذا البرنامج التعليمي وتنفيذه باستخدام Node 22.22.3.
@anthropic-ai/sdk@0.111.0— الإصدارlatestالمؤكد في السجل اعتبارًا من 14-07-20264. يتم شحن هذه الحزمة كل بضعة أيام، لذا قم بتثبيت الإصدار الدقيق بدلاً من استخدام^أوlatestفي الإنتاج.- TypeScript 7.0.2 و
tsx@4.23.1(كلاهما إصدارات حالية مؤكدة في السجل)، بالإضافة إلى@types/node@26.1.14. - مفتاح
ANTHROPIC_API_KEYإذا كنت تريد تشغيل حلقة العميل الكاملة مقابل API المباشر. لا يحتاج عرض استمرارية الذاكرة في الخطوة 2 إلى مفتاح API على الإطلاق — فهو يختبر طبقة التخزين مباشرة. يتم احتساب التكاليف للمكالمات المباشرة بأسعار رسائل API القياسية: نموذجclaude-opus-4-8المستخدم في أمثلة هذا البرنامج التعليمي يكلف 5 دولارات لكل مليون توكن مدخلات و 25 دولارًا لكل مليون توكن مخرجات؛ استبدله بـclaude-haiku-4-5(1 دولار / 5 دولارات لكل مليون توكن) لتجربة أرخص أثناء التكرار5. راجع قسم التحقق لمعرفة ما تم تشغيله وما لم يتم تشغيله بالضبط مقابل API المباشر.
عن أي "ذاكرة Claude" نتحدث بالضبط؟
تشحن Anthropic أربعة أشياء مختلفة على الأقل يطلق عليها الناس "ذاكرة Claude"، والخلط بينها هو أحد أكثر الأخطاء شيوعًا في التدوينات حول هذا الموضوع. هذا البرنامج التعليمي يدور حول واحد منها بالضبط:
- أداة ذاكرة رسائل API (
memory_20250818) — أداة من جانب العميل حيث يطلب Claude عمليات ملفات مقابل دليل/memoriesتستضيفه أنت. هذا هو ما يغطيه هذا البرنامج التعليمي. SessionStoreالخاص بـ Claude Agent SDK — حزمة مختلفة (@anthropic-ai/claude-agent-sdk) تعكس النص الخام للجلسة (كل مطالبة، استدعاء أداة، واستجابة، حرفيًا) إلى تخزين خارجي بحيث يمكن استئناف نفس تلك المحادثة لاحقًا — وليس قاعدة معرفية يقوم Claude بتقييمها وإعادة قراءتها بنشاط بالطريقة التي تعمل بها ملفات الذاكرة. تمت تغطيتها في برنامج تعليمي لـ Agent SDK مع تدخل بشري، وليس هنا.CLAUDE.mdالخاص بـ Claude Code — تعليمات على مستوى المشروع لـ Claude Code CLI. ليست ميزة في API على الإطلاق.- مخازن الذاكرة المستضافة للعملاء المدارين و "Dreaming" — منتج العميل المستضاف من Anthropic يقوم بتقييم الذاكرة ذاتيًا من جانب الخادم؛ أنت لا تقوم بتنفيذ طبقة التخزين بنفسك. راجع عملاء Claude المدارون: Dreaming، النتائج، التنسيق لهذا المنتج.
تحافظ الحزمة نفسها على فصل هذه الأشياء أيضًا: تشحن @anthropic-ai/sdk وحدة helpers/beta/memory.ts لأداة الذاكرة (#1) ومورد REST منفصل تمامًا resources/beta/memory-stores.ts لمخازن العملاء المدارين المستضافة (#4) — تم تأكيد ذلك من خلال فحص الحزمة المثبتة مباشرة بدلاً من الافتراض من الوثائق6.
الخطوة 1: إعداد المشروع
mkdir claude-agent-memory && cd claude-agent-memory
npm init -y
npm install @anthropic-ai/sdk@0.111.0
npm install -D TypeScript@7.0.2 tsx@4.23.1 @types/node@26.1.1
npx tsc --init --target ES2022 --module NodeNext --moduleResolution NodeNext --strict
أضف "type": "module" إلى package.json و "noUncheckedIndexedAccess": true إلى compilerOptions في ملف tsconfig.json الناتج. كلاهما مهم: "type": "module" هو ما يسمح لـ tsc بمعاملة await في المستوى الأعلى كأمر صالح بدلاً من الفشل مع الخطأ TS1309: The current file is a CommonJS module and cannot use 'await' at the top level — لقد واجهت هذا الخطأ بالفعل أثناء إعادة فحص عينات التعليمات البرمجية لهذا البرنامج التعليمي وأكدت الإصلاح عن طريق إضافة الحقل وإعادة تشغيل tsc --noEmit، والذي نجح بعد ذلك. مع تفعيل كلا الإعدادين، يتم فحص النوع لكل عينة كود في هذا البرنامج التعليمي بدون أخطاء مع ترك skipLibCheck على قيمته الافتراضية false6. يستحق ذلك التنويه لأنه ليس صحيحًا دائمًا: حزمة Anthropic مختلفة (@anthropic-ai/claude-agent-sdk) تحتاج إلى skipLibCheck: true لتعمل على الإطلاق، بسبب أخطاء نوع داخلية غير ذات صلة في ملفات .d.ts المشحونة الخاصة بها7. حزمة @anthropic-ai/sdk الأساسية التي تستخدمها هنا ليس لديها مثل هذه المشكلة.
الخطوة 2: منح Claude دليل ذاكرة مستمر
أسرع طريقة للحصول على مخزن ذاكرة يعمل هي استخدام تطبيق Anthropic الجاهز لنظام الملفات المحلي، BetaLocalFilesystemMemoryTool. يوجد هذا التطبيق في مسار فرعي مخصص للتصدير وينفذ الأوامر view، و create، و str_replace، و insert، و delete، و rename التي يمكن لأداة ذاكرة Claude إصدارها16:
// session1.ts — simulates the FIRST agent session.
import { BetaLocalFilesystemMemoryTool } from "@anthropic-ai/sdk/tools/memory/node";
async function main() {
const memory = await BetaLocalFilesystemMemoryTool.init("./memory-store");
// Claude's first move is always to check its memory directory.
const listing = await memory.view({ command: "view", path: "/memories" });
console.log("--- view /memories (session 1, before writing) ---");
console.log(listing);
// Claude "discovers" something worth persisting and writes it.
const result = await memory.create({
command: "create",
path: "/memories/project_notes.md",
file_text:
"# Project: invoice-service\n\n" +
"- Postgres pool max is 10 connections in staging.\n" +
"- Retry logic lives in src/retry.ts, NOT in the queue consumer.\n",
});
console.log("--- create /memories/project_notes.md ---");
console.log(result);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
قم بتشغيله:
npx tsx session1.ts
المخرجات الحقيقية من هذا السكربت تحديداً، والمنفذ في بيئة معزولة (sandbox) نظيفة:
--- view /memories (session 1, before writing) ---
Here're the files and directories up to 2 levels deep in /memories, excluding hidden items and node_modules:
4K /memories
--- create /memories/project_notes.md ---
File created successfully at: /memories/project_notes.md
لاحظ أن عرض مجلد /memories فارغ لا يعتبر خطأ — فهو يعيد ترويسة القائمة بالإضافة إلى سطر واحد للمجلد (الفارغ) نفسه، وهو ما يطابق سلوك Anthropic الموثق لاستدعاء view لأول مرة1.
الخطوة 3: إثبات بقاء الذاكرة في عملية جديدة
هذا هو الجزء الذي تتجاهله معظم شروحات "أداة الذاكرة": فهي تعرض لك شكل النموذج ولكنها لا تثبت أبداً الاستمرارية عبر حدود الجلسة. قم بتشغيل سكربت ثانٍ مستقل — عملية Node جديدة، ومثيل جديد لـ BetaLocalFilesystemMemoryTool — موجه إلى نفس المجلد:
// session2.ts — a completely separate process, no shared state with session1.ts
// except the on-disk directory.
import { BetaLocalFilesystemMemoryTool } from "@anthropic-ai/sdk/tools/memory/node";
async function main() {
const memory = await BetaLocalFilesystemMemoryTool.init("./memory-store");
console.log("--- view /memories (session 2, fresh process) ---");
console.log(await memory.view({ command: "view", path: "/memories" }));
console.log("--- view /memories/project_notes.md (session 2) ---");
console.log(
await memory.view({ command: "view", path: "/memories/project_notes.md" }),
);
const edit = await memory.str_replace({
command: "str_replace",
path: "/memories/project_notes.md",
old_str: "Postgres pool max is 10 connections in staging.",
new_str:
"Postgres pool max is 10 connections in staging, 25 in production (confirmed 2026-07-14).",
});
console.log("--- str_replace on project_notes.md ---");
console.log(edit);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
المخرجات الحقيقية:
--- view /memories (session 2, fresh process) ---
Here're the files and directories up to 2 levels deep in /memories, excluding hidden items and node_modules:
4K /memories
142B /memories/project_notes.md
--- view /memories/project_notes.md (session 2) ---
Here's the content of /memories/project_notes.md with line numbers:
1 # Project: invoice-service
2
3 - Postgres pool max is 10 connections in staging.
4 - Retry logic lives in src/retry.ts, NOT in the queue consumer.
5
--- str_replace on project_notes.md ---
The memory file has been edited. Here is the snippet showing the change (with line numbers):
1 # Project: invoice-service
2
3 - Postgres pool max is 10 connections in staging, 25 in production (confirmed 2026-07-14).
4 - Retry logic lives in src/retry.ts, NOT in the queue consumer.
5
حجم مجلد /memories المذكور (4K أعلاه، ولم يتغير قبل وبعد الكتابة) يعكس تخصيص كتل نظام الملفات، وليس حجم البايتات لما بداخله — إعادة تشغيل هذا على نظام تشغيل أو نظام ملفات مختلف قد يظهر رقماً مختلفاً لهذا السطر، بما في ذلك قيم أصغر بكثير في بعض الإعدادات. حجم كل ملف (142B لملف project_notes.md) وكل شيء آخر في هذه الكتل يأتي من طول المحتوى الفعلي ومخرجات الأوامر، لذا فهي مستقرة وستطابق ما تراه.
رأت الجلسة 2 بالضبط ما كتبته الجلسة 1، مع عدم نقل أي تاريخ للمحادثة — فقط الملفات الموجودة على القرص. هذه هي القيمة الكاملة لأداة الذاكرة في كتلة مخرجات واحدة.
أثناء اختبار هذا، تحققت أيضاً من شيء لا تؤكده الوثائق صراحة بأي من الطريقتين: هل يحمي تطبيق نظام الملفات الجاهز من تجاوز المسار (path traversal)، أم أن ذلك "مسؤوليتك" فقط إذا كتبت معالجاً مخصصاً؟ قمت باستدعاء memory.view({ command: "view", path: "/memories/../../etc/passwd" }) ضد نفس المخزن، وأعطى خطأ:
Error: Path /memories/../../etc/passwd would escape /memories directory
لذا فإن BetaLocalFilesystemMemoryTool يحمي من التجاوز بشكل افتراضي. تحذير Anthropic بشأن الاعتبارات الأمنية — "يجب أن يتحقق تطبيقك من كل مسار في كل أمر"1 — موجه للأشخاص الذين يكتبون معالجاً مخصصاً (والذي تغطيه الخطوة 5 أدناه)، وليس ثغرة في التطبيق المرجعي المشحون.
كيف يعرف Claude متى يتحقق من ذاكرته؟
عندما تكون أداة الذاكرة موجودة في مصفوفة tools الخاصة بالطلب، يضيف النموذج تلقائياً تعليمة إلى موجه النظام (system prompt) تخبر Claude بعرض /memories قبل القيام بأي شيء آخر وافتراض أن سياقه قد يتم إعادة ضبطه في أي لحظة1. أنت لا تكتب هذه التعليمة بنفسك — فهي تأتي مع الأداة. وهذا أيضاً هو السبب في أن أداة الذاكرة لا تحتاج إلى ترويسة تجريبية (beta header): فهي ميزة متاحة بشكل عام في نموذج الرسائل، وليست ميزة تجريبية اختيارية1. أما "تحرير السياق" (Context Editing)، الذي سنغطيه لاحقاً، فهو العكس: لا يزال في المرحلة التجريبية ويتطلب ترويسة.
الخطوة 4: تفعيل تحرير السياق حتى لا تستنفد عمليات التشغيل الطويلة نافذة السياق الخاصة بها
العميل (agent) الذي يعمل لفترة طويلة ويقرأ الملفات، ويقوم بعمل grep لقاعدة الكود، ويستدعي البحث في الويب بشكل متكرر، سيملأ في النهاية نافذة السياق الخاصة به بنتائج الأدوات التي عالجها Claude بالفعل ولم يعد بحاجة إليها. استراتيجية clear_tool_uses_20250919 في "تحرير السياق" تمسح أقدم نتائج الأدوات بمجرد تجاوز حد معين، وتستبدلها بنص بديل حتى يعرف Claude أن شيئاً ما قد تمت إزالته2. أفاد تقييم Anthropic الداخلي (اختبار بحث عميل، غير قابل لإعادة الإنتاج بشكل مستقل) أن تحرير السياق وحده أدى إلى تحسين الأداء بنسبة 29% عن خط الأساس، ومع دمجه مع أداة الذاكرة وصل التحسن إلى 39%، وانتهى اختبار بحث ويب مكون من 100 دورة باستهلاك توكنز أقل بنسبة 84% مما كان عليه بدونه8 — وهي أرقام مفيدة من حيث التوجه لتقرير ما إذا كان الأمر يستحق الإعداد، على الرغم من أن عبء العمل الخاص بك سيختلف. قم بتفعيله باستخدام ترويسة تجريبية وكتلة context_management:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const response = await client.beta.messages.create({
model: "claude-opus-4-8",
max_tokens: 4096,
messages: [{ role: "user", content: "Search for recent developments in AI" }],
tools: [{ type: "web_search_20250305", name: "web_search" }],
betas: ["context-management-2025-06-27"],
context_management: {
edits: [{ type: "clear_tool_uses_20250919" }],
},
});
التكوين الافتراضي (التفعيل عند 100,000 توكن إدخال، والاحتفاظ بأحدث 3 استخدامات للأدوات) جيد للبدء السريع، ولكن من الجدير معرفة خيارات التكوين الحقيقية26:
| الخيار | الافتراضي | ماذا يفعل |
|---|---|---|
trigger | 100,000 توكن إدخال | متى يبدأ المسح — يمكن أن يكون {type: "input_tokens", value: N} أو {type: "tool_uses", value: N} |
keep | 3 استخدامات للأدوات | كم عدد أزواج (استخدام الأداة/النتيجة) الحديثة التي تنجو من عملية المسح |
clear_at_least | لا يوجد | الحد الأدنى من التوكنز التي يجب تحريرها لكي تتم عملية المسح أصلاً — يحمي من المسح الذي لا يستحق إبطال ذاكرة التخزين المؤقت للموجه (prompt cache) لأجله |
exclude_tools | لا يوجد | أسماء الأدوات التي لا يتم مسحها أبداً (ضع "memory" هنا حتى تنجو استدعاءات ذاكرة Claude الخاصة) |
clear_tool_inputs | false | مسح معلمات استدعاء الأداة أيضاً، وليس فقط النتائج. النوع الحقيقي يقبل قيمة منطقية (boolean) أو مصفوفة من أسماء أدوات محددة — نصوص الوثائق تذكر فقط الصيغة المنطقية6 |
يعمل تحرير السياق بالكامل من جانب الخادم: يتم تطبيقه قبل وصول الموجه إلى Claude، ويحتفظ العميل الخاص بك بسجل المحادثة الكامل وغير المحرر محلياً. لست بحاجة أبداً لمزامنة حالتك المحلية لتطابق ما تم مسحه2.
ما الفرق بين تحرير السياق والضغط (Compaction)؟
يقوم تحرير السياق (clear_tool_uses_20250919) بحذف نتائج أدوات قديمة محددة بشكل انتقائي مع ترك بقية المحادثة سليمة. أما الضغط (compact_20260112) فهو آلية مختلفة وأكثر شمولاً: فهو يلخص المحادثة بأكملها ويستبدل السجل الكامل بهذا الملخص بمجرد تجاوز حد معين من التوكنز2. توجيهات Anthropic هي أن الضغط من جانب الخادم هو الاستراتيجية الأساسية لمعظم المحادثات الطويلة، بينما تحرير السياق مخصص للسيناريوهات التي تتطلب تحكماً أدق في ما يتم مسحه بالضبط2.
إليك تفصيل يسهل إغفاله إذا كنت تقرأ نصوص التوثيق فقط بدلاً من تعريفات الأنواع الفعلية في SDK: النوع BetaToolRunnerParams يحتوي على حقل compactionControl، ويقول JSDoc الخاص به نصياً:
@deprecated Use server-side compaction instead by passing
`edits: [{ type: 'compact_20260112' }]` in the params passed to `toolRunner()`.
See https://platform.claude.com/docs/en/build-with-claude/compaction
هذا إشعار إيقاف تشغيل (deprecation) حقيقي تم شحنه في الأنواع المجمعة الخاصة بـ @anthropic-ai/sdk@0.111.0، وليس شيئاً مستنتجاً من سجل التغييرات6. إذا وجدت درساً تعليمياً (بما في ذلك الدروس القديمة) يعرض compactionControl كطريقة لتمكين الضغط (compaction)، فهو يعرض لك مساراً مهجوراً — المسار الحالي هو تعديل compact_20260112 داخل context_management، وهي نفس المصفوفة التي يتواجد فيها clear_tool_uses_20250919.
الخطوة 5: دمج الذاكرة وتحرير السياق في عميل واحد
هذا هو النمط الذي توصي به Anthropic للعملاء الذين يعملون لفترات طويلة حقاً: يحافظ "تحرير السياق" (Context Editing) على صغر حجم السياق النشط تلقائياً، وتحافظ الذاكرة على أي شيء يجب أن ينجو من عملية المسح، لأن API يرسل لـ Claude تحذيراً تلقائياً لحفظ المعلومات المهمة في الذاكرة قبل تجاوز الحد المسموح به12. قم بربط كليهما في client.beta.messages.toolRunner()، وهي حلقة العميل المدمجة في SDK:
// full-agent-example.ts
import Anthropic from "@anthropic-ai/sdk";
import { betaMemoryTool } from "@anthropic-ai/sdk/helpers/beta/memory";
import { BetaLocalFilesystemMemoryTool } from "@anthropic-ai/sdk/tools/memory/node";
async function main() {
const client = new Anthropic();
const memory = await BetaLocalFilesystemMemoryTool.init("./memory-store");
const runner = client.beta.messages.toolRunner({
model: "claude-opus-4-8",
max_tokens: 4096,
messages: [
{
role: "user",
content:
"Review the invoice-service repo and note anything future sessions should know.",
},
],
tools: [betaMemoryTool(memory)],
betas: ["context-management-2025-06-27"],
context_management: {
edits: [
{
type: "clear_tool_uses_20250919",
trigger: { type: "input_tokens", value: 30000 },
keep: { type: "tool_uses", value: 3 },
clear_at_least: { type: "input_tokens", value: 5000 },
exclude_tools: ["memory"],
},
],
},
});
const finalMessage = await runner.runUntilDone();
console.log(finalMessage.content);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
لاحظ betaMemoryTool(memory) — أنت تمرر مثيل BetaLocalFilesystemMemoryTool الخاص بك مباشرة ككائن معالجات (handlers)؛ لا يهتم betaMemoryTool() ما إذا كان مدعوماً بنظام الملفات المحلي أو أي شيء آخر، لأن كلاهما يستوفي نفس واجهة MemoryToolHandlers من الناحية الهيكلية. هذا هو السبب أيضاً في أهمية exclude_tools: ["memory"] هنا: بدونها، يمكن أن يتم مسح كتابات الذاكرة الخاصة بـ Claude بواسطة نفس عملية المسح التي من المفترض أن تحمي المعلومات عبر الذاكرة في المقام الأول.
إذا كنت بحاجة إلى ذاكرة مدعومة بشيء آخر غير نظام الملفات المحلي — S3، Postgres، بادئة واحدة لكل عميل — فاكتب المعالج الخاص بك مقابل نفس الواجهة بدلاً من إنشاء فئة فرعية (subclassing) من أي شيء:
// custom-handler-pattern.ts — one memory store per customer, backed by
// whatever storage you already run (S3 shown as comments; swap in real calls).
import { betaMemoryTool, type MemoryToolHandlers } from "@anthropic-ai/sdk/helpers/beta/memory";
function scopedMemoryHandlers(customerId: string): MemoryToolHandlers {
const keyFor = (path: string) => `customers/${customerId${path`;
return {
view: async (cmd) => {
// const obj = await s3.getObject({ Key: keyFor(cmd.path) });
return `Here're the files and directories up to 2 levels deep in ${cmd, excluding hidden items and node_modules:\n0B\t${cmd`;
},
create: async (cmd) => {
// await s3.putObject({ Key: keyFor(cmd.path), Body: cmd.file_text });
return `File created successfully at: ${cmd`;
},
str_replace: async () => `The memory file has been edited.`,
insert: async (cmd) => `The file ${cmd has been edited.`,
delete: async (cmd) => `Successfully deleted ${cmd`,
rename: async (cmd) => `Successfully renamed ${cmd to ${cmd`,
};
}
export function memoryToolFor(customerId: string) {
return betaMemoryTool(scopedMemoryHandlers(customerId));
}
بناء معالج مخصص مثل هذا يضع مسؤولية عزل المستأجرين المتعددين عليك: قم بتحديد نطاق كل مفتاح حسب معرف العميل بالطريقة التي يفعلها scopedMemoryHandlers() أعلاه، ولا تسمح لقراءات أو كتابات ذاكرة عميل واحد بلمس بيانات عميل آخر. تغطي إرشادات Anthropic الخاصة للتنفيذ المرجعي الحالات العامة التي لا تزال تنطبق هنا — قم بتجريد البيانات الحساسة قبل الكتابة، وحدد حجم نمو أي ملف أو دليل، وقم بإنهاء صلاحية ملفات الذاكرة التي لم يقرأها أحد منذ فترة بشكل دوري1.
التحقق
ما تم تنفيذه بالفعل، في بيئة الاختبار هذه، مقابل الحزمة المثبتة الحقيقية: تم تشغيل session1.ts و session2.ts من الخطوتين 2 و 3 بشكل حقيقي باستخدام npx tsx، في استدعاءين منفصلين للعملية مقابل نفس دليل ./memory-store — مخرجات وحدة التحكم المعروضة في تلك الخطوات منسوخة نصياً من تلك العمليات، وليست مخترعة. كما تم تنفيذ اختبار تجاوز المسار (path-traversal) في الخطوة 3 فعلياً وأدى بالفعل إلى الخطأ الموضح. تم بعد ذلك إعادة استخراج كل كتلة برمجية في هذا الدرس التعليمي نصياً من ملف markdown النهائي (وليس من الملفات الأصلية) وإعادة فحصها كخطوة نهائية، بنفس الطريقة التي تمت بها إعادة تشغيل نصوص الجلسة لتأكيد المخرجات. كشف هذا الاستخراج عن خطأ حقيقي واحد: تستخدم قصاصة "تحرير السياق" المستقلة في الخطوة 4 مستوى علوي من await وفشلت في التجميع مع الخطأ TS1309 حتى تمت إضافة "type": "module" إلى package.json — وهو ما تم دمجه الآن في الخطوة 1 أعلاه. مع هذا الإصلاح، تخضع جميع كتل TypeScript الخمس المستخرجة لفحص الأنواع معاً باستخدام tsc --strict --noUncheckedIndexedAccess مقابل حزمة @anthropic-ai/sdk@0.111.0 الحقيقية المثبتة عبر npm — تجميع نظيف، صفر أخطاء، ولا حاجة لحل skipLibCheck. كشفت إعادة تشغيل نصوص الجلسة للمرة الثانية، في بيئة اختبار نظيفة ومنفصلة، عن شيء آخر يستحق المعرفة: الحجم المعلن لدليل /memories عاد كـ 4K بدلاً من 64B/96B في التشغيل الأول. هذا نتاج تخصيص كتل نظام الملفات (filesystem-block-allocation)، وليس خطأً — لذا فإن الأرقام الموضحة في الخطوتين 2 و 3 تعكس الآن ذلك التشغيل الثاني المعاد إنتاجه بشكل مستقل، وكل شيء آخر في كتل المخرجات تلك (محتويات الملفات، عدد البايتات للملفات الفعلية، رسائل النجاح، خطأ التجاوز) تطابق بايت ببايت عبر كلا التشغيلين.
ما لم يتم تنفيذه: استدعاءات client.beta.messages.create() و toolRunner() الحية في الخطوتين 4 و 5، والتي تتطلب مفتاح ANTHROPIC_API_KEY مدفوعاً. لا يحتوي خط أنابيب الكتابة الآلي هذا على مفتاح API مهيأ. إذا كان لديك واحد، فقم بتشغيل:
export ANTHROPIC_API_KEY=sk-ant-...
npx tsx full-agent-example.ts
يجب أن ترى Claude يكتب ملفاً واحداً على الأقل تحت ./memory-store/memories/ قبل الانتهاء، و — إذا كانت المحادثة طويلة بما يكفي لتجاوز محفز الـ 30,000 توكن — مصفوفة context_management.applied_edits في الاستجابة تعرض أعداد cleared_tool_uses و cleared_input_tokens2.
الأخطاء الشائعة
view على /memories يعيد خطأً بدلاً من قائمة فارغة. إذا كتبت المعالج الخاص بك بدلاً من استخدام BetaLocalFilesystemMemoryTool، فتأكد من أن تنفيذ view الخاص بك يعامل جذر الذاكرة المفقود/الفارغ كدليل فارغ صالح، وليس كخطأ "المسار غير موجود" — فقط BetaLocalFilesystemMemoryTool ينشئ الجذر تلقائياً قبل استدعاء Claude الأول1.
تحرير السياق (Context Editing) لا يفعل شيئاً بصمت. تحقق من أن betas: ["context-management-2025-06-27"] موجود بالفعل في الطلب — إنه ترويسة تجريبية (beta header)، وليس ميزة مفعلة افتراضياً، على عكس أداة الذاكرة2.
يتم مسح كتابات الذاكرة قبل أن يتمكن Claude من استخدامها مرة أخرى. أضف "memory" إلى exclude_tools في تكوين clear_tool_uses_20250919 الخاص بك. بدون ذلك، يمكن لعملية المسح أن تزيل كتل tool_result التي توثق ما حفظه Claude للتو2.
tsc --strict يفشل بسبب خطأ في مساحة الاسم NodeJS. هذا ليس خطأً في @anthropic-ai/sdk — بل يعني أن @types/node غير مثبت. قم بتشغيل npm install -D @types/node@26.1.1 وسيتم حله؛ تم التحقق من ذلك مباشرة في بيئة الاختبار هذه.
درس تعليمي أو منشور مدونة قديم يعرض compactionControl وهو لا يعمل. هذا الحقل مهجور في SDK الحالي. استخدم context_management: { edits: [{ type: "compact_20260112" }] } ممرراً إلى toolRunner() بدلاً من ذلك6.
الاعتبارات الأمنية
كل ما تفعله أداة ذاكرة Claude يتم تشغيله من خلال كود تكتبه وتستضيفه بنفسك — Claude يرسل فقط طلبات لعمليات الملفات؛ وتطبيقك هو من ينفذها1. هناك ثلاثة أشياء تستحق البناء منذ البداية، مباشرة من توجيهات Anthropic نفسها: تجريد أو رفض محاولات كتابة بيانات حساسة بوضوح (مفاتيح API، بيانات الاعتماد) في ملفات الذاكرة حتى لو كان Claude يرفض عادةً كتابتها دون طلب؛ تحديد حجم ملف الذاكرة أو الدليل، والسماح لـ Claude بالتنقل عبر الملفات الطويلة باستخدام view_range بدلاً من عرض كل شيء مرة واحدة؛ وإنهاء صلاحية ملفات الذاكرة التي لم يقم أحد بالوصول إليها لفترة طويلة بشكل دوري1. إذا كنت تكتب معالجاً مخصصاً بدلاً من استخدام BetaLocalFilesystemMemoryTool، فإن الحماية من تجاوز المسار (path traversal) تقع على عاتقك بالكامل — تحقق من أن كل مسار يتم حله داخل الجذر المقصود قبل لمس التخزين الحقيقي.
الخطوات التالية ومزيد من القراءة
يعتمد هذا البرنامج التعليمي مباشرة على client.beta.messages.toolRunner()، والذي يغلف نفس حلقة tool_use/tool_result التي تمت تغطيتها من المبادئ الأساسية في البرنامج التعليمي لحلقة Claude لاستخدام الأدوات الوكيلية — وهو يستحق القراءة إذا كنت تريد فهم ما يفعله toolRunner() خلف الكواليس، أو إذا كنت بحاجة إلى بناء الحلقة يدوياً للغة لا تحتوي على مساعد تشغيل. إذا كان وكيلك يحتاج إلى موافقة بشرية للإجراءات الخطيرة بالإضافة إلى تذكر الأشياء عبر الجلسات، فإن البرنامج التعليمي لـ Claude Agent SDK مع وجود بشري في الحلقة يغطي استدعاءات canUseTool وخطافات PreToolUse فوق حزمة Agent SDK (المختلفة). وإذا لم تكن استضافة تخزين الذاكرة الخاصة بك شيئاً تريد إدارته تشغيلياً، فإن وكلاء Claude المدارون: الأحلام، النتائج، والتنسيق يغطي بديل Anthropic المستضاف، حيث يتم تنظيم الذاكرة من جانب الخادم بدلاً من المعالج الخاص بك.
بالنسبة لمبادئ التصميم الأساسية وراء متى تلجأ إلى الذاكرة مقابل تحرير السياق مقابل الضغط، فإن المقال الهندسي الخاص بـ Anthropic حول هندسة السياق الفعالة هو المصدر الأساسي الذي تشير إليه اقتباسات هذا البرنامج التعليمي9.
Footnotes
-
Anthropic, "Memory tool" — https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool (GA status/no beta header, command reference, empty-directory view behavior, prompting guidance, security considerations, production patterns; fetched 2026-07-14) ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12
-
Anthropic, "Context editing" — https://platform.claude.com/docs/en/build-with-claude/context-editing (beta header,
clear_tool_uses_20250919config options and defaults, server-side execution model, compaction comparison; fetched 2026-07-14) ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 -
Node.js release data — https://endoflife.date/API/nodejs.json (structured API, fetched directly 2026-07-14): Node 24 active-support window 2025-10-28 to 2026-10-20 (Active LTS as of this writing), then maintenance until EOL 2028-04-30; Node 22 active-support ended 2025-10-21 (Maintenance LTS as of this writing), EOL 2027-04-30; Node 26 latest release 26.5.0, not yet LTS-promoted (LTS conversion scheduled 2026-10-28), EOL 2029-04-30 ↩
-
npm registry — https://registry.npmjs.org/@anthropic-ai/sdk/latest (version 0.111.0, published 2026-07-10T17:14:13.049Z); https://registry.npmjs.org/TypeScript/latest (7.0.2); https://registry.npmjs.org/tsx/latest (4.23.1); https://registry.npmjs.org/@types/node/latest (26.1.1) — all fetched directly from the registry API, not a search summary, 2026-07-14 ↩ ↩2
-
Claude Platform pricing — https://platform.claude.com/docs/en/about-claude/pricing (Claude Opus 4.8: $5/MTok input, $25/MTok output, flat pricing with no introductory-rate split; fetched 2026-07-14) ↩
-
تعريفات الأنواع المجمعة لـ
@anthropic-ai/sdk@0.111.0—helpers/beta/memory.d.ts،tools/memory/node.d.ts،lib/tools/BetaToolRunner.d.ts،resources/beta/messages/messages.d.ts— تم تثبيتها من npm وفحصها مباشرة، 14-07-2026 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 -
تعريفات الأنواع المجمعة لـ
@anthropic-ai/claude-agent-sdk@0.3.150، كما هو موثق في قسم التحقق الخاص بالدرس التعليمي "الإنسان في الحلقة" بتاريخ 13-07-2026 — وهي حزمة مختلفة عن تلك المستخدمة في هذا الدرس التعليمي ↩ -
Anthropic، "إدارة السياق على منصة مطوري Claude" — https://claude.com/blog/context-management (إعلان بتاريخ 29 سبتمبر 2025؛ تحسن في الأداء بنسبة 39% مجمعة / 29% لتحرير السياق وحده وتقليل التوكنز بنسبة 84% في تقييم من 100 دورة — مجموعة تقييم البحث الوكيل الداخلية الخاصة بـ Anthropic، وليست قابلة لإعادة الإنتاج بشكل مستقل؛ تم جلبها في 14-07-2026) ↩
-
Anthropic Engineering، "هندسة السياق الفعالة لوكلاء الذكاء الاصطناعي" — https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents (مرتبط من صفحة وثائق أداة الذاكرة كمرجع أوسع لمبادئ التصميم؛ تم جلبها في 14-07-2026) ↩


