> ## Documentation Index
> Fetch the complete documentation index at: https://lousho.com/llms.txt
> Use this file to discover all available pages before exploring further.

# الإعدادات

## ملفات مواصفات الوكيل (`AgentSpec`)

الوكيل التصريحي (declarative) ملف YAML (`.yaml`/`.yml`) أو JSON (`.json`)،
تتحقق منه `loadSpec()` بواسطة zod (`src/spec/schema.ts`). وهو الصيغة التي
يشغّلها `lousho dev` وينشرها `lousho build`.

| الحقل | النوع | مطلوب | الوصف |
| - | - | - | - |
| `name` | `string` | نعم | اسم الوكيل. |
| `prompt` | `string` | نعم | موجّه النظام (system prompt). |
| `provider.type` | `string` | نعم | `openai` أو `anthropic` أو `ollama` أو `openrouter` أو `mock`. |
| `provider.model` | `string` | نعم | معرّف النموذج الذي يستخدمه كل استدعاء (النموذج المضبوط في المزوّد؛ والقيمة `settings.model` الخاصة بالوكيل، إن وُجدت، تتقدم عليه). |
| `tools` | `string[]` | لا | أسماء أدوات مضمَّنة (انظر أدناه). |
| `policy` | `AgentSpecPolicy` | لا | الموافقات وحواجز الحماية والحدود وغيرها، وتُفرَض حين يتحول ملف المواصفات إلى وكيل (انظر أدناه). |
| `mcpServers` | `Record<string, McpServerSpec>` | لا | خوادم MCP التي يستخدمها الوكيل، مفهرسة بالاسم (انظر أدناه). |

الحقل الناقص أو غير الصالح يُفشل التحميل بخطأ يسمّي الحقل بعينه، مثل
`'prompt': Required`.

```yaml theme={null}
name: support-bot
prompt: You are a friendly support agent.
provider:
  type: openai
  model: gpt-4o-mini
tools:
  - current-date
  - http
```

### الأدوات التي يمكن لملف المواصفات الإشارة إليها

| الاسم | الأداة |
| - | - |
| `http` | `httpTool` - طلبات HTTP |
| `current-date` | `currentDateTool` - التاريخ والوقت الحاليان (ISO، UTC) |
| `day-name` | `dayNameTool` - اسم يوم الأسبوع |

الأداتان `github` و`jira` تحتاجان إلى بيانات اعتماد ليس لها حقل في ملف
المواصفات؛ والإشارة إليهما ترمي خطأً يطلب منك بناء الوكيل بـ `createAgent()`
وتمرير أداة مضبوطة الإعدادات بدلًا من ذلك.

### السياسة (`policy`)

تحوّل `specToAgent()` الحقل `policy` إلى خيارات لـ `createAgent()`، فيفرض ملف
المواصفات ما يصرّح به. الحقول المعروفة تتحقق منها `loadSpec()`؛ والمفاتيح
الأخرى يُحتفظ بها من أجل مولِّدات بيئات التشغيل (harness) الأخرى (Claude Code
و Codex و Pi)، وهي تقرأ السياسة الخام.

| الحقل | يتحول إلى | الوصف |
| - | - | - |
| `requiresApproval` | `permissions` ([`ask`](/ar/guardrails)) | `true`: كل استدعاء أداة يتوقف مؤقتًا بانتظار الموافقة. قائمة: تتوقف تلك الأدوات فقط. |
| `guardrails` | `guardrails` (المدخلات والمخرجات) | أسماء حواجز حماية مضمَّنة، أو `{ name, ...options }` (الجدول أدناه). |
| `limits` | `limits` ([الميزانيات](#الميزانيات)) | `maxTokens`, `maxInputTokens`, `maxOutputTokens`, `maxCostUsd`, `maxDurationMs`, `maxSteps`, `onExceeded`. |
| `askQuestion` | `askQuestion` | `true` تضيف الأداة المضمَّنة `ask_question`. |
| `compaction` | `compaction` | `true`، أو `{ thresholdPercent: 0.8 }` (كسر من نافذة السياق، أكبر من 0 وحتى 1). |

```yaml theme={null}
name: support-bot
prompt: You are a friendly support agent.
provider:
  type: openai
  model: gpt-4o-mini
tools:
  - http
policy:
  requiresApproval: [http]        # or `true` for every tool
  guardrails:
    - secret-scan
    - name: max-length
      maxChars: 4000
      on: input
    - name: deny-topics
      topics: [medical advice, legal advice]
  limits:
    maxTokens: 50000
    maxCostUsd: 0.25
    maxSteps: 10
  askQuestion: true
  compaction:
    thresholdPercent: 0.8
```

أسماء حواجز الحماية (انظر [حواجز حماية المدخلات والمخرجات](/ar/guardrails#حواجز-حماية-المدخلات-والمخرجات)):

| الاسم | الخيارات | ما يفعله |
| - | - | - |
| `max-length` | `maxChars` (الافتراضي 10000) | يحجب النصوص الأطول من `maxChars`. |
| `secret-scan` | `action` (`block` أو `rewrite`)، `replacement` | يحجب (أو يطمس) المفاتيح الخاصة، والمفاتيح على نمط OpenAI ومفاتيح AWS. |
| `regex` | `pattern` (مطلوب)، `flags`، `action`، `replacement` | يحجب (أو يعيد كتابة) النصوص التي تطابق `pattern`. |
| `deny-topics` | `topics` (مطلوب، قائمة) | يحجب النصوص التي تذكر موضوعًا من القائمة (دون تمييز بين الأحرف الكبيرة والصغيرة). |
| `llm-judge` | `model` (مطلوب، `"provider/model"`)، `instruction` | يسأل نموذجًا هل النص مقبول؛ استدعاء واحد لكل فحص. |

كل حاجز حماية يقبل أيضًا `on`: `input` أو `output` أو `tools` (وسائط استدعاء
أداة)، أو قائمة منها. القيمة الافتراضية `[input, output]`. الاسم أو الخيار غير
المعروف يُفشل التحقق، مع ذكر حواجز الحماية المتاحة واقتراح «هل تقصد» ("did you
mean"):
`'policy.guardrails.0': unknown guardrail 'deny-topic' (did you mean 'deny-topics'?)`.

يوقف `requiresApproval` التشغيل مؤقتًا (`finishReason: 'awaiting-approval'`)
إلى أن تُستدعى `agent.approvals.resolve()`؛ وقبل هذا التغيير كان ملف المواصفات
الذي يضبطه يشغّل أدواته دون أن يسأل. ويطبع `lousho doctor agent.yaml` سطرًا
واحدًا لكل قسم من السياسة.

### خوادم MCP (`mcpServers`)

يصرّح `mcpServers` بخوادم MCP التي يستخدمها الوكيل، في صورة خريطة من اسم الخادم
(وهو يشكّل نطاق أسماء لأدوات ذلك الخادم) إلى خادم stdio (`command`، ومعه
اختياريًا `args` و`env`) أو خادم HTTP (`url`، ومعه اختياريًا `headers`).
كل مُدخل يضبط واحدًا فقط من `command` / `url`؛ و`args`/`env` يخصّان stdio وحده
و`headers` يخصّ HTTP وحده. تتحقق `loadSpec()` من الحقل، والمُدخل غير الصالح
يفشل برسالة فيها اسم المُدخل، مثل
`'mcpServers.files': AgentSpec validation failed: missing 'command' (stdio server) or 'url' (HTTP server)`.
والحقل الاختياري `approval` (`annotations` أو `always` أو `never`) يحدد أيّ أدوات الخادم تطلب الموافقة؛ انظر [الموافقة على أدوات MCP](#الموافقة-على-أدوات-mcp-approval).
ويتحقق `lousho doctor` من أن كل `command` لخادم stdio يمكن العثور عليه.

```yaml theme={null}
mcpServers:
  filesystem:
    command: npx
    args: [-y, '@modelcontextprotocol/server-filesystem', ./data]
    env:
      LOG_LEVEL: warn
  docs:
    url: https://example.com/mcp
    headers:
      Authorization: Bearer <token>
```

```ts theme={null}
import { agentSpecSchema, specToAgent, type McpServerSpec } from '@lousho/build-ai-agent';

const filesystem: McpServerSpec = { command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem'] };
const spec = agentSpecSchema.parse({
  name: 'support-bot',
  prompt: 'You are a friendly support agent.',
  provider: { type: 'mock', model: 'mock-1' },
  mcpServers: { filesystem, docs: { url: 'https://example.com/mcp' } },
});

// The servers connect on agent.ready() or the first send() / stream().
const agent = specToAgent(spec);
console.log(Object.keys(agent.mcpServers)); // ['filesystem', 'docs']
```

تمرّر `specToAgent()` الخوادم إلى `createAgent({ mcpServers })` الموصوف في
القسم التالي، فتحصل وكلاء `lousho dev` و`lousho mcp` على أدواتها.

### ربط خوادم MCP (`mcpServers`، `connectMcp()`)

يقبل `createAgent({ mcpServers })` الخريطة نفسها. تتصل الخوادم عند
`await agent.ready()` أو، تلقائيًا، عند أول `send()` / `stream()`؛ وتُضاف
أدوات كل خادم بالصيغة `<server>__<tool>` (مثل `docs__search`). الخادم الذي
يتعذر الاتصال به يُفشل ذلك الاستدعاء، والاستدعاء التالي يحاول من جديد.
تقطع `agent.close()` الاتصال بها (وتوقف عمليات stdio)؛ وأي استدعاء أداة لاحق
يعيد الاتصال. ودون `mcpServers` لا تفعل `ready()` و`close()` شيئًا.

```ts theme={null}
import { createAgent } from '@lousho/build-ai-agent';

const agent = createAgent({
  model: 'openai/gpt-4o-mini',
  mcpServers: {
    files: { command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '.'] },
    docs: { url: 'https://example.com/mcp', headers: { Authorization: 'Bearer <token>' } },
  },
});
const { text } = await agent.send('List the files here.');
await agent.close();
```

لمشاركة الخوادم بين عدة وكلاء، أو لاختيار طريقة معالجة الإخفاقات، استدعِ
`connectMcp(servers, options?)` ومرّر `tools` الناتجة عنها بنفسك. فهي تتصل بكل
خادم وتسرد أدواته قبل أن يُنجَز وعدها، فتكون الأدوات معروفة سلفًا.
الخيارات:

* `onError`: القيمة `'throw'` (الافتراضية) ترفض الوعد حين يتعذر الاتصال بخادم،
  بعد إغلاق الخوادم الأخرى؛ والقيمة `'skip'` تستبعد ذلك الخادم وتحذّر عبر
  `logger`.
* `lazy` (الافتراضي `true`): بعد `close()` أو انقطاع الاتصال، يعيد استدعاء
  الأداة التالي الاتصال. ومع `false` يفشل ذلك الاستدعاء بدلًا من ذلك. سرد
  الأدوات يحتاج إلى اتصال، ولذلك لا يؤخّر `lazy` الاتصال الأول أبدًا.
* `logger`: يتلقى تحذيرات الخوادم المتخطّاة والأدوات المتخطّاة (الافتراضي: لا
  شيء).

تُرجع `{ tools, close(), status() }`؛ و`status()` تقرن كل خادم بإحدى القيم
`'idle'` أو `'connected'` أو `'failed'`.

```ts theme={null}
import { createAgent } from '@lousho/build-ai-agent';
import { connectMcp } from '@lousho/build-ai-agent/mcp';

const mcp = await connectMcp(
  { files: { command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '.'] } },
  { onError: 'skip', logger: console }
);
console.log(mcp.status()); // { files: 'connected' }
const agent = createAgent({ model: 'openai/gpt-4o-mini', tools: mcp.tools });
await agent.send('List the files here.');
await mcp.close();
```

تُشغَّل خوادم stdio بـ `command` و`args`؛ ويُضاف `env` إلى البيئة الافتراضية
(`PATH` وما شابه) ولا يحل محلها. أما خوادم HTTP فتستخدم النقل streamable HTTP
مع `headers` في كل طلب. والحزمة `@modelcontextprotocol/sdk` اعتمادية نظيرة
اختيارية: ثبّتها لاستخدام MCP.

### الموافقة على أدوات MCP (`approval`)

تصف خوادم MCP كل أداة بتوصيفات (annotations) هي `readOnlyHint`
و`destructiveHint` و`idempotentHint` و`openWorldHint` و`title`. وهي مجرد
تلميحات، لكن الـ SDK يتخذها أساسًا للسلوك الافتراضي في
[الموافقات](/ar/approvals): الأداة التي لها `readOnlyHint: true` تُنفَّذ؛ والأداة
التي لها `destructiveHint: true`، أو التي لا ترسل `destructiveHint` (الافتراضي
في مواصفة MCP أنها مُتلِفة)، توقف التشغيل مؤقتًا إلى أن يوافق إنسان؛ و
`destructiveHint: false` تُنفَّذ. وعليه فالأداة التي بلا توصيفات تطلب
الموافقة. تبقى التوصيفات الخام في `descriptor.metadata.mcp.annotations`،
ويصبح `title` هو `displayName`.

اضبط `approval` في مُدخل الخادم (`mcpServers`، `createAgent`، `connectMcp()`) أو
في `loadMcpTools(client, name, { approval })`:

* `'annotations'` (الافتراضي): كما سبق.
* `'always'` / `'never'`: اطلب الموافقة لكل الأدوات / لا تطلبها لأيٍّ منها.
* دالة `({ name, annotations }) => boolean` تقرر لكل أداة على حدة (`name` هو
  اسم الأداة المجرّد؛ و`annotations` تكون `{}` إذا لم يرسل الخادم شيئًا). متاحة
  في الشيفرة فقط؛ أما ملف المواصفات فيقبل السلاسل النصية الثلاث.

تُطبَّق [قواعد الصلاحيات](/ar/approvals#سياسات-الصلاحيات) أولًا، ويبقى في وسعها
أن تقرر `allow` أو `deny` أو `ask`.

```ts theme={null}
import { createAgent } from '@lousho/build-ai-agent';

const agent = createAgent({
  model: 'openai/gpt-4o-mini',
  mcpServers: {
    files: { command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '.'] },
    // Ask before anything except tools whose name starts with `search`.
    docs: { url: 'https://example.com/mcp', approval: ({ name }) => !name.startsWith('search') },
    // A server you trust: never ask.
    scratch: { command: 'node', args: ['./scratch-server.js'], approval: 'never' },
  },
});
```

### أدوات MCP (Model Context Protocol)

يمكن أيضًا تحميل أدوات `Client` اتصلت به بنفسك يدويًا - اتصل بـ `Client` من `@modelcontextprotocol/sdk` بنفسك وحمّل
أدواته بـ `loadMcpTools()`، ثم مرّر الناتج إلى `createAgent()` (أو سجّله في
`ToolRegistry`):

```ts theme={null}
import { createAgent } from '@lousho/build-ai-agent';
import { loadMcpTools } from '@lousho/build-ai-agent/mcp';

const tools = await loadMcpTools(mcpClient, 'my-server');
const agent = createAgent({ prompt: '...', provider, tools });
```

الدالة `loadMcpTools` متاحة كذلك من جذر الحزمة ومن
`@lousho/build-ai-agent/tools`.

### تقديم وكيل عبر MCP

الدالة `serveMcp()` هي عكس `loadMcpTools()`: تعرض وكيلًا (ومعه، اختياريًا،
بعض أدواته) في صورة خادم MCP، فيتمكن Claude Code و Cursor وغيرهما من عملاء MCP
من استدعائه.

```ts theme={null}
import { createAgent, defineTool } from '@lousho/build-ai-agent';
import { serveMcp } from '@lousho/build-ai-agent/mcp';
import { z } from 'zod';

const searchDocs = defineTool({
  name: 'search_docs',
  description: 'Search the docs',
  input: z.object({ query: z.string() }),
  execute: ({ query }) => `results for ${query}`,
});

const supportAgent = createAgent({ prompt: 'You answer support questions.', provider, tools: [searchDocs] });

const server = await serveMcp({
  agent: supportAgent,            // exposed as ONE tool taking { message: string }
  name: 'support-bot',            // server name; the tool name defaults to a sanitized version
  description: 'Ask the support agent a question',
  tools: [searchDocs],            // optional: also expose these tools directly
  transport: { type: 'http', port: 3920, host: '127.0.0.1', path: '/mcp' }, // default: 'stdio'
});
await server.close();
```

* **بلا حالة.** كل استدعاء لأداة الوكيل محادثة جديدة.
* **الإلغاء.** إلغاء طلب MCP يُلغي تشغيل الوكيل
  (`agent.send(message, { signal })`).
* **الأخطاء.** فشل الوكيل يعود في صورة نتيجة MCP فيها `isError: true`.
* **الموافقات.** الأدوات المشروطة بموافقة لا يمكن الموافقة عليها عبر MCP.
  التشغيل الذي يتوقف مؤقتًا بانتظار موافقة يُرجع `isError: true` مع رسالة تقول
  ذلك. والأدوات الموسومة بـ `needsApproval` لا تُعرَض مباشرة إلا إذا مرّرت
  `allowApprovalTools: true`؛ وإن فعلت، شغّلها العملاء **دون أي رقابة بشرية**.
* **stdio.** لا يُكتب إلى stdout شيء سوى بروتوكول MCP؛ والتحذيرات تذهب إلى stderr.
* **HTTP.** يرتبط بالعنوان `127.0.0.1` افتراضيًا. أضف
  `auth: { type: 'bearer', token }` لاشتراط الترويسة `Authorization: Bearer`؛
  والارتباط بمضيف غير محلي (non-loopback) دون `auth` يسجّل تحذيرًا.

#### التوصيفات

يحمل `tools/list` توصيفات MCP ليعرف العملاء ما تفعله الأداة. الأداة التي تحتاج
إلى موافقة يُعلَن عنها بـ `readOnlyHint: false, destructiveHint: true`؛ وحدّد
التلميحات بنفسك عبر `annotations` (تُرسل كما هي حرفيًا). الأداة التي بلا
تلميحات لا ترسل شيئًا، فيظل وكيل Lousho الذي يستهلك هذا الخادم يسأل قبل
تشغيلها (انظر `approval` في `connectMcp()`)؛ و`readOnlyHint: true` تُنفَّذ دون
سؤال. والأداة التي تحتاج إلى موافقة لا يُعلَن عنها أبدًا أنها للقراءة فقط.
الأدوات المضمَّنة `read_file` و`list_dir` و`glob` و`grep` و`todo_read`
و`current_date` و`day_name` للقراءة فقط.

```ts theme={null}
import { defineTool } from '@lousho/build-ai-agent';
import { z } from 'zod';

const lookupOrder = defineTool({
  name: 'lookup_order',
  description: 'Look up an order',
  input: z.object({ id: z.string() }),
  annotations: { readOnlyHint: true, destructiveHint: false, title: 'Look up order' },
  execute: ({ id }) => ({ id, status: 'shipped' }),
});
```

من سطر الأوامر، يقدّم `lousho mcp` ملف مواصفات وكيل (عبر stdio افتراضيًا):

```sh theme={null}
npx lousho mcp agent.yaml
npx lousho mcp agent.yaml --http --port 3920 --host 127.0.0.1
```

لاستخدامه من عميل MCP، أضفه إلى إعدادات MCP لدى العميل (مثل `.mcp.json` في
Claude Code):

```json theme={null}
{
  "mcpServers": {
    "support-bot": { "command": "npx", "args": ["lousho", "mcp", "agent.yaml"] }
  }
}
```

## بيانات اعتماد المزوّدين

المزوّدون الحقيقيون تحدّدهم `resolveProvider('<provider>/<model>')` (وتُستخدم
أيضًا لملفات المواصفات)، وهي تقرأ بيانات الاعتماد من متغيرات البيئة:

| المزوّد | متغير البيئة |
| - | - |
| `openai` | `OPENAI_API_KEY` |
| `anthropic` | `ANTHROPIC_API_KEY` |
| `openrouter` | `OPENROUTER_API_KEY` |
| `ollama` | `OLLAMA_BASE_URL` |

المزوّد `mock` لا يحتاج إلى بيانات اعتماد ويُرجع ردودًا معدّة سلفًا؛ وهو ما
تستخدمه الأمثلة ودليل البدء السريع افتراضيًا.

## إعادة المحاولة والبديل الاحتياطي لدى المزوّد

تعيد `createAgent()` محاولة استدعاءات النموذج الفاشلة من تلقاء نفسها، ويمكنها
اللجوء إلى نماذج أخرى كبديل احتياطي:

```ts theme={null}
import { createAgent } from '@lousho/build-ai-agent';

const agent = createAgent({
  model: 'openai/gpt-4o-mini',
  retry: { maxRetries: 3, backoff: { initialMs: 1000 } }, // default { maxRetries: 2 }; false turns it off
  fallbackModels: ['anthropic/claude-3-5-haiku-latest'], // tried in order once the retries are used up
});

for await (const event of agent.stream('Hello!')) {
  if (event.type === 'provider.retry') console.warn(`retry ${event.attempt} in ${event.delayMs}ms: ${event.error.message}`);
  if (event.type === 'provider.fallback') console.warn(`falling back from ${event.from} to ${event.to}`);
}
```

* يقبل `retry` خيارات `withRetry()` المذكورة أدناه. وهو يسري على السلسلة النصية
  `model` (أو النموذج المختار من البيئة) وعلى كل مُدخل في `fallbackModels`.
  تبني createAgent هؤلاء المزوّدين مع تعطيل إعادة المحاولة الخاصة بـ SDK
  الـ `ai` (`maxRetries: 0`)، فتجري إعادة المحاولة في مكان واحد، ويُجري
  الافتراضي `{ maxRetries: 2 }` العدد نفسه من الاستدعاءات كما في السابق.
* نسخة `provider` التي تمرّرها تحتفظ بسلوكها الخاص في إعادة المحاولة؛ ولا
  تُغلَّف بـ `withRetry()` إلا إذا ضبطت `retry`. وتعمل `fallbackModels` معها
  أيضًا.
* قيم `fallbackModels` سلاسل نصية بالصيغة `provider/model`، تُحدَّد مثل `model`
  عند إنشاء الوكيل. يشغّل الوكيل
  `withFallback([withRetry(primary), withRetry(fallback1), ...])`:
  كل استدعاء يبدأ بالنموذج الأساسي.
* تُبلغ `stream()` و`session.stream()` عن كل إعادة محاولة بحدث `provider.retry`
  وعن كل انتقال بحدث `provider.fallback` (انظر
  [البث](/ar/streaming#مخطط-الأحداث-الإصدار-1)). أما `send()` فتُرجع النتيجة
  النهائية كما في السابق.

لبناء الشيء نفسه يدويًا، أو لمزوّدين تنشئهم بنفسك، تغلّف
`withRetry(provider, options)` و`withFallback(providers, options)` أي
`LLMProvider` وتُرجعان مزوّدًا آخر، فيمكن تركيبهما معًا وتمريرهما في أي موضع
يُقبل فيه مزوّد:

```ts theme={null}
import { createAgent, resolveProvider, withFallback, withRetry } from '@lousho/build-ai-agent';

const provider = withFallback(
  [
    withRetry(resolveProvider('openai/gpt-4o-mini'), {
      maxRetries: 3,
      backoff: { initialMs: 500, maxMs: 10_000 },
      onRetry: ({ attempt, delayMs }) => console.warn(`retry ${attempt} in ${delayMs}ms`),
    }),
    withRetry(resolveProvider('anthropic/claude-3-5-haiku-latest')),
  ],
  { onFallback: ({ from, to }) => console.warn(`falling back from ${from} to ${to}`) }
);

const agent = createAgent({ prompt: 'You are helpful.', provider });
```

* تعيد `withRetry` محاولة `generate()` و`stream()` (الافتراضي `maxRetries: 2`)
  عند تجاوز حدود المعدّل (rate limits)، وانقضاء المهلة، وأخطاء الشبكة،
  واستجابات 5xx، بالتصنيف نفسه الذي تستخدمه `compactProviderError()`. لا تُعاد
  المحاولة عند فشل المصادقة، ولا الطلبات غير الصالحة، ولا أخطاء طول السياق؛
  ولا عند الإلغاء. وتلميح `retryAfterMs` من المزوّد (الترويسة `Retry-After`)
  يحل محل مدة التراجع (backoff). مرّر `retryOn(error, attempt)` لتغيير
  القاعدة، و`timeoutMs` لتحديد مهلة لكل محاولة، و`signal` لإيقاف إعادة
  المحاولة.
* لا تُعاد محاولة استدعاء `stream()` إلا إذا رُفض وعده. والخطأ الذي يقع داخل
  بث أُرجع بالفعل لا تُعاد محاولته.
* تجرّب `withFallback` المزوّدين واحدًا تلو الآخر بالترتيب، وترمي الخطأ الأخير
  من جديد إذا فشلوا جميعًا. افتراضيًا تنتقل إلى البديل الاحتياطي عند أي خطأ ما
  عدا الإلغاء (ويغيّر `fallbackOn` ذلك). كل بديل احتياطي يعمل بقيمة
  `defaultModel` الخاصة به. و`name` و`defaultModel` يعكسان المزوّد الذي خدم
  آخر استدعاء.
* تطبّق `resilientProvider(provider, { maxRetries, timeout })` حقلَي
  `LLMProviderConfig` اللذين يحملان الاسمين نفسيهما.
* المزوّدون المضمَّنون يمرّرون قيمة `maxRetries` من إعداداتهم (الافتراضي 2) إلى
  إعادة المحاولة الداخلية في SDK الـ `ai`، وهي تجري داخل كل محاولة من محاولات
  `withRetry`. أنشئ المزوّد الذي تغلّفه مع `maxRetries: 0`
  (`new OpenAIProvider({ apiKey, maxRetries: 0 })`) لتجري إعادة المحاولة في
  مكان واحد. وتفعل `createAgent()` ذلك للنماذج التي تحدّدها هي.

## خيارات `createAgent()`

| الخيار | الوصف |
| - | - |
| `model` | سلسلة نصية بالصيغة `'provider/model'` مثل `'openai/gpt-4o-mini'`، تُحدَّد بواسطة `resolveProvider()` (والمفتاح من متغير البيئة المذكور أعلاه). بديل عن `provider`. |
| `provider` | نسخة من `LLMProvider` (حقيقي أو وهمي). بديل عن `model`. إذا مرّرت الاثنين استُخدم `provider` وصار `model` إعداد النموذج لكل تشغيل لدى الوكيل (معرّف نموذج مجرّد مثل `'gpt-4o'`). |
| `instructions` | موجّه النظام. اختياري (الافتراضي `'You are a helpful assistant.'`). |
| `prompt` | اسم بديل عامل لـ `instructions`؛ وتمرير الاثنين معًا خطأ. |
| `tools` | مصفوفة من نواتج `defineTool()`، أو `Record<string, ToolDescriptor>` مفهرس بالاسم الذي يستخدمه الوكيل (انظر [الأدوات](/ar/tools)). |
| `name` | اسم الوكيل (الافتراضي `'agent'`). |
| `description` | ما يفعله الوكيل، في جملة واحدة. مطلوب حين يُستخدم وكيلًا فرعيًا. |
| `maxSteps` | يُمرَّر كما هو إلى `AgentExecutor.execute()`. |
| `limits` | ميزانيات كل تشغيل: `{ maxTokens?, maxInputTokens?, maxOutputTokens?, maxCostUsd?, maxDurationMs?, maxSteps?, onExceeded? }`. بلوغ أحد الحدود ينهي التشغيل بـ `finishReason: 'budget-exceeded'`. انظر [الميزانيات](#الميزانيات). |
| `toolConcurrency` | عدد استدعاءات الأدوات التي تعمل معًا في دورة نموذج واحدة: عدد صحيح موجب أو `'unbounded'` (الافتراضي). انظر [استدعاءات الأدوات المتوازية](/ar/api-overview#استدعاءات-الأدوات-المتوازية). |
| `skills` | مهارات من `defineSkill()` / `loadSkills()`؛ انظر [المهارات](/ar/skills). |
| `subagents`, `maxSubagentDepth` | وكلاء فرعيون مسمَّون خلف أداة `task` واحدة، وأقصى عمق لتداخلهم (الافتراضي 1)؛ انظر [الوكلاء الفرعيون](/ar/sub-agents). |
| `store` | مخزن `AgentStore` (`SqliteStore`، أو `memoryStore()`، أو `{ sessions?, checkpoints?, approvals? }`): المخازن الافتراضية لـ `agent.session()` وللموافقات ولتشغيلات `send(message, { sessionId })`؛ وتُكمل `agent.resume(id)` تشغيلًا انقطع. انظر [الجلسات المتينة](/ar/sessions#الجلسات-المتينة). |
| `memory` | خانات ذاكرة من `defineMemory()`: تُستحضر إلى موجّه النظام في بداية كل تشغيل، مع أدوات `remember_<name>` / `recall_<name>`. انظر [الذاكرة](/ar/memory). |
| `approvalStore` | الموضع الذي يُحفظ فيه التوقف المؤقت الناتج عن `needsApproval` (الافتراضي: `store.approvals`، وإلا `InMemoryApprovalStore` خاص بكل وكيل)؛ انظر [الموافقات](/ar/approvals). |
| `approve` | `(call) => boolean`: احسم الموافقات في الشيفرة بدلًا من التوقف المؤقت. |
| `projectInstructions` | `true` أو `{ cwd?, files? }`: ألحِق أقرب ملف `AGENTS.md` / `CLAUDE.md` بالتعليمات (معطَّل افتراضيًا؛ انظر [تعليمات المشروع](#تعليمات-المشروع)). |
| `retry` | خيارات `withRetry()` لاستدعاءات النموذج الفاشلة، أو `false`. الافتراضي `{ maxRetries: 2 }` لسلاسل `model` النصية؛ أما نسخة `provider` فلا تُغلَّف إلا إذا ضُبط. انظر [إعادة المحاولة والبديل الاحتياطي لدى المزوّد](#إعادة-المحاولة-والبديل-الاحتياطي-لدى-المزوّد). |
| `fallbackModels` | سلاسل نصية بالصيغة `provider/model` تُجرَّب بالترتيب حين يظل النموذج يفشل بعد استنفاد محاولاته. |
| `hooks` | مصفوفة `AgentHook[]` تعمل حول كل استدعاء للنموذج وكل استدعاء أداة، بالترتيب، قبل خطّاف ضغط السياق (انظر `AgentHook` في [نظرة عامة على الواجهة](/ar/api-overview)). |
| `compaction` | `true` (احذف نتائج الأدوات القديمة عند تجاوز 90% من نافذة السياق) أو `{ strategy?, thresholdPercent?, contextWindow?, protectedTokens?, summarizer? }`؛ و`summarizer` (`'provider/model'` أو `LLMProvider`) يختار الاستراتيجية ذات المرحلتين. تُبلغ `stream()` عن `compaction.start` / `compaction.done`. انظر [ضغط السياق](/ar/compaction#ضغط-سياق-وكيل). |

إذا لم يُحدَّد `model` ولا `provider`، تحدّد `createAgent()` المزوّد من البيئة:
`LOUSHO_MODEL` (سلسلة نصية بالصيغة `'provider/model'`) إن كان مضبوطًا، وإلا
فأول مزوّد ضُبط متغيره، وتُفحص المتغيرات بهذا الترتيب:
`OPENAI_API_KEY` (`openai/gpt-4o-mini`)، ثم `ANTHROPIC_API_KEY`
(`anthropic/claude-3-5-sonnet-latest`)، ثم `OPENROUTER_API_KEY`
(`openrouter/openai/gpt-4o-mini`)، ثم `OLLAMA_BASE_URL` (`ollama/llama3`). وإذا
لم يكن أيٌّ منها مضبوطًا رمت خطأً يسرد بدقة الخيارات أو المتغيرات التي تحل
المشكلة.

أخطاء سوء الإعداد تبيّن طريقة إصلاحها: المفتاح الناقص يسمّي المتغير
(`createAgent: OPENAI_API_KEY is not set. ...`)، والبادئة غير المعروفة تسرد
البادئات المدعومة وتقترح أقربها، والاعتمادية النظيرة الاختيارية الناقصة تطبع
أمر `npm install` بنصّه.

## الميزانيات

يضع `limits` سقفًا لما يجوز للتشغيل أن ينفقه. اضبطه في `createAgent()` (لكل
تشغيلات الوكيل) أو في `AgentExecutor.execute()` / `stream()`:

| الحد | ما يحسبه |
| - | - |
| `maxTokens` | رموز (tokens) الموجّه مع رموز الإكمال في التشغيل (`usage.totalTokens`). |
| `maxInputTokens` | رموز الموجّه (`usage.inputTokens`). |
| `maxOutputTokens` | رموز الإكمال (`usage.outputTokens`). |
| `maxCostUsd` | التكلفة التقديرية بالدولار الأمريكي (`usage.costUsd`، من [جدول الأسعار](/ar/api-overview#النماذج-والرموز-والتكلفة)). لا يُفحص ما دام أحد النماذج المستخدمة مجهول التسعير (`costUsd` تساوي `undefined`). |
| `maxDurationMs` | الزمن الفعلي المنقضي في استدعاء `execute()` / `stream()`. |
| `maxSteps` | خطوات النموذج. اسم بديل للخيار `maxSteps`: إذا ضُبط الاثنان غلب الأشد تقييدًا (وعند التساوي يُبلَّغ عن `'max-steps'` الخاص بالخيار)؛ وإذا ضُبط وحده حلّ محل القيمة الافتراضية 10. |

تُفحص الحدود قبل كل استدعاء للنموذج (أي بعد كل دفعة أدوات) وبعد استدعاء
النموذج الذي يطلب أدوات؛ كما يُلغي `maxDurationMs` استدعاء النموذج أو الأداة
الجاري عبر إشارة التشغيل. يُعدّ الحد متجاوَزًا حالما يبلغه التشغيل. واستهلاك
الوكلاء الفرعيين يُحتسب من ميزانية وكيلهم الرئيسي: يُضاف حين يعود الوكيل
الفرعي، فيتوقف الوكيل الرئيسي قبل استدعائه التالي للنموذج. والتشغيل الذي ينتهي
من تلقاء نفسه في الخطوة التي بلغت حدًّا يحتفظ بسبب انتهائه هو، كما في
`maxSteps`.

حين يُتجاوَز حد، يتوقف التشغيل بـ `finishReason: 'budget-exceeded'` مع
`result.budget` (`{ limit, value, max, scope }`). استدعاءات الأدوات التي طلبها
النموذج في تلك الخطوة تحصل على نتيجة «أُلغي» ("cancelled")، فيبقى سجل المحادثة
صالحًا، ومع مخزن نقاط حفظ يُحفظ في نقطة حفظ على أنه منتهٍ، مثل `'max-steps'`.
تُصدر `stream()` الحدث `budget.exceeded` قبل `run.done`. ومع
`onExceeded: 'throw'` يُرفَض وعد التشغيل بالخطأ `BudgetExceededError`
(`LOUSHO_BUDGET_EXCEEDED`، ومعه قيمة `budget` نفسها) بدلًا من ذلك.

```ts theme={null}
import { BudgetExceededError, createAgent } from '@lousho/build-ai-agent';

const agent = createAgent({
  provider,
  limits: { maxTokens: 50_000, maxCostUsd: 0.25, maxDurationMs: 60_000 },
});
const result = await agent.send('Research this thoroughly');
if (result.finishReason === 'budget-exceeded') {
  console.warn(`Stopped by ${result.budget?.limit}: ${result.budget?.value} of ${result.budget?.max}`);
}

try {
  await createAgent({ provider, limits: { maxCostUsd: 0.01, onExceeded: 'throw' } }).send('Go');
} catch (error) {
  if (error instanceof BudgetExceededError) console.error(error.budget);
}
```

**حدود التشغيل وحدود الجلسة.** يسري `createAgent({ limits })` على كل تشغيل على
حدة: كل `send()`، وكل دورة في جلسة، يبدأ من الصفر. ويضيف
`agent.session({ id, limits })` حدودًا تشمل كل دورات الجلسة: تتوقف الدورة
حالما يبلغ ما أنفقته الجلسة، في دوراتها كلها، حدًّا (وعندها تكون
`budget.scope` مساوية `'session'`)، والدورات اللاحقة تتوقف قبل استدعاء النموذج.
ما أنفقته الدورات (الرموز والتكلفة والخطوات وزمن التشغيل) يُحفظ مع سجل
المحادثة، في `metadata.sessionUsage` على آخر رسالة فيه، فالجلسة التي تُستكمل
من مخزنها تحتفظ بميزانيتها. يسري النوعان معًا؛ وأول حد يُبلَغ يوقف الدورة.
والدورة التي أُلغيت لا تُحتسب.

```ts theme={null}
import { createAgent, memoryStore } from '@lousho/build-ai-agent';

const agent = createAgent({ provider, store: memoryStore(), limits: { maxTokens: 20_000 } });
const session = agent.session({ id: 'user-42', limits: { maxCostUsd: 1 } });
const reply = await session.send('Hello');
if (reply.budget?.scope === 'session') console.log('This conversation used up its budget.');
```

## تعليمات المشروع

كثير من المستودعات يحفظ إرشادات لوكلاء البرمجة في ملف `AGENTS.md` (أو
`CLAUDE.md`). يستطيع `createAgent` إلحاقه بتعليمات الوكيل:

```ts theme={null}
import { createAgent } from '@lousho/build-ai-agent';

const agent = createAgent({
  instructions: 'You review pull requests.',
  provider,
  projectInstructions: true, // or { cwd: './packages/api', files: ['AGENTS.md'] }
});
```

يُضاف الملف بعد تعليماتك أنت تحت العنوان
`## Project instructions (from AGENTS.md)`. ويُقرأ مرة واحدة، عند إنشاء الوكيل.
يصعد البحث من `cwd` (الافتراضي `process.cwd()`) ويستخدم أقرب مجلد فيه أحد
ملفات `files` (الافتراضي `['AGENTS.md', 'CLAUDE.md']`، وأول تطابق يفوز)، ويتوقف
عند أقرب مجلد يحتوي `.git` أو عند جذر نظام الملفات. المحتوى الذي يزيد على
32,000 حرف يُقتطع مع علامة تدل على الاقتطاع. وإذا لم يُعثر على ملف لم يُضَف
شيء.

هذه الميزة **اختيارية (opt-in)** عن قصد: قراءة الملفات من القرص افتراضيًا
ستفاجئ من يضمّنون الـ SDK في خادم، حيث مجلد العمل ليس المشروع الذي يُعنى به
الوكيل. وللعثور على الملف بنفسك (لعرضه مثلًا)، استخدم
`loadProjectInstructions({ cwd, files, stopAt, maxChars })`، وهي تُرجع
`{ path, content }` أو `undefined`.

## خيارات `AgentExecutor.execute()`

الصنف `AgentExecutor` ساكن (static): استدعِ `AgentExecutor.execute(options)`.
المطلوب فقط `agent` و`input` و`provider`. الخيارات الشائعة الاستخدام:

| الخيار | الوصف |
| - | - |
| `agent` | كائن `AgentConfig`، يُبنى عادةً بـ `AgentBuilder`. |
| `input` | رسالة مستخدم في سلسلة نصية، أو محادثة `Message[]`. |
| `provider` | المزوّد `LLMProvider` الذي يُولَّد به. |
| `toolRegistry` | سجل `ToolRegistry` يضم الأدوات التي تشير إليها إعدادات الوكيل. |
| `maxSteps` | الحد الأعلى لخطوات LLM/الأدوات. |
| `limits` | ميزانيات الرموز والتكلفة والزمن والخطوات للتشغيل؛ انظر [الميزانيات](#الميزانيات). |
| `temperature`, `maxTokens` | معاملات التوليد. |
| `onAgentEvent` | مستمع لأحداث `AgentEvent` الخاصة بالتشغيل (`run.start`، `tool.start`، `run.done`، ...)؛ انظر [البث](/ar/streaming#الاستماع-دون-المرور-على-الأحداث). |
| `approvalStore`, `sessionId` | موافقات إشراك الإنسان (انظر `resumeAfterApproval()`). |
| `checkpointStore` | حفظ نقاط حفظ التنفيذ واستئنافها. |
| `exporter` | مُصدِّر `TraceExporter` لمقاطع التتبّع (spans) (وفق اصطلاحات OpenTelemetry GenAI، انظر [قابلية المراقبة](/ar/observability)). |
| `captureContent`, `redactContent` | تسجيل محتوى الرسائل/الأدوات في سمات المقاطع `gen_ai.*` (اختياري، opt-in) / حذف سمات المحتوى المُهمَلة. |
| `onLLMRequest`, `onLLMResponse`, `onToolCall`, `onToolResult` | خطّافات قابلية المراقبة. |

يُنجَز وعدها بكائن `ExecutionResult`: `{ text, messages, toolCalls, usage,
finishReason, steps, approvalId? }`.

## CLI

الأوامر `lousho dev` و`lousho build` و`lousho mcp` وسائر الأوامر، مع
راياتها (flags)، موصوفة في [CLI](/ar/cli).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.