البدء السريع (5 دقائق)
خلال خمس دقائق ستنشئ وكيلًا، وتستدعيه مرة واحدة، وتفتح جلسة محادثة بمعرّفك الخاص، وتستقبل الرد بثًا مباشرًا. تعرض كل خطوة أمثلة curl وJavaScript (fetch على Node 18 أو أحدث) وPython (requests)؛ اختر التبويب مرة واحدة وسيتبعك اختيارك في الموقع كله.
الوكيل في هذا الدليل يجيب عملاء «عطور ندى»، وهو متجر إلكتروني للعطور والعود: دهن العود الملكي (12 مل) بـ 450 ريال، وعطر المسك الأبيض (100 مل) بـ 220 ريال، والتوصيل مجاني للطلبات فوق 200 ريال (وإلا فرسومه 25 ريال) ويصل خلال 1 إلى 3 أيام عمل للرياض وجدة والدمام، والإرجاع خلال 7 أيام إذا كان المنتج مغلقًا.
1. أنشئ حسابك واربط نموذجًا
رابط القسم «1. أنشئ حسابك واربط نموذجًا»- سجّل في app.k-agent.kerneltics.com. ستحصل على منظمة على الخطة المجانية ومشروع اسمه Production.
- في خطوات الإعداد اختر اربط نموذج الذكاء الاصطناعي: الصق مفتاح API من OpenAI أو Anthropic أو DeepSeek أو أي مزوّد متوافق مع OpenAI. يُتحقق من المفتاح مباشرة، ويُشفَّر، ولا يُعرض مرة أخرى أبدًا. إذا كان خادم K-Agent لديك يوفّر نموذجًا من المنصة فيمكنك تخطّي هذه الخطوة.
2. أنشئ مفتاحًا سريًا
رابط القسم «2. أنشئ مفتاحًا سريًا»افتح مفاتيح API ← إنشاء مفتاح سري وانسخ المفتاح. يبدأ بـ kt_sk_live_ ويُعرض مرة واحدة فقط. احفظه على خادمك، ثم صدّره في الطرفية:
export KAGENT_API_KEY="kt_sk_live_…"3. أنشئ وكيلًا
رابط القسم «3. أنشئ وكيلًا»الأسرع من لوحة التحكم: الوكلاء ← وكيل جديد، اختر قالبًا وسمِّه. وللقيام بالشيء نفسه عبر الواجهة البرمجية:
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 أيام إذا كان المنتج مغلقًا وبتغليفه الأصلي." } } }'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);import osimport 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 فورًا، فيصبح جاهزًا للرد مباشرة:
{ "id": "agt_01k6rz1m3w8q4t7v9x2b5c0dnf", "object": "agent", "name": "مساعد ندى", "slug": "store-assistant", "published_version": 1, "has_unpublished_changes": false, "readiness": { "ready": true, "blockers": [] }, "created_at": 1791271800}4. اطرح سؤالًا واحدًا
رابط القسم «4. اطرح سؤالًا واحدًا»السؤال الواحد لا يحتاج إلى جلسة: أرسل السؤال واستلم الجواب. خاطب الوكيل بمعرّفه النصي (slug) أو بمعرّفه agt_….
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": "كم رسوم التوصيل؟"}'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);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):
{ "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. ابدأ جلسة بمعرّفك الخاص
رابط القسم «5. ابدأ جلسة بمعرّفك الخاص»الجلسات تحفظ سجل المحادثة. يمكنك استخدام معرّفنا sess_…، أو إرفاق معرّفك الخاص external_id — هنا رقم طلب العميل order-8812. الطلب POST /v1/sessions يجلب الجلسة أو ينشئها: الطلب الأول ينشئها (201)، والطلبات اللاحقة بالمعرّف نفسه تستأنفها (200). أرسل input في الطلب نفسه لتضيف رسالة وتستلم ردها.
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": "وين طلبي؟"}'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);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"]){ "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 هذه الجلسة في أي رابط. القواعد مفصّلة في الجلسات ومعرّفات الجلسات.
6. استقبل الرد بثًا مباشرًا
رابط القسم «6. استقبل الرد بثًا مباشرًا»أضف "stream": true لتستقبل الرد على شكل Server-Sent Events أثناء كتابة النموذج له. هذه الرسالة تخاطب الجلسة بمعرّفك external_id:
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}'// 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;}import codecsimport 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 فهي المرجع المعتمد:
id: 4182event: run.createddata: {"run":{"id":"run_01k6rz7d9f1h3k5n7q9s1v3x5z","object":"run","status":"queued"}}
event: message.deltadata: {"message_id":"msg_01k6rz8e0h2k4n6q8s0v2x4z6b","delta":"أكيد، خلال 7 أيام"}
event: message.deltadata: {"message_id":"msg_01k6rz8e0h2k4n6q8s0v2x4z6b","delta":" إذا كان مغلقًا وبتغليفه الأصلي."}
id: 4185event: message.completeddata: {"message":{"id":"msg_01k6rz8e0h2k4n6q8s0v2x4z6b","role":"assistant","content":[{"type":"text","text":"أكيد، خلال 7 أيام إذا كان مغلقًا وبتغليفه الأصلي."}]}}
id: 4186event: run.completeddata: {"run":{"id":"run_01k6rz7d9f1h3k5n7q9s1v3x5z","object":"run","status":"completed","outcome":"answered"}}قد تظهر بينها أحداث أخرى مثل استدعاءات الأدوات. تجاهل أنواع الأحداث التي لا تستخدمها، فقد تُضاف أنواع جديدة. وإذا انقطع الاتصال فاستأنف بآخر id استلمته — انظر التشغيلات والبث.
ماذا بعد؟
رابط القسم «ماذا بعد؟»- ضع الوكيل على موقعك عبر ودجت الدردشة.
- دعه يستدعي أنظمتك عبر أدوات HTTP.
- تابع التحويلات والردود عبر الويب هوك.
- احتفظ بكود OpenAI الخاص بك: استخدم حزمة OpenAI.
- اضبط كل إعداد من مرجع الإعدادات.