נושאים בקורס
chevron_right
Management Plane - ניהול מעגל חיים של סוכנים
chevron_right
Control Plane - הגדרת ותכיפות מדיניות
chevron_right
Data Plane - ביצוע פעולות ותקשורת
chevron_right
Security Plane - אמון ואימות
מהו מישור בקרה (Control Plane)?
מישור בקרה הוא ארכיטקטורה שנוצרה כדי לנהל וללוות מערכות מורכבות. המונח עצמו בא מרשתות תקשורת וKubernetes, אבל הוא משתלם במיוחד לסוכני AI. הרעיון הוא לחלק את המערכת לכמה "מישורים", כל אחד עם אחריות ברורה.
ארבעת המישורים הקלאסיים הם: Management (ניהול כללי), Control (קביעת כללים), Data (ביצוע בפועל), ו-Security (אבטחה). בקורס זה נתמקד בכל אחד מהם בהעמקה, וגם נראה איך הם מחוברים זה לזה. פעם אחת שתבין את ארבעת המישורים הללו, תוכל לתכנן מערכת בקרה חזקה וניתנת להרחבה עבור כמעט כל סוג של סוכנים.
Management Plane — ניהול מעגל חיים
ה-Management Plane עוסקת בשאלות ארגוניות גדולות. איך הסוכן נוצר? איך הוא משודרג? איך הוא מושבת? זה המישור שבו מנהלי מערכות וmultiple engineers מתמודדים עם lifecycle ארוך של סוכנים. כאן קיימות תיעוד פרויקטים, חלוקת משאבים, ותכנון קיבולת.
בפרט, ה-Management Plane דואגת לכך שנוכל לשדרג סוכנים בבטחה (ללא downtime), לסיים את חייהם כשהם לא נדרשים עוד, להקצות משאבים כך שלא יהיה congestion, ולנהל versions שונות של אותו סוכן בו-זמנית (כמו running v1.2 ו-v1.3 באותה עת עם gradual rollout).
// Management Plane: Lifecycle Management
class AgentLifecycleManager {
constructor() {
this.agents = new Map();
}
// Creation
createAgent(agentConfig) {
const agentId = generateUUID();
const agent = {
id: agentId,
config: agentConfig,
version: "1.0.0",
status: "created", // created, deployed, running, paused, terminated
deployedAt: null,
createdAt: new Date(),
resources: { cpu: "1", memory: "2Gi", storage: "10Gi" }
};
this.agents.set(agentId, agent);
return agentId;
}
// Versioning & Deployment
deployAgentVersion(agentId, newVersion) {
const agent = this.agents.get(agentId);
agent.version = newVersion;
agent.status = "deploying";
// Blue-Green deployment: run old and new in parallel
return {
blueDeployment: agent.version - 1,
greenDeployment: newVersion,
trafficSplit: { blue: 90, green: 10 } // Start with 10% traffic to new
};
}
// Scaling
scaleAgent(agentId, replicas) {
const agent = this.agents.get(agentId);
agent.replicas = replicas;
agent.resources.memory = `${replicas}Gi`; // Scale memory accordingly
return { agentId, replicas, memoryAllocated: agent.resources.memory };
}
// Termination
terminateAgent(agentId) {
const agent = this.agents.get(agentId);
agent.status = "terminated";
agent.terminatedAt = new Date();
// Graceful shutdown: allow in-flight requests to complete
return { agentId, status: "terminating", gracefulTimeout: "30s" };
}
}
Control Plane — הגדרת כללים ומדיניות
ה-Control Plane היא הלב של מערכת הבקרה שלנו. כאן מגדירים את הכללים והמדיניות שיסדירו את ההתנהגות של הסוכנים. זו הרמה בה מנהלי מדיניות (policy managers), security officers, ו-compliance specialists עובדים.
Control Plane מגדירה דברים כמו: "סוכן פרסום אינו רשאי להציג מודעות לקטינים", "החלטות הקשורות למכירה מעל $10,000 דורשות אישור אנושי", "סוכן לא רשאי לגשת לנתוני אשראי של לקוחות מאזור מסוים". כללים אלה מוקדשים לתוך מערכת, ובדרך כלל מומשים דרך Enforcement Engine בData Plane.
Control Plane גם מטבעה לא-סטטית. כשמדיניות משתנה (חברה משנה את מנהגה, או רגולציה חדשה נכנסת), ניתן לעדכן את הכללים בלי שצריך לעצור את כל הסוכנים. זה יתרון ענק על הקודדינג של ההגבלות ישירות לקוד הסוכן.
// Control Plane: Policy Definition Engine
class PolicyEngine {
constructor() {
this.policies = new Map();
}
// Define a policy
definePolicy(policyId, policyConfig) {
const policy = {
id: policyId,
name: policyConfig.name,
description: policyConfig.description,
scope: policyConfig.scope, // e.g., "sales_agent", "all_agents", "customer_support"
rules: policyConfig.rules, // Array of rules
enforcementMode: policyConfig.enforcementMode, // "block", "warn", "approve"
createdAt: new Date(),
updatedAt: new Date(),
version: "1.0.0"
};
this.policies.set(policyId, policy);
return policyId;
}
// Example policy
examplePolicy() {
return {
id: "pol_high_value_tx",
name: "High-Value Transaction Approval",
scope: "transactions_agent",
rules: [
{
condition: "transaction.amount > 10000",
action: "require_human_approval",
approvers: ["finance_manager", "cfo"],
timeout: "24h"
},
{
condition: "transaction.amount > 50000",
action: "block_immediately",
notifyTeam: ["compliance", "security"]
},
{
condition: "transaction.destination_country == 'restricted'",
action: "block_immediately",
reason: "Sanctions compliance"
}
],
enforcementMode: "block" // Don't even allow the transaction to proceed
};
}
// Update policy
updatePolicy(policyId, updates) {
const policy = this.policies.get(policyId);
Object.assign(policy, updates);
policy.updatedAt = new Date();
policy.version = this.incrementVersion(policy.version);
return policy;
}
// Versioning
incrementVersion(version) {
const [major, minor, patch] = version.split('.').map(Number);
return `${major}.${minor}.${patch + 1}`;
}
// Policy evaluation: Should an action be allowed?
evaluatePolicy(agentId, action, context) {
const applicablePolicies = Array.from(this.policies.values())
.filter(p => p.scope === "all_agents" || p.scope === agentId);
for (const policy of applicablePolicies) {
for (const rule of policy.rules) {
if (this.evaluateCondition(rule.condition, context)) {
return {
allowed: rule.action !== "block_immediately",
action: rule.action,
policy: policy.name,
rule: rule
};
}
}
}
return { allowed: true, reason: "No blocking policies apply" };
}
evaluateCondition(condition, context) {
// This is a simplified version; in reality, use a proper expression evaluator
return eval(condition); // In production, use a safe expression language!
}
}
lightbulb
חשוב: שפות מדיניות
כשמתכננים Control Plane, בחרו בשפה לציון מדיניות שפשוטה, מהנדסים יכולים לתחזוקה, ובעלי עסק יכולים להבין. דוגמאות: OPA/Rego, Cedar (מ-AWS), או YAML בעיצוב משלכם. הימנעו מלשפות מורכבות מדי — מדיניות צריכה להיות ברורה וקלה לביקורת.
Data Plane — ביצוע ותקשורת
ה-Data Plane היא שם חם של פעולות. כאן הסוכנים בפועל פועלים, מחשבים, וקוראים החלטות. זה גם המקום בו אנחנו מיישמים את המדיניות שהוגדרה בControl Plane. ה-Data Plane כוללת את הסוכנים עצמם, את המנוע שלהם ל-inference, ואת כל ה-APIs והשירותים שהם קוראים אליו.
בעיצוב של Data Plane, אנחנו חושבים על דברים כמו: איך הסוכן קורא ל-policy engine כדי לווידוא שהחלטתו מותרת? איך הוא תומך retractions אם הוא בחר משהו לא בסדר? איך הוא מעביר דיווח לחזרה ל-Management Plane? זה גם המקום בו אנחנו עשויים לבצע caching (כדי להאיץ דברים) ו-rate limiting (כדי להגן על משאבים).
בחירה של Data Plane צריכה לקחת בחשבון: latency (כמה מהר הסוכן צריך לפעול?), throughput (כמה סוכנים באותו זמן?), fault tolerance (מה קורה אם משהו נשבר?), ו-cost (כמה יוקר זה לשדר?). שונות כמו edge deployment (סוכנים בקרוב לנתונים) לעומת centralized (כל הסוכנים בנחלת אחד) צריכות שיקול.
Security Plane — אמון ואימות
Security Plane היא הבעיה הרביעית, אבל כמו כל אבטחה, היא אינה אפשרות — היא חובה. כאן אנחנו מטפלים בשאלות כמו: "איך נודע שהסוכן הוא באמת סוכן וקיבול לחתום על בקשות?" (Authentication), "איך נודע שלסוכן יש רשות לבצע פעולה מסוימת?" (Authorization), "איך אנחנו מנקים שגויויות?" (Audit), וגם "איך אנחנו מגנים על סוכן מפני התקפות?" (Security).
ברמה הפרקטית, Security Plane מיישמת דברים כמו: mutual TLS (mTLS) בין סוכנים והשירותים שהם קוראים אליו, API keys ו-tokens שמחדשים בקביעות, audit logs של כל החלטה שהסוכן עשה, ו-encryption של נתונים בעברות (both in transit and at rest).
חלק חשוב של Security Plane הוא גם "Sandboxing" — הפרדה בין סוכנים כך שסוכן "רע" לא יכול להשפיע על אחרים. בתוך Kubernetes, זה יכול להיות Network Policies או Pod Security Policies. בתוך LLM, זה יכול להיות הגבלת ה-functions שהסוכן רשאי לקרוא אליהן.
// Security Plane: Authentication & Authorization
class SecurityPlane {
constructor() {
this.agents = new Map();
this.permissions = new Map();
}
// Register agent with cryptographic identity
registerAgent(agentId, agentConfig) {
const agent = {
id: agentId,
publicKey: generatePublicKey(),
privateKey: generatePrivateKey(), // Stored securely (e.g., in Vault)
certificate: issueCertificate(agentId),
permissions: [],
createdAt: new Date(),
lastRotatedAt: new Date()
};
this.agents.set(agentId, agent);
return agent.publicKey;
}
// Define roles and permissions
defineRole(roleId, permissions) {
this.permissions.set(roleId, {
id: roleId,
permissions: permissions, // e.g., ["read:database", "write:api", "execute:functions"]
createdAt: new Date()
});
}
// Assign role to agent
assignRoleToAgent(agentId, roleId) {
const agent = this.agents.get(agentId);
const role = this.permissions.get(roleId);
agent.roles = agent.roles || [];
agent.roles.push(roleId);
return { agentId, roleId, permissions: role.permissions };
}
// Authenticate: Verify agent signature
authenticateRequest(agentId, request, signature) {
const agent = this.agents.get(agentId);
const isValid = verifySignature(request, signature, agent.publicKey);
if (!isValid) {
return { authenticated: false, reason: "Invalid signature" };
}
// Check if certificate is not expired
if (agent.certificate.expiresAt < new Date()) {
return { authenticated: false, reason: "Certificate expired" };
}
return { authenticated: true, agentId, roles: agent.roles };
}
// Authorize: Check if agent has permission for action
authorizeAction(agentId, action) {
const agent = this.agents.get(agentId);
const allPermissions = agent.roles
.flatMap(roleId => this.permissions.get(roleId).permissions);
const isAuthorized = allPermissions.includes(action);
return {
authorized: isAuthorized,
agentId,
action,
reason: isAuthorized ? "Permission granted" : "Permission denied"
};
}
// Audit Log
logAction(agentId, action, result, context) {
const auditEntry = {
timestamp: new Date().toISOString(),
agentId,
action,
result, // "success" or "failure"
context, // What was the request? What was the response?
ipAddress: context.ipAddress,
userId: context.userId // If human approved/initiated
};
// Store in audit database
this.storeAuditLog(auditEntry);
return auditEntry;
}
// Rotate credentials
rotateAgentCredentials(agentId) {
const agent = this.agents.get(agentId);
agent.privateKey = generatePrivateKey();
agent.publicKey = generatePublicKey();
agent.certificate = issueCertificate(agentId);
agent.lastRotatedAt = new Date();
return { agentId, newPublicKey: agent.publicKey };
}
}
// Audit Logging Example
const AuditLogEntry = {
timestamp: "2025-01-15T10:23:45Z",
agentId: "agent_sales_001",
action: "create_order",
result: "success",
context: {
orderId: "ord_12345",
amount: 5000,
customerId: "cust_67890",
approvedBy: "user_admin_001"
}
};
בסוף מודול זה תוכל:
- ✓ להסביר את ארבעת המישורים של Control Plane
- ✓ לתכנן Management Plane עם lifecycle management
- ✓ ליישם Policy Engine בControl Plane
- ✓ לעצב Data Plane עם enforcement
- ✓ להקים אמות-מידה אבטחה בSecurity Plane
4
Monitoring, Logging ו-Observability
נושאים בקורס
chevron_right
Setup של Observability Stack לסוכנים
chevron_right
Metrics חיוניות: latency, throughput, error rates
chevron_right
Distributed tracing בין סוכנים
chevron_right
Alerting ו-incident response automation
Observability vs Monitoring — הבדל חשוב
אנשים רבים משתמשים במילים "monitoring" ו"observability" כחליפה, אך הם לא בדיוק אותו הדבר. Monitoring הוא בדיקה של דברים שאתה מצפה כבר לראות — "האם ה-HTTP status 200?" או "האם CPU נמוך מ-80%?" observability הוא היכולת לשאול שאלות חדשות על מערכת שלך בלי שצריך לשנות קוד. "למה בקש זה לקח 5 שניות?" אתה יכול לחפור עומק לתוך logs ו-traces כדי להבין.
עבור סוכנים, observability קרוב יותר חשובה מ-monitoring, מכיוון שסוכנים עובדים בדרכים בלתי צפויות לפעמים. Monitoring גם חשוב, אבל בלתי שלם. זה מוקד גבוה של קורס זה.
ה-three pillars של observability הם: Metrics (מדידות מספריות), Logs (רצפי טקסט), ו-Traces (שטחות של בקשה דרך מערכת). יחד, הם נותנים לך תמונה מלאה.
// Observability Stack Setup for Agents
class ObservabilityStack {
constructor() {
this.metrics = [];
this.logs = [];
this.traces = [];
}
// Metrics Collection (using Prometheus format)
recordMetric(metricName, value, labels = {}) {
const metric = {
name: metricName,
value,
labels, // e.g., { agent_id: "agent_123", action: "classify" }
timestamp: Date.now()
};
this.metrics.push(metric);
// In real setup, send to Prometheus
console.log(`METRIC: ${metricName} = ${value}`, labels);
}
// Key Metrics for AI Agents
recordAgentMetrics(agentId, context) {
// Latency: How long did the agent take?
this.recordMetric("agent.latency_ms", context.duration, {
agent_id: agentId,
action: context.action
});
// Throughput: How many requests per second?
this.recordMetric("agent.requests_per_second", context.rps, {
agent_id: agentId
});
// Error Rate: What percentage failed?
this.recordMetric("agent.error_rate", context.errorRate, {
agent_id: agentId
});
// Token Usage: How many tokens did the LLM use?
if (context.tokensUsed) {
this.recordMetric("agent.tokens_used", context.tokensUsed, {
agent_id: agentId,
model: context.model
});
}
// Decision Time: How long to make a decision?
this.recordMetric("agent.decision_time_ms", context.decisionTime, {
agent_id: agentId
});
// Approval Rate: How many decisions needed human approval?
this.recordMetric("agent.approval_rate", context.approvalRate, {
agent_id: agentId
});
}
// Structured Logging
log(level, message, context = {}) {
const logEntry = {
timestamp: new Date().toISOString(),
level, // "info", "warn", "error", "debug"
message,
context, // Add structured data
traceId: context.traceId // Link to trace
};
this.logs.push(logEntry);
console.log(JSON.stringify(logEntry));
}
// Distributed Tracing: Track a request through multiple services
createTrace(traceId, requestId) {
return {
traceId,
requestId,
spans: [],
startTime: Date.now()
};
}
addSpan(trace, spanName, startTime, endTime, attributes = {}) {
trace.spans.push({
name: spanName,
startTime,
endTime,
duration: endTime - startTime,
attributes
});
}
exampleTrace() {
const traceId = "trace_12345";
const requestId = "req_67890";
const trace = this.createTrace(traceId, requestId);
// Span 1: Agent receives request
this.addSpan(trace, "agent.receive_request", 0, 10, {
agent_id: "agent_sales_001",
action: "classify_lead"
});
// Span 2: Agent calls LLM
this.addSpan(trace, "llm.inference", 10, 250, {
model: "gpt-4o",
tokens: 150
});
// Span 3: Agent evaluates policy
this.addSpan(trace, "policy.evaluate", 250, 270, {
policy_id: "pol_lead_quality"
});
// Span 4: Agent writes to database
this.addSpan(trace, "database.write", 270, 290, {
table: "leads",
operation: "insert"
});
// Span 5: Agent sends response
this.addSpan(trace, "agent.send_response", 290, 300, {
status: "success"
});
return trace;
}
}
// Example Metrics
const KeyAgentMetrics = {
latency: "How long until the agent responds?",
throughput: "How many requests per second?",
error_rate: "What % of requests fail?",
token_usage: "How many LLM tokens consumed?",
decision_time: "Time to make a decision (excluding I/O)",
policy_violations: "How many times was a policy violated?",
approval_rate: "What % of decisions needed human approval?",
cost_per_request: "Average cost per request (tokens, compute)",
hallucination_rate: "What % of responses had hallucinations?"
};
Distributed Tracing בין סוכנים
כשיש לך סוכנים מרובים שעובדים ביחד (multi-agent systems), ישנה סכנה שבקשה תחליק ביניהם בלא שיודע. Distributed tracing עוזרת לעקוב אחרי בקשה כשהיא עוברת מסוכן לסוכן, שירות לשירות. כל קטע של העבודה מתויג כ"span", וביחד הם יוצרים "trace".
כלים כמו Jaeger ו-Zipkin הם קלאסיים. הם מסתכלים בכל ה-spans ויוצרים waterfall diagram שמראה היכן בזבזו זמן. "אה, סוכן A קרא לסוכן B, וסוכן B חכה 3 שניות לתשובה מAPI חיצוני" — דברים כאלה קלים לראות בtraces.
OpenTelemetry היא התקן הקדום כיום. זה ספרייה שמקלה על שליחה של metrics, logs, וtraces לכל destination (Datadog, New Relic, Prometheus, וכו'). זה מסיר coupling בין קוד שלך לבין observability backend.
Alerting ו-Incident Response
ניטור הוא טוב, אבל אם אתה לא תגיד לאדם על בעיה, מה התועלת? Alerting היא המקום שבו metrics הופכות לפעולה. אתה מגדיר rules: "אם error rate עלה מעל 5%, שלח לי Slack". "אם latency p95 גבוה מ-1 שנייה, פתח issue ב-GitHub". "אם agent crashed 3 פעמים ברציפות, trigger ל-PagerDuty וגרום למהנדס לעירור מהשינה".
incident response automation פירוש שהמערכת עושה דברים בעצמה כשמשהו נשבר. "Error rate גבוה? בואו נחזור לגרסה הישנה." "Latency גבוה? בואו נשדרג." "Agent crashed? בואו נתחיל מחדש." זה מקטין את MTTR (Mean Time To Recovery) — כמה מהר אתה חוזר לנורמל.
כלים כמו Prometheus Alertmanager, Datadog, ו-PagerDuty משמשים. אבל החשוב ביותר הוא להגדיר alerts שיותר אינטליגנטיים — לא "trigger on every anomaly" (כי אחרי כן תתרגל להם), אלא "trigger only if this is bad enough to require human action".
lightbulb
Alert Fatigue
אם יש לך יותר מדי alerts, מהנדסים יתחילו להתעלם מהם (הידע כ-"alert fatigue"). הקפד על איכות alerts: trigger רק אם זה באמת חשוב, תן context מהיר (מה קרה? למה זה רע?), ותן טיפים לפתרון ("spikes usually resolve themselves in 2-3 minutes, או "check XYZ for common issues").
בסוף מודול זה תוכל:
- ✓ להקים observability stack עם metrics, logs, וtraces
- ✓ להגדיר KPIs עבור סוכני AI
- ✓ להשתמש בdistributed tracing לdebug multi-agent systems
- ✓ לכתוב alerts חכמים וייעודיים
- ✓ לבנות incident response playbooks