# البدء السريع (5 دقائق)

> أنشئ وكيلًا ومفتاحًا سريًا، واطرح سؤالًا واحدًا، وابدأ جلسة بمعرّفك الخاص، واستقبل الرد بثًا مباشرًا — بأمثلة curl وJavaScript وPython.

خلال خمس دقائق ستنشئ وكيلًا، وتستدعيه مرة واحدة، وتفتح جلسة محادثة بمعرّفك الخاص، وتستقبل الرد بثًا مباشرًا. تعرض كل خطوة أمثلة **curl** و**JavaScript** (`fetch` على Node 18 أو أحدث) و**Python** (`requests`)؛ اختر التبويب مرة واحدة وسيتبعك اختيارك في الموقع كله.

الوكيل في هذا الدليل يجيب عملاء «عطور ندى»، وهو متجر إلكتروني للعطور والعود: دهن العود الملكي (12 مل) بـ 450 ريال، وعطر المسك الأبيض (100 مل) بـ 220 ريال، والتوصيل مجاني للطلبات فوق 200 ريال (وإلا فرسومه 25 ريال) ويصل خلال 1 إلى 3 أيام عمل للرياض وجدة والدمام، والإرجاع خلال 7 أيام إذا كان المنتج مغلقًا.

## 1. أنشئ حسابك واربط نموذجًا

1. سجّل في [app.k-agent.kerneltics.com](https://app.k-agent.kerneltics.com). ستحصل على منظمة على الخطة المجانية ومشروع اسمه **Production**.
2. في خطوات الإعداد اختر **اربط نموذج الذكاء الاصطناعي**: الصق مفتاح API من OpenAI أو Anthropic أو DeepSeek أو أي مزوّد متوافق مع OpenAI. يُتحقق من المفتاح مباشرة، ويُشفَّر، ولا يُعرض مرة أخرى أبدًا. إذا كان خادم K-Agent لديك يوفّر نموذجًا من المنصة فيمكنك تخطّي هذه الخطوة.

## 2. أنشئ مفتاحًا سريًا

افتح **مفاتيح API ← إنشاء مفتاح سري** وانسخ المفتاح. يبدأ بـ `kt_sk_live_` ويُعرض **مرة واحدة فقط**. احفظه على خادمك، ثم صدّره في الطرفية:

```bash
export KAGENT_API_KEY="kt_sk_live_…"
```

## 3. أنشئ وكيلًا

الأسرع من لوحة التحكم: **الوكلاء ← وكيل جديد**، اختر قالبًا وسمِّه. وللقيام بالشيء نفسه عبر الواجهة البرمجية:

**curl**

```bash
curl https://api.k-agent.kerneltics.com/v1/agents \
  -H "Authorization: Bearer $KAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "مساعد ندى",
    "slug": "store-assistant",
    "config": {
      "locale": { "language": "ar", "timezone": "Asia/Riyadh" },
      "instructions": {
        "enabled": true,
        "text": "أنت تجيب عملاء «عطور ندى»، وهو متجر إلكتروني للعطور والعود. الأسعار: دهن العود الملكي 12 مل بـ 450 ريال، وعطر المسك الأبيض 100 مل بـ 220 ريال، وصندوق البخور بـ 95 ريال. التوصيل مجاني للطلبات فوق 200 ريال، وإلا فرسومه 25 ريال، ويصل خلال 1 إلى 3 أيام عمل للرياض وجدة والدمام، ومن 3 إلى 5 أيام لبقية المدن. الإرجاع خلال 7 أيام إذا كان المنتج مغلقًا وبتغليفه الأصلي."
      }
    }
  }'
```

**JavaScript**

```js
const BASE = 'https://api.k-agent.kerneltics.com/v1';
const headers = {
  Authorization: `Bearer ${process.env.KAGENT_API_KEY}`,
  'Content-Type': 'application/json',
};

const res = await fetch(`${BASE}/agents`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    name: 'مساعد ندى',
    slug: 'store-assistant',
    config: {
      locale: { language: 'ar', timezone: 'Asia/Riyadh' },
      instructions: {
        enabled: true,
        text: 'أنت تجيب عملاء «عطور ندى»، وهو متجر إلكتروني للعطور والعود. الأسعار: دهن العود الملكي 12 مل بـ 450 ريال، وعطر المسك الأبيض 100 مل بـ 220 ريال، وصندوق البخور بـ 95 ريال. التوصيل مجاني للطلبات فوق 200 ريال، وإلا فرسومه 25 ريال، ويصل خلال 1 إلى 3 أيام عمل للرياض وجدة والدمام، ومن 3 إلى 5 أيام لبقية المدن. الإرجاع خلال 7 أيام إذا كان المنتج مغلقًا وبتغليفه الأصلي.',
      },
    },
  }),
});
const agent = await res.json();
console.log(agent.id, agent.published_version, agent.readiness);
```

**Python**

```python
import os
import requests

BASE = "https://api.k-agent.kerneltics.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['KAGENT_API_KEY']}"}

r = requests.post(f"{BASE}/agents", headers=HEADERS, json={
    "name": "مساعد ندى",
    "slug": "store-assistant",
    "config": {
        "locale": {"language": "ar", "timezone": "Asia/Riyadh"},
        "instructions": {
            "enabled": True,
            "text": "أنت تجيب عملاء «عطور ندى»، وهو متجر إلكتروني للعطور والعود. "
                    "الأسعار: دهن العود الملكي 12 مل بـ 450 ريال، وعطر المسك الأبيض 100 مل بـ 220 ريال، وصندوق البخور بـ 95 ريال. "
                    "التوصيل مجاني للطلبات فوق 200 ريال، وإلا فرسومه 25 ريال، ويصل خلال 1 إلى 3 أيام عمل "
                    "للرياض وجدة والدمام، ومن 3 إلى 5 أيام لبقية المدن. "
                    "الإرجاع خلال 7 أيام إذا كان المنتج مغلقًا وبتغليفه الأصلي.",
        },
    },
})
r.raise_for_status()
agent = r.json()
print(agent["id"], agent["published_version"], agent["readiness"])
```

الإعدادات التي لا ترسلها تأخذ قيمها الافتراضية، والاستجابة تعرض الإعدادات كاملة دائمًا. وإنشاء الوكيل **ينشر الإصدار 1 فورًا**، فيصبح جاهزًا للرد مباشرة:

```json
{
  "id": "agt_01k6rz1m3w8q4t7v9x2b5c0dnf",
  "object": "agent",
  "name": "مساعد ندى",
  "slug": "store-assistant",
  "published_version": 1,
  "has_unpublished_changes": false,
  "readiness": { "ready": true, "blockers": [] },
  "created_at": 1791271800
}
```

:::tip[الوكيل غير جاهز؟]
إذا احتوت `readiness.blockers` على `no_model_credential` فاربط مفتاح مزوّد (الخطوة 1). الطلبات إلى وكيل غير جاهز تعيد `409 agent_not_ready`، ولا تعيد نصف إجابة أبدًا.
:::

## 4. اطرح سؤالًا واحدًا

السؤال الواحد لا يحتاج إلى جلسة: أرسل السؤال واستلم الجواب. خاطب الوكيل بمعرّفه النصي (slug) أو بمعرّفه `agt_…`.

**curl**

```bash
curl https://api.k-agent.kerneltics.com/v1/agents/store-assistant/ask \
  -H "Authorization: Bearer $KAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input": "كم رسوم التوصيل؟"}'
```

**JavaScript**

```js
const res = await fetch(`${BASE}/agents/store-assistant/ask`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ input: 'كم رسوم التوصيل؟' }),
});
const run = await res.json();
if (!res.ok) throw new Error(`${run.error.code}: ${run.error.message}`);
console.log(run.output_text);
```

**Python**

```python
r = requests.post(f"{BASE}/agents/store-assistant/ask", headers=HEADERS,
                  json={"input": "كم رسوم التوصيل؟"}, timeout=120)
r.raise_for_status()
print(r.json()["output_text"])
```

الاستجابة **تشغيل** (run). يحمل `output_text` الجواب، ويخبرك `outcome` هل أجاب الوكيل (`answered`) أم حوّل لموظف (`handed_off`):

```json
{
  "id": "run_01k6rz5a9d3f6g2h8j4k7m1n5p",
  "object": "run",
  "agent": { "id": "agt_01k6rz1m3w8q4t7v9x2b5c0dnf", "version": 1 },
  "session_id": null,
  "mode": "one_shot",
  "status": "completed",
  "outcome": "answered",
  "output_text": "التوصيل مجاني للطلبات فوق 200 ريال، وإذا كان طلبك أقل فرسومه 25 ريال.",
  "handoff": null,
  "error": null,
  "usage": { "input_tokens": 1214, "cached_input_tokens": 0, "output_tokens": 27, "model_calls": 1, "units": 0.25, "weight": 1 },
  "config_hash": "sha256:4be1c0d6…",
  "created_at": 1791271860,
  "completed_at": 1791271861
}
```

## 5. ابدأ جلسة بمعرّفك الخاص

الجلسات تحفظ سجل المحادثة. يمكنك استخدام معرّفنا `sess_…`، أو إرفاق معرّفك الخاص `external_id` — هنا رقم طلب العميل `order-8812`. الطلب `POST /v1/sessions` **يجلب الجلسة أو ينشئها**: الطلب الأول ينشئها (`201`)، والطلبات اللاحقة بالمعرّف نفسه تستأنفها (`200`). أرسل `input` في الطلب نفسه لتضيف رسالة وتستلم ردها.

**curl**

```bash
curl https://api.k-agent.kerneltics.com/v1/sessions \
  -H "Authorization: Bearer $KAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"agent": "store-assistant", "external_id": "order-8812", "input": "وين طلبي؟"}'
```

**JavaScript**

```js
const res = await fetch(`${BASE}/sessions`, {
  method: 'POST',
  headers: { ...headers, 'Idempotency-Key': crypto.randomUUID() },
  body: JSON.stringify({ agent: 'store-assistant', external_id: 'order-8812', input: 'وين طلبي؟' }),
});
const { session, created, run } = await res.json();
console.log(res.status, session.id, created, run.output_text);
```

**Python**

```python
import uuid

r = requests.post(f"{BASE}/sessions",
                  headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
                  json={"agent": "store-assistant", "external_id": "order-8812",
                        "input": "وين طلبي؟"},
                  timeout=120)
r.raise_for_status()
body = r.json()
print(r.status_code, body["session"]["id"], body["created"], body["run"]["output_text"])
```

```json
{
  "session": {
    "id": "sess_01k6rz4p7h2c9m5x8w3t6v1qbg",
    "object": "session",
    "external_id": "order-8812",
    "status": "active",
    "mode": "agent",
    "created_at": 1791271920
  },
  "created": true,
  "message": { "id": "msg_01k6rz5b2c4d6e8f0g1h3j5k7m", "object": "message", "role": "user" },
  "run": { "id": "run_01k6rz6c8e0g2j4m6p8r0t2v4x", "object": "run", "status": "completed", "outcome": "answered", "output_text": "طلبات الرياض وجدة والدمام توصل خلال 1 إلى 3 أيام عمل، وبقية المدن خلال 3 إلى 5 أيام. لأي مدينة طلبك؟" },
  "warnings": []
}
```

من الآن يخاطب كلٌّ من `order-8812` و`sess_01k6rz4p7h2c9m5x8w3t6v1qbg` هذه الجلسة في أي رابط. القواعد مفصّلة في [الجلسات ومعرّفات الجلسات](/docs/concepts/sessions/).

## 6. استقبل الرد بثًا مباشرًا

أضف `"stream": true` لتستقبل الرد على شكل Server-Sent Events أثناء كتابة النموذج له. هذه الرسالة تخاطب الجلسة بمعرّفك `external_id`:

**curl**

```bash
curl -N https://api.k-agent.kerneltics.com/v1/sessions/order-8812/messages \
  -H "Authorization: Bearer $KAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input": "أقدر أرجع العطر؟", "stream": true}'
```

**JavaScript**

```js
// Parses a text/event-stream response into { id, event, data } objects.
async function* readEvents(response) {
  const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
  let buffer = '';
  let ev = { id: undefined, event: 'message', data: [] };
  for (;;) {
    const { value, done } = await reader.read();
    if (done) return;
    buffer += value;
    const lines = buffer.split('\n');
    buffer = lines.pop();
    for (const raw of lines) {
      const line = raw.endsWith('\r') ? raw.slice(0, -1) : raw;
      if (line === '') {
        if (ev.data.length) yield { id: ev.id, event: ev.event, data: JSON.parse(ev.data.join('\n')) };
        ev = { id: undefined, event: 'message', data: [] };
      } else if (!line.startsWith(':')) {
        const i = line.indexOf(':');
        const field = i === -1 ? line : line.slice(0, i);
        const value = i === -1 ? '' : line.slice(i + 1).replace(/^ /, '');
        if (field === 'id') ev.id = value;
        else if (field === 'event') ev.event = value;
        else if (field === 'data') ev.data.push(value);
      }
    }
  }
}

const res = await fetch(`${BASE}/sessions/order-8812/messages`, {
  method: 'POST',
  headers: { ...headers, Accept: 'text/event-stream' },
  body: JSON.stringify({ input: 'أقدر أرجع العطر؟', stream: true }),
});
if (!res.ok) throw new Error((await res.json()).error.code);

for await (const { event, data } of readEvents(res)) {
  if (event === 'message.delta') process.stdout.write(data.delta);
  if (event === 'run.completed' || event === 'run.failed') break;
}
```

**Python**

```python
import codecs
import json

def sse_events(response):
    """Yields (event, data) pairs from a text/event-stream response."""
    decoder = codecs.getincrementaldecoder("utf-8")()
    buffer, event, data = "", "message", []
    for chunk in response.iter_content(chunk_size=None):
        buffer += decoder.decode(chunk)
        *lines, buffer = buffer.split("\n")
        for line in lines:
            line = line.rstrip("\r")
            if not line:  # a blank line ends an event
                if data:
                    yield event, json.loads("\n".join(data))
                event, data = "message", []
            elif not line.startswith(":"):  # lines starting with ":" are heartbeats
                field, _, value = line.partition(":")
                value = value.removeprefix(" ")
                if field == "event":
                    event = value
                elif field == "data":
                    data.append(value)

with requests.post(f"{BASE}/sessions/order-8812/messages", headers=HEADERS,
                   json={"input": "أقدر أرجع العطر؟", "stream": True},
                   stream=True, timeout=120) as r:
    r.raise_for_status()
    for event, data in sse_events(r):
        if event == "message.delta":
            print(data["delta"], end="", flush=True)
        elif event in ("run.completed", "run.failed"):
            break
```

يبدو البث هكذا. أحداث `message.delta` معاينة على أفضل جهد؛ أما `message.completed` و`run.completed` فهي المرجع المعتمد:

```text
id: 4182
event: run.created
data: {"run":{"id":"run_01k6rz7d9f1h3k5n7q9s1v3x5z","object":"run","status":"queued"}}

event: message.delta
data: {"message_id":"msg_01k6rz8e0h2k4n6q8s0v2x4z6b","delta":"أكيد، خلال 7 أيام"}

event: message.delta
data: {"message_id":"msg_01k6rz8e0h2k4n6q8s0v2x4z6b","delta":" إذا كان مغلقًا وبتغليفه الأصلي."}

id: 4185
event: message.completed
data: {"message":{"id":"msg_01k6rz8e0h2k4n6q8s0v2x4z6b","role":"assistant","content":[{"type":"text","text":"أكيد، خلال 7 أيام إذا كان مغلقًا وبتغليفه الأصلي."}]}}

id: 4186
event: run.completed
data: {"run":{"id":"run_01k6rz7d9f1h3k5n7q9s1v3x5z","object":"run","status":"completed","outcome":"answered"}}
```

قد تظهر بينها أحداث أخرى مثل استدعاءات الأدوات. تجاهل أنواع الأحداث التي لا تستخدمها، فقد تُضاف أنواع جديدة. وإذا انقطع الاتصال فاستأنف بآخر `id` استلمته — انظر [التشغيلات والبث](/docs/concepts/runs-and-streaming/).

## ماذا بعد؟

- ضع الوكيل على موقعك عبر [ودجت الدردشة](/docs/guides/widget/).
- دعه يستدعي أنظمتك عبر [أدوات HTTP](/docs/guides/http-tools/).
- تابع التحويلات والردود عبر [الويب هوك](/docs/guides/webhooks/).
- احتفظ بكود OpenAI الخاص بك: [استخدم حزمة OpenAI](/docs/guides/openai-sdk/).
- اضبط كل إعداد من [مرجع الإعدادات](/docs/concepts/settings/).
