ai-ml

امنح عميل AI ذاكرة طويلة المدى باستخدام pgvector (2026)

١٧ يوليو ٢٠٢٦

Give an AI Agent Long-Term Memory with pgvector (2026)

نافذة السياق (context window) الخاصة بعميل الذكاء الاصطناعي يتم إعادة ضبطها في كل جلسة — لذا فهو لا يملك أي فكرة عن هويتك في المرة الثانية التي تتحدث فيها معه. يقوم هذا البرنامج التعليمي ببناء عميل TypeScript صغير يحل هذه المشكلة باستخدام Postgres وإضافة pgvector: حيث يقرر Claude ما الذي يستحق التذكر، وتقوم أداة remember_fact بتخزينه كـ embedding، بينما يقوم استعلام cosine-similarity باسترجاعه في كل دورة لاحقة — بما في ذلك بعد إيقاف العملية بالكامل وإعادة تشغيلها1.

ملخص

ستقوم ببناء عميل CLI يربط Claude (claude-sonnet-5) بمخزن ذاكرة Postgres 18 + pgvector2. تتيح أداة remember_fact لـ Claude تحديد متى يكون شيء ما عن المستخدم يستحق الحفظ؛ وقبل كل رد، يقوم التطبيق بتحويل رسالة المستخدم إلى embedding باستخدام text-embedding-3-small من OpenAI3 ويسحب الذكريات الأكثر تطابقاً باستخدام عامل مسافة جيب التمام (cosine-distance) <=> الخاص بـ pgvector4، ثم يحقنها في موجه النظام (system prompt). أوقف العملية، ابدأها مرة أخرى، وسيظل العميل يعرف اسمك. بيئة التشغيل: Node.js 24 LTS5، @anthropic-ai/sdk@0.112.1، pg@8.22.0. وقت البناء: 25-30 دقيقة.

ما ستتعلمه

  • كيفية تشغيل Postgres مع إضافة pgvector مثبتة مسبقاً باستخدام صورة Docker الرسمية pgvector/pgvector
  • كيفية تخزين الـ embeddings في عمود vector والاستعلام عنها باستخدام عامل مسافة جيب التمام <=> في pgvector
  • كيفية إعطاء Claude أداة remember_fact لكي يقرر النموذج ما الذي يستحق الحفظ، بدلاً من تحويل كل رسالة إلى embedding بشكل أعمى
  • كيفية استرجاع الذكريات ذات الصلة قبل كل دورة وحقنها في موجه النظام
  • كيفية إثبات أن الذاكرة صمدت بعد إعادة التشغيل عن طريق إنهاء عملية Node وبدء عملية جديدة
  • ماذا تفعل عندما لا يعيد الاسترجاع أي شيء، أو يعيد ذكريات خاطئة

المتطلبات الأساسية

  • Docker (أي إصدار حديث) — يُستخدم لتشغيل pgvector/pgvector:pg18، وهي صورة Postgres 18 الرسمية مع pgvector مثبتة مسبقاً6
  • Node.js 24 LTS أو أحدث — صدر في 2025-05-06، وفي مرحلة Active LTS منذ 2025-10-28 (ينتقل إلى Maintenance LTS في 2026-10-20)، ومدعوم حتى 2028-04-305
  • مفتاح ANTHROPIC_API_KEY (لـ Claude) ومفتاح OPENAI_API_KEY (للـ embeddings فقط — لأن Anthropic لا توفر نقطة نهاية للـ embeddings، لذا فإن text-embedding-3-small يسد هذه الفجوة)7
  • إلمام بأساسيات SQL؛ لن تكتب أي أدوات تهجير (migrations)، فقط استعلامات CREATE TABLE خام واستعلامات ذات معاملات (parameterized queries)

الخطوة 1: تشغيل Postgres مع pgvector

تجاوز عملية تجميع الإضافة بنفسك — ينشر مشروع pgvector صورة Docker وهي صورة Postgres القياسية مع pgvector مدمجة بالفعل6:

Docker run -d \
  --name agent-memory-db \
  -e POSTGRES_PASSWORD=postgres \
  -e POSTGRES_DB=agent_memory \
  -p 5432:5432 \
  pgvector/pgvector:pg18

pg18 تشير إلى Postgres 18 (حالياً في إصدار التصحيح 18.4) مع أحدث تصحيح لـ pgvector مثبت مسبقاً — يتتبع الوسم (tag) وتيرة إصدارات pgvector تلقائياً، لذا ستحصل على أي تصحيح متاح عند سحب الصورة، وليس بالضرورة ما كان متاحاً عند كتابة هذا الدليل. إصدار 0.8.2 (2026-02-25) أصلح خطأ buffer-overflow في عمليات بناء فهرس HNSW المتوازية28؛ بعد الخطوة 2، سيخبرك الاستعلام SELECT extversion FROM pg_extension WHERE extname = 'vector'; بالضبط عن التصحيح الذي حصلت عليه. تأكد من أن الحاوية تعمل:

Docker exec agent-memory-db pg_isready -U postgres
# /var/run/postgresql:5432 - accepting connections

الخطوة 2: إنشاء جدول الذاكرة

قم بتفعيل الإضافة وإنشاء جدول واحد: معرف المورد (resource ID) لمن تعود هذه الذاكرة، والحقيقة كنص، والـ embedding الخاص بها.

-- schema.sql
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE IF NOT EXISTS agent_memories (
  id bigserial PRIMARY KEY,
  resource_id text NOT NULL,
  content text NOT NULL,
  embedding vector(1536) NOT NULL,
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS agent_memories_embedding_idx
  ON agent_memories USING hnsw (embedding vector_cosine_ops);

vector(1536) يتطابق مع حجم المخرجات الافتراضي لـ text-embedding-3-small3. فهرس hnsw مع vector_cosine_ops هو ما يجعل <=> سريعاً بمجرد أن يكون لديك أكثر من بضع مئات من الصفوف — حيث يقوم pgvector بالبحث الدقيق افتراضياً ولا يتحول إلى البحث التقريبي إلا عند وجود فهرس كهذا4. قم بتطبيقه:

Docker exec -i agent-memory-db psql -U postgres -d agent_memory < schema.sql

الخطوة 3: إعداد مشروع TypeScript

mkdir agent-memory && cd agent-memory
npm init -y
npm install @anthropic-ai/sdk@0.112.1 openai@6.48.0 pg@8.22.0 pgvector@0.3.0
npm install -D TypeScript@6.0.3 @types/node@24.13.3 @types/pg@8.20.0 tsx@4.23.1

pgvector هنا هي حزمة npm (غير مرتبطة في رقم الإصدار بإضافة Postgres) التي تحول مصفوفات الأرقام في JS إلى تنسيق literal الخاص بـ Postgres vector وتقوم بتسجيل النوع على عميل pg9. أضف "type": "module" إلى package.json، ثم أنشئ tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "noEmit": true,
    "allowImportingTsExtensions": true
  },
  "include": ["*.ts"]
}

خيار allowImportingTsExtensions مهم: الملفات أدناه تستورد بعضها البعض كـ ./db.ts، وليس ./db.js، وهو ما يعمل فقط عند تفعيل هذا الخيار (ويتطلب noEmit: true، وهو ما تريده على أي حال لأن tsx يتولى التنفيذ).

الخطوة 4: الاتصال بـ Postgres وكتابة وظائف الذاكرة

يقوم ملف db.ts بفتح مجمع اتصالات (connection pool) وتسجيل أنواع pgvector في كل اتصال جديد:

// db.ts
import pg from "pg";
import pgvector from "pgvector/pg";

const { Pool } = pg;

export const pool = new Pool({
  connectionString: process.env.DATABASE_URL ?? "postgres://postgres:postgres@localhost:5432/agent_memory",
  onConnect: async (client) => {
    await pgvector.registerTypes(client);
  },
});

يقوم ملف memory.ts بالعمل الفعلي: تحويل النص إلى embedding باستخدام OpenAI، وتخزينه، واسترجاع أقرب التطابقات لمستخدم معين.

// memory.ts
import OpenAI from "openai";
import pgvector from "pgvector/pg";
import { pool } from "./db.ts";

const openai = new OpenAI();

export async function embed(text: string): Promise<number[]> {
  const response = await openai.embeddings.create({
    model: "text-embedding-3-small",
    input: text,
  });
  const vector = response.data[0]?.embedding;
  if (!vector) throw new Error("OpenAI returned no embedding");
  return vector;
}

export async function rememberFact(resourceId: string, fact: string): Promise<void> {
  const embedding = await embed(fact);
  await pool.query(
    "INSERT INTO agent_memories (resource_id, content, embedding) VALUES ($1, $2, $3)",
    [resourceId, fact, pgvector.toSql(embedding)],
  );
}

export interface RecalledMemory {
  content: string;
  distance: number;
}

export async function recallMemories(
  resourceId: string,
  query: string,
  limit = 3,
): Promise<RecalledMemory[]> {
  const embedding = await embed(query);
  const result = await pool.query<{ content: string; distance: number }>(
    `SELECT content, embedding <=> $2 AS distance
       FROM agent_memories
      WHERE resource_id = $1
      ORDER BY embedding <=> $2
      LIMIT $3`,
    [resourceId, pgvector.toSql(embedding), limit],
  );
  return result.rows;
}

تقوم pgvector.toSql() بتحويل مصفوفة JS إلى السلسلة النصية التي يتوقعها Postgres لـ literal من نوع vector — فتتحول [1, 2, 3] إلى "[1,2,3]"، بما يتطابق مع أمثلة SQL الخام في وثائق pgvector نفسها9. <=> تعني مسافة جيب التمام، لذا فإن القيمة الأصغر تعني تشابهاً أكبر؛ و ORDER BY ... ASC تضع بالفعل أقرب التطابقات أولاً، لذا لا حاجة لتحويلها إلى "تشابه" (similarity)4.

الخطوة 5: دع Claude يقرر ما الذي يتذكره

هذا هو الجزء الذي يميز ميزة الذاكرة الحقيقية عن مجرد تحويل كل رسالة إلى embedding دون تمييز: امنح Claude أداة، ودع النموذج يستدعيها فقط عندما يكون هناك شيء يستحق الحفظ فعلاً.

حلقة while (response.stop_reason === "tool_use") هي الدورة القياسية بين العميل والأداة: حيث يعيد Claude كتلة tool_use بدلاً من النص، ويقوم الكود الخاص بك بتشغيل الأداة وإضافة كتلة tool_result، ثم تقوم باستدعاء الـ API مرة أخرى حتى يرد Claude بنص10. عملية الاسترجاع (Recall) نفسها ليست استدعاءً لأداة — فهي تعمل بشكل حتمي قبل أن يرى Claude الرسالة، مما يجعل الحالة الشائعة تقتصر على دورة API واحدة.

خيار tool_choice: { type: "auto", disable_parallel_tool_use: true } أهم مما يبدو: فبشكل افتراضي، يمكن لـ Claude إعادة كتل tool_use متعددة في رد واحد، وهذه الحلقة تقرأ فقط الكتلة الأولى باستخدام .find().

بدون تعطيل الاستدعاءات المتوازية، فإن رسالة مثل "اسمي سام وأنا مشترك في خطة Pro" — وهما حقيقتان مستقلتان — قد تجعل Claude يشغل remember_fact مرتين في دورة واحدة؛ ولن يحصل الاستدعاء الثاني أبداً على tool_result مطابق، وسيفشل استدعاء الـ API التالي لأن كل كتلة tool_use تتطلب نتيجة واحدة11. تحديد الأمر باستدعاء أداة واحدة لكل دورة يعني أن حقيقتي سام سيتم تخزينهما عبر تكرارين للحلقة بدلاً من ذلك، وهو بالضبط ما يظهره قسم التحقق أدناه.

الخطوة 6: ربط حلقة CLI

// run.ts
import { createInterface } from "node:readline/promises";
import { stdin, stdout } from "node:process";
import { runTurn } from "./agent.ts";
import { pool } from "./db.ts";

const RESOURCE_ID = "demo-user";

async function main() {
  const rl = createInterface({ input: stdin, output: stdout });
  console.log("Agent memory demo. Type a message, or 'exit' to quit.\n");

  while (true) {
    const input = await rl.question("you> ");
    if (input.trim().toLowerCase() === "exit") break;
    const reply = await runTurn(RESOURCE_ID, input);
    console.log(`agent> ${reply}\n`);
  }

  rl.close();
  await pool.end();
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});

تم تحديد RESOURCE_ID بشكل ثابت لإبقاء العرض التوضيحي مركزاً على الاستمرارية وليس المصادقة — في تطبيق حقيقي، سيأتي هذا من نظام الجلسات/المستخدمين الخاص بك، وسيكون كل صف ذاكرة واستعلام استرجاع مرتبطاً به تماماً بهذا الشكل.

التحقق

ما تم تشغيله فعلياً: تم تثبيت جميع الملفات الأربعة (db.ts، memory.ts، agent.ts، run.ts، بإجمالي 157 سطراً) مقابل حزم npm الحقيقية من الخطوة 3 وتم فحص الأنواع باستخدام npx tsc --noEmit — دون أي أخطاء، مما يؤكد استخدام أنواع Tool و MessageParam و ToolUseBlock من @anthropic-ai/sdk@0.112.1 وواجهات برمجة تطبيقات pg/pgvector بشكل صحيح. تم تنفيذ pgvector.toSql() مباشرة: حيث تعيد toSql([1, 2, 3]) القيمة "[1,2,3]"، وهو ما يطابق التنسيق الحرفي الذي تستخدمه أمثلة SQL الخاصة بـ pgvector9. كما تم فحص بناء جملة schema.sql سطراً بسطر مقابل ملف README الرسمي لـ pgvector4.

ما لم يتم تشغيله بالكامل: دورة حية مقابل Postgres حقيقي وواجهات برمجة تطبيقات Claude/OpenAI حقيقية — فهذه البيئة التجريبية لا تحتوي على Docker ولا مفتاح API مدفوع. إذا كان لديك كلاهما، فإليك ما يجب توقعه. التشغيل الأول:

you> My name is Sam and I'm on the Pro plan.
agent> Nice to meet you, Sam! I've made a note that you're on the Pro plan —
let me know if you need help with anything.
you> exit

أغلق العملية (Ctrl+C أو أغلق الطرفية فقط)، ثم ابدأها مرة أخرى — عملية Node جديدة، حالة جديدة في الذاكرة، ونفس حاوية Postgres:

you> What's my name, and what plan am I on?
agent> Your name is Sam, and you're on the Pro plan.
you> exit

تأكد من ذلك مباشرة في قاعدة البيانات، بشكل مستقل عن العميل:

Docker exec agent-memory-db psql -U postgres -d agent_memory \
  -c "SELECT resource_id, content, created_at FROM agent_memories ORDER BY created_at;"
 resource_id |            content             |          created_at
-------------+---------------------------------+-------------------------------
 demo-user   | The user's name is Sam.         | 2026-07-17 09:14:02.113+00
 demo-user   | The user is on the Pro plan.    | 2026-07-17 09:14:02.897+00

صفان، استدعاءان منفصلان لـ remember_fact — قام Claude بتقسيم الرسالة إلى حقيقتين ذريتين بدلاً من تخزين الجملة كاملة حرفياً، وهو سلوك نموذجي لأن وصف الأداة يطلب "حقيقة واحدة مستقلة بذاتها".

استكشاف الأخطاء وإصلاحها

relation "agent_memories" does not exist. لم يتم تطبيق schema.sql أبداً، أو تم تطبيقه على قاعدة بيانات مختلفة عن تلك الموجودة في سلسلة الاتصال الخاصة بك. أعد تشغيل أمر Docker exec ... psql من الخطوة 2 وتأكد من أن POSTGRES_DB=agent_memory يطابق DATABASE_URL.

type "vector" does not exist. لم يتم تشغيل CREATE EXTENSION IF NOT EXISTS vector; — عادةً ما يكون السبب هو وصول schema.sql إلى قاعدة بيانات خاطئة، أو أن الحاوية بدأت من وحدة تخزين قديمة تسبق تثبيت الإضافة. اتصل باستخدام psql وقم بتشغيل هذا السطر يدوياً للتأكد.

عملية الاسترجاع (Recall) تعيد دائماً مصفوفة فارغة. تأكد من أن resource_id متطابق تماماً بين استدعاء rememberFact واستدعاء recallMemories — فاستخدام معرف يتم إنشاؤه ديناميكياً (مثل UUID جديد لكل عملية بدلاً من معرف ثابت) يعني أن كل استعلام يبحث عن مستخدم ليس لديه صفوف بعد. هذا هو الخطأ الأكثر شيوعاً في أنظمة الذاكرة الصحيحة تقنياً.

عملية الاسترجاع تعيد ذكريات، ولكن ليست الأكثر صلة. مع وجود عدد قليل من الصفوف، لا ينبغي أن يحدث هذا — حيث يقوم pgvector ببحث دقيق حتى يبدأ فهرس hnsw في العمل فعلياً، وعند هذه النقطة تصبح النتائج تقريبية حسب التصميم4. إذا كانت جودة الاسترجاع أهم من السرعة عند التوسع، ارفع قيمة hnsw.ef_search فوق القيمة الافتراضية 40: SET hnsw.ef_search = 100;4.

Claude لا يستدعي أبداً remember_fact، حتى بالنسبة للحقائق التي تتوقع تخزينها. حقل description الخاص بالأداة هو الذي يوجه العملية — يقرر Claude ما إذا كان سيستدعي أداة بناءً على الطلب وهذا الوصف10. دفعة في "مطالبة النظام" (system-prompt) مثل "استدعِ دائماً remember_fact عندما يشارك المستخدم اسمه أو تفضيلاته أو تفاصيل حسابه" تدفع النموذج نحو استدعائها بشكل أكثر حماساً.

ECONNREFUSED عند الاتصال بـ Postgres. الحاوية لم تعمل بعد، أو لا تستمع على المنفذ 5432. قم بتشغيل Docker exec agent-memory-db pg_isready -U postgres من الخطوة 1؛ إذا فشل ذلك، تحقق من Docker logs agent-memory-db قبل لمس كود التطبيق.

لماذا لا نقوم بتمثيل (embed) كل رسالة ببساطة؟

يمكنك تخطي remember_fact وتمثيل كل رسالة تلقائياً، ولكن هذا يملأ الجدول بالضوضاء — فجملة "كيف حال الطقس" لا تنتمي إلى الملف الشخصي الدائم لعميل في خطة Pro، ورسالة خام مثل "نعم، لنعتمد هذا الخيار" تكون بلا معنى خارج السياق بعد ست دورات من الحوار. إجبار Claude على استدعاء أداة يدفعه إلى كتابة الذكريات كحقائق مستقلة بذاتها ("يفضل المستخدم خطة الفوترة السنوية")، وهو ما يجعل الاسترجاع مفيداً حقاً لاحقاً.

الخطوات التالية وقراءات إضافية

يستخدم هذا البرنامج التعليمي ذاكرة مرتبطة بمورد بمطابقة دقيقة مع عدد قليل من الصفوف، لذا فإن البحث الدقيق الافتراضي في pgvector سريع بما يكفي. بمجرد أن يجمع مستخدم واحد آلاف الذكريات، ارجع إلى ضبط فهرس hnsw في pgvector HNSW Postgres 18 Production Tuning Tutorial 2026 — حيث تنطبق إعدادات ef_search، وتكميم halfvec، وبناء الفهارس المتوازية مباشرة على جدول agent_memories عند التوسع.

إذا كنت غير متأكد لماذا كانت مسافة جيب التمام (cosine distance) <=> هي المشغل الصحيح بدلاً من الضرب الداخلي (inner product) <#>، فإن مقال Cosine Similarity vs Dot Product for Embeddings (2026) يغطي الرياضيات ومتى يتفوق كل منهما. وإذا كنت تبني باستخدام Claude Agent SDK بدلاً من الـ Messages API الخام، فإن Anthropic توفر آلية استمرارية مختلفة تعتمد على الملفات تستحق المقارنة مع هذه الآلية: Claude Memory Tool + Context Editing: Agent Tutorial (2026).

للمزيد من التعمق في جانب الاسترجاع — الجمع بين البحث في النص الكامل واستعلام المتجهات، ثم استخدام Reciprocal Rank Fusion أو cross-encoder لدمج النتائج — راجع ملاحظات pgvector حول البحث الهجين (hybrid search)، والتي تنطبق على ذكريات العميل تماماً كما تنطبق على البحث في المستندات.

Footnotes

  1. آلية الذاكرة في هذا البرنامج التعليمي (Postgres خارجي + pgvector، يتم التحكم فيه من خلال التطبيق) غير مرتبطة بميزة أداة الذاكرة القائمة على الملفات الخاصة بشركة Anthropic لـ Claude Agent SDK — راجع قسم "الخطوات التالية" للحصول على رابط يقارن بين الاثنين.

  2. سجل تغييرات pgvector — https://GitHub.com/pgvector/pgvector/blob/master/CHANGELOG.md (الإصدار 0.8.2، صدر في 2026-02-25، أصلح خطأ في تجاوز سعة المخزن المؤقت (buffer-overflow) في عمليات بناء فهرس HNSW المتوازية — تم تأكيد هذه الحقيقة التاريخية المحددة بشكل متطابق عبر كل محاولة جلب. تضاربت عمليات الجلب المتكررة لسجل التغييرات هذا وسجل علامات Docker Hub حول أي تصحيح هو الحالي اعتباراً من 2026-07-17، لذا لا يؤكد هذا البرنامج التعليمي عمداً رقم تصحيح "أحدث" محدد لـ pg18 — راجع الخطوة 1 لمعرفة كيفية التحقق من إصدارك مباشرة باستخدام SELECT extversion؛ تم الجلب في 2026-07-17) 2

  3. OpenAI، دليل تضمينات المتجهات (Vector embeddings) — https://platform.openai.com/docs/guides/embeddings (يخرج text-embedding-3-small 1,536 بُعداً بشكل افتراضي؛ يمكن تقليلها عبر معامل dimensions، وفقاً للمثال التطبيقي في الدليل الذي يقصر text-embedding-3-large إلى 256 بُعداً باستخدام نفس الآلية) وصفحة أسعار OpenAI (الفئة القياسية: 0.02 دولار لكل مليون توكن مدخل وقت كتابة هذا النص)؛ تمت المقارنة المرجعية مع متعقبات الأسعار الخارجية، تم الجلب في 2026-07-17 2

  4. ملف README الخاص بـ pgvector — https://GitHub.com/pgvector/pgvector/blob/master/README.md (معامل مسافة جيب التمام <=>، سلوك البحث الدقيق مقابل التقريبي، صيغة إنشاء فهرس HNSW، القيمة الافتراضية لـ hnsw.ef_search هي 40؛ تم الجلب في 2026-07-17 مباشرة من فرع master) 2 3 4 5 6

  5. جدول إصدارات Node.js — https://endoflife.date/nodejs وجدول مجموعة عمل إصدارات Node.js في https://GitHub.com/nodejs/Release (Node 24: الإصدار الأولي 2025-05-06، بدء دعم Active LTS في 2025-10-28، ينتهي Active LTS في 2026-10-20، دعم الأمان حتى 2028-04-30، أحدث تصحيح 24.18.0 اعتباراً من 2026-06-23؛ تم الجلب في 2026-07-17) 2

  6. ملف README الخاص بـ pgvector، قسم Docker — https://GitHub.com/pgvector/pgvector/blob/master/README.md#Docker (Docker pull pgvector/pgvector:pg18-trixie؛ pg18 و pg18-bookworm هما أسماء مستعارة لنفس الصورة، بينما pg18-trixie هي صورة منفصلة مبنية على قاعدة Debian مختلفة — نفس إصدار pgvector بينهما، أياً كان الإصدار الحالي، ولكن مجموعتي العلامات غير قابلتين للتبديل؛ تم الجلب في 2026-07-17) 2

  7. لا تنشر Anthropic API للتضمينات؛ يشير كتاب الطبخ (cookbook) الخاص بـ Anthropic إلى Voyage AI كمزود تضمينات خارجي — https://GitHub.com/anthropics/claude-cookbooks/blob/main/third_party/VoyageAI/how_to_create_embeddings.md (تم التحقق في 2026-07-17). يستخدم هذا البرنامج التعليمي نقطة نهاية تضمين OpenAI بدلاً من ذلك، وهي صالحة بنفس القدر ولا تتطلب حساب Voyage AI.

  8. ملاحظات إصدار PostgreSQL 18 وتحديد الإصدارات — https://www.postgresql.org/about/news/postgresql-18-released-3142/ و https://www.postgresql.org/about/news/postgresql-184-1710-1614-1518-and-1423-released-3297/ (صدر PostgreSQL 18 في سبتمبر 2025؛ إصدار التصحيح 18.4 في 2026-05-14؛ كان PostgreSQL 19 لا يزال في المرحلة التجريبية — صدر Beta 2 في 2026-07-16 — اعتباراً من هذا المنشور، لذا يظل 18.x هو الإصدار الرئيسي المستقر الحالي؛ تم الجلب في 2026-07-17)

  9. ملف README الخاص بـ pgvector-node — https://GitHub.com/pgvector/pgvector-node (المسار الفرعي pgvector/pg، و registerTypes()، وتحويل toSql()، وأمثلة استخدام node-postgres؛ حزمة npm pgvector@0.3.0، تم تثبيتها وتنفيذها مباشرة، 2026-07-17) 2 3

  10. Anthropic، "استخدام الأدوات مع Claude" — https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview (دورة العميل والأداة: stop_reason: "tool_use"، كتل محتوى tool_use، تنسيق استجابة tool_result، توجيه tool_choice: "auto" الافتراضي عبر حقل description الخاص بالأداة؛ تم الجلب في 2026-07-17) 2

  11. Anthropic، "استخدام الأدوات المتوازي" — https://platform.claude.com/docs/en/agents-and-tools/tool-use/parallel-tool-use ("بشكل افتراضي، قد يستدعي Claude أدوات متعددة في استجابة واحدة"؛ "إرجاع tool_result واحد لكل كتلة tool_use، جميعها معاً في رسالة المستخدم التالية"؛ disable_parallel_tool_use: true داخل tool_choice — مع type: "auto"، يحد هذا من Claude إلى استدعاء أداة واحدة لكل استجابة؛ تم الجلب في 2026-07-17)