الخادم API

يوفر خادم ADK-Rust REST API لتشغيل الـ agents، وإدارة الـ sessions، والوصول إلى الـ artifacts. عند نشر الـ agent الخاص بك باستخدام Launcher في وضع الخادم، فإنه يكشف هذه الـ endpoints بالإضافة إلى واجهة مستخدم ويب.

نظرة عامة

الخادم مبني على Axum ويوفر:

  • REST API: HTTP endpoints لتنفيذ الـ agent وإدارة الـ session
  • Server-Sent Events (SSE): بث مباشر لاستجابات الـ agent
  • Web UI: واجهة تفاعلية قائمة على المتصفح
  • CORS Support: طلبات عبر المصادر ممكّنة
  • Telemetry: قابلية ملاحظة مدمجة مع التتبع

يكشف ServerConfig أيضًا تمريرًا على مستوى الـ runner لعمليات النشر طويلة الأمد:

let config = ServerConfig::new(agent_loader, session_service)
    .with_compaction(compaction_config)
    .with_context_cache(context_cache_config, cache_capable_model);

بدء تشغيل الخادم

استخدم الـ Launcher لبدء تشغيل الخادم:

use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<()> {
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = Arc::new(GeminiModel::new(&api_key, "gemini-2.5-flash")?);
    
    let agent = LlmAgentBuilder::new("my_agent")
        .description("A helpful assistant")
        .instruction("You are a helpful assistant.")
        .model(model)
        .build()?;
    
    Launcher::new(Arc::new(agent)).run().await
}

ابدأ من هيكل API الذي تم التحقق منه:

cargo adk new my-api --template api
cd my-api
cargo run

REST API نقاط النهاية

فحص السلامة

تحقق مما إذا كان الخادم قيد التشغيل:

GET /api/health

الاستجابة:

OK

تشغيل الوكيل مع البث

نفّذ وكيلًا وقم ببث الاستجابات باستخدام أحداث مرسلة من الخادم (Server-Sent Events):

POST /api/run_sse

نص الطلب:

{
  "appName": "my_agent",
  "userId": "user123",
  "sessionId": "session456",
  "newMessage": {
    "role": "user",
    "parts": [
      {
        "text": "What is the capital of France?"
      }
    ]
  },
  "streaming": true
}

الاستجابة:

  • Content-Type: text/event-stream
  • يبث الأحداث ككائنات JSON

تنسيق الحدث:

{
  "id": "evt_123",
  "timestamp": 1234567890,
  "author": "my_agent",
  "content": {
    "role": "model",
    "parts": [
      {
        "text": "The capital of France is Paris."
      }
    ]
  },
  "actions": {},
  "llm_response": {
    "content": {
      "role": "model",
      "parts": [
        {
          "text": "The capital of France is Paris."
        }
      ]
    }
  }
}

إدارة الجلسات

إنشاء جلسة

أنشئ جلسة جديدة:

POST /api/sessions

نص الطلب:

{
  "appName": "my_agent",
  "userId": "user123",
  "sessionId": "session456"
}

الاستجابة:

{
  "id": "session456",
  "appName": "my_agent",
  "userId": "user123",
  "lastUpdateTime": 1234567890,
  "events": [],
  "state": {}
}

الحصول على جلسة

استرجع تفاصيل الجلسة:

GET /api/sessions/:app_name/:user_id/:session_id

الاستجابة:

{
  "id": "session456",
  "appName": "my_agent",
  "userId": "user123",
  "lastUpdateTime": 1234567890,
  "events": [],
  "state": {}
}

حذف جلسة

احذف جلسة:

DELETE /api/sessions/:app_name/:user_id/:session_id

الاستجابة:

  • الحالة: 204 No Content

سرد الجلسات

اسرد جميع الجلسات لمستخدم:

GET /api/apps/:app_name/users/:user_id/sessions

الاستجابة:

[
  {
    "id": "session456",
    "appName": "my_agent",
    "userId": "user123",
    "lastUpdateTime": 1234567890,
    "events": [],
    "state": {}
  }
]

إدارة القطع الأثرية

سرد القطع الأثرية

اسرد جميع القطع الأثرية لجلسة:

GET /api/sessions/:app_name/:user_id/:session_id/artifacts

الاستجابة:

[
  "image1.png",
  "document.pdf",
  "data.json"
]

الحصول على الأثر

تنزيل أثر:

GET /api/sessions/:app_name/:user_id/:session_id/artifacts/:artifact_name

الاستجابة:

  • Content-Type: يتم تحديده بواسطة امتداد الملف
  • Body: محتوى ثنائي أو نصي

إدارة التطبيقات

سرد التطبيقات

سرد جميع الـ agents المتاحة:

GET /api/apps
GET /api/list-apps  (legacy compatibility)

الاستجابة:

{
  "apps": [
    {
      "name": "my_agent",
      "description": "A helpful assistant"
    }
  ]
}

واجهة المستخدم الويب

يتضمن الخادم واجهة مستخدم ويب مدمجة يمكن الوصول إليها على:

http://localhost:8080/ui/

الميزات

  • الدردشة التفاعلية: إرسال الرسائل وتلقي الاستجابات المتدفقة
  • إدارة الجلسات: إنشاء الجلسات وعرضها والتبديل بينها
  • دعم الـ Multi-Agent: تصور عمليات نقل الـ agent والتسلسلات الهرمية
  • عارض الآثار: عرض وتنزيل آثار الجلسة
  • تحديثات في الوقت الفعلي: تدفق قائم على SSE للاستجابات الفورية

مسارات واجهة المستخدم

  • / - يعيد التوجيه إلى /ui/
  • /ui/ - واجهة الدردشة الرئيسية
  • /ui/assets/* - الأصول الثابتة (CSS، JS، الصور)
  • /ui/assets/config/runtime-config.json - تهيئة وقت التشغيل

أمثلة العميل

JavaScript/TypeScript

استخدام Fetch API مع SSE:

async function runAgent(message) {
  const response = await fetch('http://localhost:8080/api/run_sse', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      appName: 'my_agent',
      userId: 'user123',
      sessionId: 'session456',
      newMessage: {
        role: 'user',
        parts: [{ text: message }]
      },
      streaming: true
    })
  });

  const reader = response.body.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    
    const chunk = decoder.decode(value);
    const lines = chunk.split('\n');
    
    for (const line of lines) {
      if (line.startsWith('data: ')) {
        const event = JSON.parse(line.slice(6));
        console.log('Event:', event);
      }
    }
  }
}

Python

استخدام مكتبة requests:

import requests
import json

def run_agent(message):
    url = 'http://localhost:8080/api/run_sse'
    payload = {
        'appName': 'my_agent',
        'userId': 'user123',
        'sessionId': 'session456',
        'newMessage': {
            'role': 'user',
            'parts': [{'text': message}]
        },
        'streaming': True
    }
    
    response = requests.post(url, json=payload, stream=True)
    
    for line in response.iter_lines():
        if line:
            line_str = line.decode('utf-8')
            if line_str.startswith('data: '):
                event = json.loads(line_str[6:])
                print('Event:', event)

run_agent('What is the capital of France?')

cURL

# Create session
curl -X POST http://localhost:8080/api/sessions \
  -H "Content-Type: application/json" \
  -d '{
    "appName": "my_agent",
    "userId": "user123",
    "sessionId": "session456"
  }'

# Run agent with streaming
curl -X POST http://localhost:8080/api/run_sse \
  -H "Content-Type: application/json" \
  -d '{
    "appName": "my_agent",
    "userId": "user123",
    "sessionId": "session456",
    "newMessage": {
      "role": "user",
      "parts": [{"text": "What is the capital of France?"}]
    },
    "streaming": true
  }'

تهيئة الخادم

منفذ مخصص

لتعيين منفذ مخصص، قم بتعيين PORT قبل بدء تشغيل الخادم الذي تم إنشاؤه:

PORT=3000 cargo run

خدمة الأصول المخصصة

قم بتوفير خدمة الأصول الخاصة بك:

use adk_artifact::InMemoryArtifactService;

let artifact_service = Arc::new(InMemoryArtifactService::new());

Launcher::new(Arc::new(agent))
    .with_artifact_service(artifact_service)
    .run()
    .await

خدمة الجلسات المخصصة

لعمليات النشر الإنتاجية، استخدم خدمة جلسات مستمرة:

use adk_session::SqliteSessionService;

// Note: This requires implementing a custom server setup
// The Launcher uses InMemorySessionService by default

معالجة الأخطاء

يستخدم API استجابات خطأ منظمة مع رموز حالة HTTP مشتقة من فئة الخطأ:

رمز الحالةالفئةالمعنى
200نجاح
204نجاح (لا يوجد محتوى)
400invalid_inputطلب سيء — معلمات أو إعدادات غير صالحة
401unauthorizedبيانات اعتماد مفقودة أو غير صالحة
403forbiddenبيانات اعتماد صالحة، أذونات غير كافية
404not_foundالمورد غير موجود
408timeoutانتهت مهلة العملية
429rate_limitedتم تجاوز حد المعدل في المنبع
500internalخطأ داخلي في الخادم
501unsupportedميزة غير مدعومة
503unavailableالخدمة المصدر غير متاحة

تنسيق استجابة الخطأ (مشكلة JSON):

{
  "error": {
    "code": "model.openai.rate_limited",
    "message": "OpenAI rate limit exceeded",
    "component": "model",
    "category": "rate_limited",
    "requestId": "req-abc123",
    "retryAfter": 5000,
    "upstreamStatusCode": 429
  }
}

يتم تضمين الحقول requestId، retryAfter، و upstreamStatusCode عند توفرها (تكون null بخلاف ذلك).

CORS التكوين

يقوم الخادم بتمكين CORS المتساهل افتراضيًا، مما يسمح بالطلبات من أي مصدر. هذا مناسب للتطوير ولكن يجب تقييده في بيئة الإنتاج.

القياس عن بعد

يقوم الخادم بتهيئة القياس عن بعد تلقائيًا عند بدء التشغيل. يتم إخراج السجلات إلى stdout بتنسيق منظم.

مستويات السجل:

  • ERROR: أخطاء حرجة
  • WARN: تحذيرات
  • INFO: معلومات عامة (افتراضي)
  • DEBUG: تصحيح أخطاء مفصل
  • TRACE: تتبع مفصل للغاية

عيّن مستوى السجل باستخدام متغير البيئة RUST_LOG:

RUST_LOG=debug cargo run

أفضل الممارسات

  1. إدارة الجلسة: قم دائمًا بإنشاء session قبل تشغيل Agent
  2. معالجة الأخطاء: تحقق من HTTP status codes وتعامل مع الأخطاء بشكل مناسب
  3. البث: استخدم SSE للاستجابات في الوقت الفعلي؛ قم بتحليل الأحداث سطرًا بسطر
  4. الأمان: في بيئة الإنتاج، قم بتطبيق المصادقة وتقييد CORS
  5. الاستمرارية: استخدم SqliteSessionService أو PostgresSessionService لعمليات النشر في بيئة الإنتاج
  6. المراقبة: قم بتمكين telemetry وراقب logs بحثًا عن المشكلات

مثال متكامل

للحصول على هيكل خادم عامل ومتكامل، استخدم قالب cargo-adk API المعتمد. يوضح هذا:

  • الواجهة الأمامية: HTML/JavaScript عميل مع بث في الوقت الفعلي
  • الواجهة الخلفية: ADK Agent مع بحث مخصص وأدوات توليد PDF
  • التكامل: استخدام REST API كامل مع بث SSE
  • المخرجات: توليد PDF وتنزيلها
  • إدارة الجلسات: إنشاء الجلسات ومعالجتها تلقائيًا

يوضح هذا المثال نمطًا جاهزًا للإنتاج لبناء تطبيقات ويب مدعومة بالذكاء الاصطناعي باستخدام ADK-Rust.

بدء سريع:

cargo adk new my-api --template api
cd my-api
cargo run

الملفات:

  • الواجهة الخلفية: adk-rust-guide/examples/deployment/full_stack_research.rs
  • الواجهة الأمامية: examples/research_paper/frontend.html
  • الوثائق: examples/research_paper/README.md
  • الهندسة المعمارية: examples/research_paper/architecture.md

السابق: ← Launcher | التالي: A2A بروتوكول →