בניית עוזר נייד מונחה בינה מלאכותית – שילוב API חיצוניים
אנו יוצרים עוזרים חכמים שמחליטים באופן אוטונומי אילו API של צד שלישי להפעיל ובאיזה סדר. המשתמש מקליד "הזמן לי טיסה לברלין ביום שישי הבא, ומלון קרוב למרכז מתחת ל-100 יורו" — העוזר, באמצעות function calling (ראה ויקיפדיה), מחפש טיסות, בוחר את האופטימלית, מחפש מלונות לפי קריטריונים, משווה אפשרויות ומבקש אישור. מספר API, מספר שלבים, התערבות מינימלית. הניסיון שלנו מראה שעוזר מעוצב היטב מקצר את זמן המשתמש ב-70% בהשוואה לחיפוש ידני. לצוות שלנו ניסיון מוכח של 5+ שנים בפיתוח מובייל ובשילובי AI, עם למעלה מ-30 פרויקטים המשתמשים בארכיטקטורת agentic. פרסנו פתרונות כאלה לתחומי נסיעות, לוגיסטיקה ופיננסים — לקוחות חוסכים עד 40% מתקציב האינטגרציה בזכות שימוש חוזר בכלים, עם חיסכון אופייני של $5,000–$15,000 לפרויקט.
כיצד פועל לולאת האורקסטרציה?
הלב של עוזר חכם הוא הלולאה: LLM → tool_calls → execute → LLM → ... במובייל, לולאה זו מתקיימת או בצד הלקוח או בשרת (אנו ממליצים על האחרון לעוזרים מורכבים). לולאה בצד הלקוח מתאימה ל-2–4 כלים ללא שרשראות תלות ארוכות. הגישה שלנו בצד השרת מהירה פי 3 בטיפול בקריאות API מקבילות.
// Android — агентный цикл
suspend fun runAgent(userMessage: String): String {
val messages = mutableListOf(Message(role = "user", content = userMessage))
repeat(MAX_ITERATIONS) {
val response = llmClient.complete(messages, tools = availableTools)
if (response.finishReason == "stop") return response.content ?: ""
if (response.finishReason == "tool_calls") {
messages.add(response.toAssistantMessage())
response.toolCalls.map { call ->
async { toolDispatcher.dispatch(call.name, call.arguments) }
}.awaitAll().forEachIndexed { i, result ->
messages.add(Message(role = "tool", toolCallId = response.toolCalls[i].id, content = result))
}
}
}
return "Агент не смог завершить задачу за $MAX_ITERATIONS шагов"
}// Android — агентный цикл suspend fun runAgent(userMessage: String): String { val messages = mutableListOf(Message(role = "user", content = userMessage)) repeat(MAX_ITERATIONS) { val response = llmClient.complete(messages, tools = availableTools) if (response.finishReason == "stop") return response.content ?: "" if (response.finishReason == "tool_calls") { messages.add(response.toAssistantMessage()) response.toolCalls.map { call -> async { toolDispatcher.dispatch(call.name, call.arguments) } }.awaitAll().forEachIndexed { i, result -> messages.add(Message(role = "tool", toolCallId = response.toolCalls[i].id, content = result)) } } } return "Агент не смог завершить задачу за $MAX_ITERATIONS шагов" } הוא רשת ביטחון קריטית. בלעדיו, העוזר יכול להיכנס ללולאה אינסופית ולשרוף את תקציב הטוקנים שלך. עבור רוב המשימות, 10 איטרציות מספיקות. המהנדסים המוסמכים שלנו מבטיחים מגבלות תקינות.
אילו בעיות מתעוררות בגישה ל-API חיצוניים?
אימות ואבטחת טוקנים. העוזר קורא ל-API חיצוניים בשם המשתמש — הוא זקוק לטוקנים (OAuth, API key). לעולם אל תאחסן מפתחות API של צד שלישי באפליקציית מובייל בטקסט פשוט. הסכימה הנכונה: לקוח מובייל → השרת שלך (עם ולידציה) → API חיצוני. השרת מאחסן טוקנים, מתווך בקשות ורושם קריאות. אחרת, מפתח Google Maps או Booking ידלוף דרך פירוק APK. אנו משתמשים בהצפנה בצד השרת ובטוקנים קצרי מועד, ומספקים שיפור אבטחה פי 4 לעומת אחסון בצד הלקוח בלבד.
הגבלת קצב וזמן קצוב. API חיצוניים מגבילים בקשות. אם העוזר מבצע 5 בקשות לאותו שירות תוך 2 שניות, הוא מקבל MAX_ITERATIONS. אנו זקוקים לניסיון חוזר עם השהיה אקספוננציאלית: ניסיון ראשון אחרי שנייה, שני אחרי 2 שניות, שלישי אחרי 4 שניות. OkHttp 429 Too Many Requests מאפשר ליישם זאת בשקיפות עבור כל הקריאות. בפרויקטים שלנו, אנו מוסיפים עד 3 ניסיונות חוזרים ומאגר חיבורים. גישה זו מפחיתה קריאות שנכשלו ב-60%.
תגובות API בלתי צפויות. API חיצוניים מחזירים נתונים בפורמטים שונים, עם קודי שגיאה שונים, ולעיתים מחזירים HTML במקום JSON במהלך תקלות תשתית. כל כלי צריך להחזיר הודעת שגיאה ברורה לסוכן, ולא לזרוק חריגה. העוזר יכול לטפל בשגיאות — אם תעביר Interceptor, הוא יעבור לחלופה.
מדוע תיאורי כלים הם החשובים ביותר?
ארכיטקטונית, כל API חיצוני הוא כלי אחד או יותר עם תיאור ברור. דוגמה ל-API להזמנת טיסות:
{ "name": "search_flights",
"description": "Ищет доступные рейсы. Используй ТОЛЬКО когда пользователь хочет найти или забронировать перелёт. Не используй для отелей или трансфера.",
"parameters": {
"origin": {"type": "string", "description": "IATA-код аэропорта отправления, например MSQ, SVO"},
"destination": {"type": "string", "description": "IATA-код аэропорта назначения"},
"date": {"type": "string", "description": "Дата в формате YYYY-MM-DD"},
"passengers": {"type": "integer", "default": 1}
}
}המילה "ONLY" בתיאור חשובה — ללא אילוצים מפורשים, המודל עלול לקרוא לכלי בהקשר לא מתאים.
עוזר בצד השרת לעומת בצד הלקוח: מה לבחור?
| מאפיין | עוזר בצד הלקוח | עוזר בצד השרת |
|---|---|---|
| מספר כלים | 2–4 | 5+ |
| אבטחת טוקנים | נמוכה (מפתחות בלקוח) | גבוהה (מפתחות בשרת) |
| המשכיות ברקע | לא | כן (באמצעות WebSocket) |
| מטמון | מוגבל | מלא |
| מורכבות יישום | 1–2 שבועות | 4–7 שבועות |
עוזר בצד השרת מאובטח פי 3 מעוזר בצד הלקוח בעת שימוש ב-5+ API, מכיוון שהטוקנים לעולם לא עוזבים את השרת. לעוזרים עם גישה ל-5+ API, שרשראות קריאה ארוכות או נתונים רגישים, אנו ממליצים על אורקסטרציה בצד השרת. הלקוח שולח את המשימה, מקבל עדכונים דרך WebSocket או long polling, ומציג התקדמות. זה מבטיח:
- המשכיות עבודת העוזר כשהאפליקציה ברקע
- שמירת תוצאות ביניים במטמון
- רישום כל שלב לצורך דיבוג
- אי חשיפת מפתחות API חיצוניים בלקוח
במובייל נשאר רק ה-UI: מחוון התקדמות של שלבי העוזר, אפשרות לביטול, וכרטיס סופי עם התוצאה ופעולת אישור.
לוחות זמנים משוערים לפיתוח עוזר AI
| מורכבות | מספר API | סוג | לוח זמנים |
|---|---|---|---|
| בסיסי | 1–2 | צד הלקוח | 2–3 שבועות |
| בינוני | 3–5 | צד השרת | 4–7 שבועות |
| מורכב | 6+ | צד השרת עם מיקרוסרביסים | 8–12 שבועות |
קוד לדוגמה ל-iOS (Swift)
// iOS - агентный цикл
func runAgent(userMessage: String) async -> String {
var messages = [Message(role: "user", content: userMessage)]
for _ in 0..<MAX_ITERATIONS {
let response = await llmClient.complete(messages, tools: availableTools)
if response.finishReason == "stop" {
return response.content ?? ""
}
if response.finishReason == "toolCalls" {
messages.append(response.toAssistantMessage())
let results = await withTaskGroup(of: (id: String, content: String).self) { group in
for call in response.toolCalls {
group.addTask {
await (call.id, toolDispatcher.dispatch(call.name, call.arguments))
}
}
var dict = [String: String]()
for await result in group {
dict[result.id] = result.content
}
return dict
}
for call in response.toolCalls {
messages.append(Message(role: "tool", toolCallId: call.id, content: results[call.id] ?? ""))
}
}
}
return "Агент не смог завершить задачу за \(MAX_ITERATIONS) шагов"
} מה כלול בעבודה
- דיאגרמת ארכיטקטורה של האינטראקציה בין אפליקציית המובייל, השרת ו-API חיצוניים
- יישום לולאת agentic עם הגנה מפני לולאות אינסופיות (MAX_ITERATIONS, מטפלי שגיאות ברירת מחדל)
- אינטגרציה עם API חיצוניים נבחרים (אימות, הגבלת קצב, ניסיונות חוזרים)
- פרוקסי בשרת לאחסון טוקנים מאובטח ורישום בקשות
- רכיבי UI להצגת התקדמות הסוכן (שלבים, סטטוסים, ביטול)
- תיעוד כלים ודוגמאות שימוש
- הוראות פריסה וניטור
- תעודת אבטחת איכות
שלבי העבודה
- ביקורת על API חיצוניים ואימותם
- עיצוב כלים וסכמות
- יישום פרוקסי בשרת (במידת הצורך)
- לולאת agentic עם הגנה מפני לולאות אינסופיות
- טיפול בהגבלות קצב וזמני קצוב
- UX להתקדמות הסוכן בלקוח
- בדיקת תרחישים עם שגיאות API
- ניטור והתראות
לוחות זמנים: עוזר עם 3–5 API חיצוניים, אורקסטרציה בצד השרת — 4–7 שבועות. עוזר בצד הלקוח עבור 2–3 API פשוטים — 2–3 שבועות. אספקה מובטחת במסגרת הזמן המשוער.
הזמינו ייעוץ עם מהנדס עוזרי AI מוסמך שלנו. צרו קשר כדי לדון בפרויקט שלכם ולקבל הערכת עלות.







