Sürekli Çalışan Aracı Tasarım Örüntüleri
Arka plan işlemleri, arka plan aracıları ve kalıcı bağlantı yönetimi.
Sürekli Çalışan Aracı Tasarım Örüntüleri, CoddyKit'te ücretsiz bir AI Agents dersidir. Bu, 4 dersinin 1. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, AI Agents öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. AI Agents kursu toplamda 4 dersten oluşur.
Sürekli Çalışan Ajan Nedir?
Sürekli çalışan ajan, arka plan hizmeti olarak kesintisiz çalışır; olayları bekler ve proaktif olarak harekete geçer. İstek-yanıt ajanlarının aksine etkileşimler arasında çalışmaya devam eder ve zaman içinde durumunu korur.
Arka Plan Süreci Kalıbı
Arka plan süreci, herhangi bir terminal oturumundan bağımsız olarak çalışır. Terminal kapandıktan sonra ajanın çalışmaya devam etmesi için Python'ın arka plan iş parçacıklarını veya bir süreç yöneticisini kullanın.
import threading
import time
import signal
import sys
shutdown_flag = threading.Event()
def agent_main_loop():
print('Agent daemon started')
while not shutdown_flag.is_set():
try:
# Agent work: check for events, process tasks
perform_agent_cycle()
shutdown_flag.wait(timeout=60) # Sleep 60s, wakes on shutdown
except Exception as e:
print(f'Agent loop error: {e}')
shutdown_flag.wait(timeout=5) # Brief pause on error
print('Agent daemon stopped')
def perform_agent_cycle():
print(f'Agent cycle at {time.strftime("%H:%M:%S")}')
# Check emails, process queue, run scheduled tasks
def handle_signal(signum, frame):
print(f'Signal {signum} received, shutting down...')
shutdown_flag.set()
# Register signal handlers for graceful shutdown
signal.signal(signal.SIGTERM, handle_signal)
signal.signal(signal.SIGINT, handle_signal)
# Start as daemon thread
thread = threading.Thread(target=agent_main_loop, daemon=True)
thread.start()
print('Agent running in background')Gözetleyici: Çökmede Otomatik Yeniden Başlatma
Bir gözetleyici, ajan sürecini izler ve süreç çökerse yeniden başlatır. Bu, üretim ortamı için gereklidir: ajanlar kaçınılmaz olarak beklenmeyen hatalarla karşılaşır ve otomatik olarak toparlanmalıdır.
import subprocess
import time
import logging
logger = logging.getLogger('watchdog')
class AgentWatchdog:
def __init__(self, agent_script: str, max_restarts: int = 10, restart_delay: float = 5.0):
self.agent_script = agent_script
self.max_restarts = max_restarts
self.restart_delay = restart_delay
self.restart_count = 0
self.process = None
def start(self):
self.process = subprocess.Popen(
['python', self.agent_script],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
logger.info(f'Agent started (PID: {self.process.pid})')
def run_forever(self):
self.start()
while True:
return_code = self.process.wait()
logger.warning(f'Agent exited with code {return_code}')
if self.restart_count >= self.max_restarts:
logger.error(f'Max restarts ({self.max_restarts}) reached. Stopping watchdog.')
break
self.restart_count += 1
logger.info(f'Restarting agent (attempt {self.restart_count})...')
time.sleep(self.restart_delay * self.restart_count) # Backoff
self.start()
print('AgentWatchdog defined')Kalıcı WebSocket Bağlantısı
Gerçek zamanlı olay iletimi için kalıcı bir WebSocket bağlantısı sürdürün. Bağlantı koparsa otomatik olarak yeniden bağlanın — sürekli çalışan ajanların en önemli zorluğu budur.
import asyncio
import websockets
import json
async def persistent_websocket_connection(uri: str, on_message):
backoff = 1
max_backoff = 60
while True: # Reconnect forever
try:
print(f'Connecting to {uri}')
async with websockets.connect(uri, ping_interval=30, ping_timeout=10) as ws:
print('WebSocket connected')
backoff = 1 # Reset backoff on successful connection
async for raw_message in ws:
try:
message = json.loads(raw_message)
await on_message(message)
except json.JSONDecodeError:
print(f'Invalid JSON message: {raw_message[:100]}')
except websockets.exceptions.ConnectionClosed as e:
print(f'WebSocket closed: {e}. Reconnecting in {backoff}s')
except Exception as e:
print(f'WebSocket error: {e}. Reconnecting in {backoff}s')
await asyncio.sleep(backoff)
backoff = min(backoff * 2, max_backoff) # Exponential backoff
async def handle_ws_message(message: dict):
print(f'Received: {message}')
print('Persistent WebSocket connection function defined')Canlılık Denetimleri
Canlılık sinyali, ajanın çalışır durumda olduğunu ve işlemleri yürüttüğünü doğrular. Her N saniyede bir canlılık sinyali gönderin; canlılık sinyalleri durursa gözetleyici ajanın takıldığını veya çalışmadığını anlar.
import threading
import time
from datetime import datetime
class HeartbeatMonitor:
def __init__(self, max_silence_seconds: int = 300):
self.last_heartbeat = datetime.utcnow()
self.max_silence = max_silence_seconds
self.lock = threading.Lock()
def beat(self):
with self.lock:
self.last_heartbeat = datetime.utcnow()
def is_alive(self) -> bool:
with self.lock:
silence = (datetime.utcnow() - self.last_heartbeat).total_seconds()
return silence < self.max_silence
def silence_seconds(self) -> float:
with self.lock:
return (datetime.utcnow() - self.last_heartbeat).total_seconds()
monitor = HeartbeatMonitor(max_silence_seconds=60)
def agent_with_heartbeat():
while not shutdown_flag.is_set():
# Send heartbeat at start of each cycle
monitor.beat()
# Do agent work
perform_agent_cycle()
time.sleep(30)
# External watchdog checks the monitor
def watchdog_check():
while True:
if not monitor.is_alive():
print(f'ALERT: Agent silent for {monitor.silence_seconds():.0f}s')
# Restart agent here
time.sleep(30)
print('Heartbeat monitor defined')Düzgün Kapanma
Düzgün kapanma, durmadan önce devam eden çalışmaları tamamlar. Ajan bir durdurma sinyali alır, yeni çalışmaların başlamasını engeller, geçerli görevleri tamamlar, durumu kaydeder ve temiz bir şekilde çıkar.
import signal
import threading
from contextlib import contextmanager
class GracefulShutdown:
def __init__(self, timeout: float = 30.0):
self.should_stop = threading.Event()
self.active_tasks = 0
self.lock = threading.Lock()
self.timeout = timeout
signal.signal(signal.SIGTERM, self._handle_signal)
signal.signal(signal.SIGINT, self._handle_signal)
def _handle_signal(self, signum, frame):
print(f'Shutdown signal received. Waiting for {self.active_tasks} active tasks...')
self.should_stop.set()
@contextmanager
def task(self):
if self.should_stop.is_set():
raise RuntimeError('Shutdown in progress, not accepting new tasks')
with self.lock:
self.active_tasks += 1
try:
yield
finally:
with self.lock:
self.active_tasks -= 1
def wait_for_all_tasks(self):
self.should_stop.wait()
deadline = time.time() + self.timeout
while self.active_tasks > 0 and time.time() < deadline:
time.sleep(0.1)
if self.active_tasks > 0:
print(f'WARNING: Forced shutdown with {self.active_tasks} tasks still active')
shutdown = GracefulShutdown(timeout=30)
print('Graceful shutdown manager created')Bağlantı Kesilmelerini ve Yeniden Bağlanmaları Yönetme
Sürekli çalışan ajanların hizmet bağlantılarının kesilmesini yönetmek için stratejilere ihtiyacı vardır: kesinti sırasında olayları arabelleğe alın, yeniden bağlandıktan sonra kaçırılan olayları yeniden oynatın ve bağlantı kesikken gelen olayların kaybolmasını önleyin.
import asyncio
import redis
from datetime import datetime
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
class DisconnectHandler:
def __init__(self, buffer_key: str = 'agent:offline_buffer'):
self.buffer_key = buffer_key
self.connected = True
def on_disconnect(self):
self.connected = False
print(f'Disconnected at {datetime.utcnow()}')
def on_reconnect(self):
self.connected = True
print(f'Reconnected at {datetime.utcnow()}')
self.replay_buffered_events()
def handle_event(self, event: dict):
if not self.connected:
# Buffer events for later replay
import json
r.lpush(self.buffer_key, json.dumps(event))
print(f'Event buffered (offline): {event["type"]}')
return
self.process_event(event)
def replay_buffered_events(self):
import json
replayed = 0
while True:
raw = r.rpop(self.buffer_key)
if not raw:
break
event = json.loads(raw)
self.process_event(event)
replayed += 1
if replayed:
print(f'Replayed {replayed} buffered events')
def process_event(self, event: dict):
print(f'Processing event: {event["type"]}')
handler = DisconnectHandler()
print('Disconnect handler created')systemd ile Süreç Yönetimi
Linux üretim dağıtımları için ajan sürecini yönetmek üzere systemd kullanın. systemd otomatik yeniden başlatmayı, journald günlüklemesini ve sistem açılışında ajanı başlatmayı yönetir.
# /etc/systemd/system/my-agent.service
SERVICE_FILE = '''
[Unit]
Description=My AI Agent Service
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/agent
ExecStart=/home/ubuntu/venv/bin/python agent.py
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
# Environment variables
EnvironmentFile=/home/ubuntu/agent/.env
# Resource limits
MemoryLimit=1G
CPUQuota=50%
[Install]
WantedBy=multi-user.target
'''
# Deploy commands:
# sudo cp my-agent.service /etc/systemd/system/
# sudo systemctl daemon-reload
# sudo systemctl enable my-agent
# sudo systemctl start my-agent
# sudo systemctl status my-agent
# sudo journalctl -u my-agent -f # Follow logs
print('Systemd service configuration defined')
print('Enables: auto-start on boot, auto-restart on crash, centralized logging')Yeniden Başlatmalar Arasında Durumu Kalıcı Kılma
Sürekli çalışan bir ajan, yeniden başlatıldıktan sonra kaldığı yerden devam edebilmek için durumunu kaydetmelidir. Kontrol noktası verilerini düzenli aralıklarla ve önemli durum değişikliklerinden sonra diske veya Redis'e kaydedin.
import json
import os
from datetime import datetime
CHECKPOINT_FILE = '/tmp/agent_checkpoint.json'
def save_checkpoint(state: dict):
state['last_saved'] = datetime.utcnow().isoformat()
with open(CHECKPOINT_FILE, 'w') as f:
json.dump(state, f, indent=2)
print(f'Checkpoint saved at {state["last_saved"]}')
def load_checkpoint() -> dict:
if not os.path.exists(CHECKPOINT_FILE):
print('No checkpoint found, starting fresh')
return {}
with open(CHECKPOINT_FILE) as f:
state = json.load(f)
print(f'Checkpoint loaded from {state.get("last_saved", "unknown")}')
return state
# Agent startup
agent_state = load_checkpoint()
last_processed_id = agent_state.get('last_processed_email_id', 0)
print(f'Resuming from email ID: {last_processed_id}')
# After processing each email
agent_state['last_processed_email_id'] = last_processed_id + 1
if agent_state['last_processed_email_id'] % 10 == 0: # Checkpoint every 10 items
save_checkpoint(agent_state)Sürekli Çalışan Ajanları İzleme
Sürekli çalışan ajanlar için temel ölçümleri takip edin: çalışma süresi, saatte işlenen olay sayısı, hata oranı, bellek kullanımı ve son etkinlik zamanı. Bu ölçümleri bir sağlık uç noktası üzerinden sunun veya bir izleme hizmetine gönderin.
from fastapi import FastAPI
from datetime import datetime
import psutil
import os
app = FastAPI()
start_time = datetime.utcnow()
events_processed = 0
last_event_time = None
@app.get('/health')
def health_check():
process = psutil.Process(os.getpid())
uptime_seconds = (datetime.utcnow() - start_time).total_seconds()
last_active = None
if last_event_time:
last_active = (datetime.utcnow() - last_event_time).total_seconds()
return {
'status': 'ok',
'uptime_seconds': round(uptime_seconds),
'events_processed': events_processed,
'memory_mb': round(process.memory_info().rss / 1024 / 1024, 1),
'cpu_percent': process.cpu_percent(interval=1),
'last_event_seconds_ago': round(last_active) if last_active else None,
'timestamp': datetime.utcnow().isoformat()
}Harici Bağımlılıklar için Devre Kesici
Sürekli çalışan bir ajan, arızalanabilecek harici hizmetlerle etkileşime girer. Bir devre kesici, arızalı bir hizmete belirli bir süre boyunca çağrı yapılmasını durdurarak zincirleme arızaları önler.
import time
from enum import Enum
class CircuitState(Enum):
CLOSED = 'closed' # Normal operation
OPEN = 'open' # Service down, not calling
HALF_OPEN = 'half_open' # Testing if service recovered
class CircuitBreaker:
def __init__(self, failure_threshold=5, recovery_timeout=60):
self.state = CircuitState.CLOSED
self.failure_count = 0
self.threshold = failure_threshold
self.recovery_timeout = recovery_timeout
self.last_failure_time = None
def call(self, fn, *args):
if self.state == CircuitState.OPEN:
if time.time() - self.last_failure_time > self.recovery_timeout:
self.state = CircuitState.HALF_OPEN
else:
raise RuntimeError('Circuit open: service unavailable')
try:
result = fn(*args)
if self.state == CircuitState.HALF_OPEN:
self.state = CircuitState.CLOSED
self.failure_count = 0
print('Circuit closed: service recovered')
return result
except Exception as e:
self.failure_count += 1
self.last_failure_time = time.time()
if self.failure_count >= self.threshold:
self.state = CircuitState.OPEN
print(f'Circuit opened after {self.failure_count} failures')
raise
circuit = CircuitBreaker(failure_threshold=3, recovery_timeout=30)
print('Circuit breaker created')Bilgi Kontrolü: Sürekli Çalışan Ajanlar
Sürekli çalışan ajan tasarım kalıplarını anlayıp anlamadığınızı kontrol edin.
Sürekli Çalışan Tasarım Kalıplarının Özeti
Güvenilir sürekli çalışan ajanlar şunları bir araya getirir: temiz kapanma için sinyal yönetimine sahip arka plan süreçleri, çökme durumunda otomatik yeniden başlatma için gözetleyiciler, üstel geri çekilmeyle yeniden bağlanan kalıcı WebSocket bağlantıları, takılmış süreçleri algılamak için canlılık denetimleri, devam eden çalışmaları tamamlamak için düzgün kapanma ve yeniden başlatma sonrasında devam edebilmek için durum kontrol noktalarının kaydedilmesi. Üretim ortamında süreç yönetimi için systemd veya supervisord kullanın.
Sıkça Sorulan Sorular
“Sürekli Çalışan Aracı Tasarım Örüntüleri” dersi ücretsiz mi?
Evet — “Sürekli Çalışan Aracı Tasarım Örüntüleri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve AI Agents kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. AI Agents kursu toplamda 4 dersten oluşur.
“Sürekli Çalışan Aracı Tasarım Örüntüleri” dersinde ne öğreneceğim?
Arka plan işlemleri, arka plan aracıları ve kalıcı bağlantı yönetimi. AI Agents ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
AI Agents öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te AI Agents, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 1. dersidir.
“Sürekli Çalışan Aracı Tasarım Örüntüleri” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu AI Agents dersinde kod yazıp çalıştırabilir miyim?
Evet. Her AI Agents dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Sürekli Çalışan Aracı Tasarım Örüntüleri
- Proaktif Bildirim ve Uyarı Sistemleri
- Oturumlar Arasında Bağlamı Kalıcı Hâle Getirme
- Günlük Bilgilendirme Aracısı Oluşturma