Lumen × LangGraph × Kova
Objectif : faire passer le Checkpointer d’un Agent LangGraph de SqliteSaver à LumenCheckpointer, le déployer sur Kova et observer la comparaison de récupération après crash.
Avant / Après
Mono-machine, sans sauvegarde distante · verrouillage requis entre processus · récupération après crash de l’ordre de la milliseconde · aucun suivi des coûts.
Récupération après crash de l’ordre de la microseconde (moteur WAL de Kova) · sécurité multi-processus native · Trace + Cost automatiques · persistance distante.
Avant
from langgraph.checkpoint.sqlite import SqliteSaver
graph = wf.compile(checkpointer=SqliteSaver.from_conn_string("./state.db"))Après
from lumen_ai import LumenCheckpointer, LumenTracer
from kova import KovaClient
kova = KovaClient("kova://prod-cluster")
graph = wf.compile(
checkpointer=LumenCheckpointer(kova_client=kova),
callbacks=[LumenTracer()],
)Validation locale
Démarrer Kova en local
bashdocker run -d --name kova -p 9999:9999 ghcr.io/hanmahong5-arch/kova:latestExécuter votre Agent
bashpython my_agent.pySimuler un crash
bashkill -9 $(pgrep -f my_agent)Redémarrer — reprise depuis le point d’interruption
bashpython my_agent.py
Déployer sur Kova
# agent.yaml
name: my-research-agent
entry: python my_agent.py
replicas: 3
checkpointer: lumen
wal:
retention: 7dlumen deploy --target kova://prod-clusterExpérience comparative de récupération après crash
| Indicateur | SqliteSaver | Lumen + Kova |
|---|---|---|
| Latence de récupération | 8 ms (mono-machine) | niveau microseconde |
| Multi-réplicas | verrouillage supplémentaire requis | natif |
| Multi-datacenter | copie manuelle | réplication asynchrone intégrée |
| Réappel LLM | réappel si l’écriture SQLite échoue | jamais de réappel |
| Trace | aucune | corrélation automatique |
D’où vient la récupération en microsecondes
La latence d’ordonnancement du moteur Kova descend jusqu’à 3 μs (pipeline FIFO complet, benchmark Criterion à 3,17 μs, 315 K ops/s). LumenCheckpointer confie l’écriture des checkpoints de LangGraph au WAL de Kova — la récupération passe par un rejeu WAL au niveau du moteur plutôt que par un fichier SQLite, d’où un niveau microseconde, bien plus rapide que la milliseconde d’un SQLite mono-machine.