Notes pratiques : Création d’un système de détection des fraudes par agents prêt pour la production
Guide opérationnel des notes pratiques : Création d’un système de détection de la fraude agentic prêt pour la production : contrats, vérifications et emplacements de code à insérer pour les équipes qui déploient ce modèle.
Ce guide reconstitue le parcours allant des matières premières à un système opérationnel pour : Construire un système de détection de fraude agissant prêt à la production — Partie 1 : La vue d’ensemble. L’accent est mis sur des étapes exécutables, des vérifications explicites et du code que vous pouvez intégrer directement dans un dépôt sans devoir deviner l’intention derrière lui. Pour l’étape d’aperçu, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans avoir à deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définissez des vérifications de succès et refusez toute complétion partielle silencieuse.
La nature du problème
Lorsque vous travaillez sur « The shape of the stage », notez d’abord les exigences : données requises, signal de succès, et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés. Créez un point de contrôle après chaque étape coûteuse. Le système de reprise ne doit pas facturer à nouveau la même appel d’LLM lorsque l’opérateur réessaie un nœud ultérieur.
Aperçu du système
Lors de la phase d’aperçu du système, notez d’abord les exigences du contrat : entrées requises, signal de succès et comportement en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Créez des points de contrôle après les étapes coûteuses. Le mécanisme de reprise ne doit pas facturer à nouveau la même appel du LLM lorsque l’opérateur réessaie un nœud ultérieur.
Orchestration agente — Évaluation en temps réel de la fraude
Lors du travail sur l’étape d’orchestration agente en temps réel, notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations apportées ultérieurement. Créez un point de contrôle après les étapes coûteuses. Le système de reprise ne doit pas facturer à nouveau la même appel du LLM lorsque l’opérateur tente à nouveau un nœud ultérieur.
Agent A — scoring de propension (le modèle entraîné)
Lors de l’étape d’évaluation des probabilités pour l’Agent A, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de maintenir l’honnêteté des modifications ultérieures du code. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité et non un processus embrouillé. Cachez les instructions système stables ainsi que les schémas des outils. Envoyer à nouveau un préambule identique est une cause fréquente de surcharge.
Agent B — évaluation comportementale (pas de modèle du tout)
Lors de l’étape d’évaluation comportementale de l’Agent B, notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès, et refusez toute exécution partielle silencieuse. Cachez les instructions système stables ainsi que les schémas des outils. L’envoi répété d’un préambule identique est une cause fréquente de problèmes.
Agent C — récupération de politiques via pgvector
Lors de l’étape de récupération des politiques Agent C, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le système passe de l’environnement de démonstration à des environnements partagés. Mesurez le taux de rappel sur un ensemble fixe de questions avant d’ajuster les prompts. Changer fréquemment les prompts ne résout que rarement un système de récupération insuffisant.
L’ingénierie au service du projet : les éléments absents de la fiche du modèle
Lors du travail sur l’ingénierie des composants dans Harness, notez d’abord les spécifications : entrées requises, signal de succès, et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Mémorisez les instructions stables du système ainsi que les schémas des outils. L’envoi répété d’un préambule identique est une cause fréquente de surconsommation.
"""
SessionMemory — the public interface tying working memory (short-term) and
episodic memory (long-term, cross-session) together for context engineering.
mem = SessionMemory() # new session, fresh UUID
mem.remember("user", "...") # auto-persists to pgvector
mem.remember("assistant", "...")
context = mem.build_context(next_question) # summary + recent turns + relevant past episodes
mem.end_session() # finalize into episodic_memory
"""
"""
In-memory semantic cache in front of episodic recall.
Two layers:
- exact-string embedding cache: a literal repeat query skips the OpenAI
embeddings API call entirely.
- semantic result cache: a near-duplicate query (different wording, same
intent) still needs embedding to compare, but skips the Postgres/pgvector
round-trip if it's cosine-similar enough to something already cached.
Process-local only (not shared across workers/processes) — fine for a
single running service, not a substitute for a distributed cache if this
ever runs behind multiple instances.
Must be invalidated when a new episode is saved: a cached "no good match" or
partial result set can go stale the moment the underlying corpus changes.
"""
"""
Fraud-detection event chain, built on the generic pub-sub bus in
common/pubsub.py:
UserQueryEvent
-> InputGuardrailService -> InputGuardrailPassedEvent | InputGuardrailBlockedEvent
-> OrchestrationService -> OrchestrationCompletedEvent | OrchestrationPausedHITLEvent
-> OutputGuardrailService -> OutputGuardrailPassedEvent | OutputGuardrailBlockedEvent
-> ResultPublisher -> PipelineCompletedEvent
HumanDecisionEvent (resumes a run paused at OrchestrationPausedHITLEvent)
-> OrchestrationService -> ... (same chain onward)
Each service subscribes to exactly one (or two, for resume) event type and
publishes the next event in the chain — a new listener (audit logger,
LangSmith exporter) can subscribe to any event without touching the
publishers. The guardrail/graph calls underneath are synchronous
(psycopg2, HF/OpenAI SDKs); handlers run them via asyncio.to_thread so a
slow call doesn't block the event loop for other in-flight events.
"""
@mcp.tool()
@guarded(action="score_transaction")
def score_propensity(features: dict[str, float], role: str) -> float:
"""Score one transaction's V1-V28 features for ML fraud probability (0-1). Agent A.
Requires role: analyst or admin."""
return score_customer_propensity(features)
@mcp.tool()
@guarded(action="score_transaction")
def score_behavior(customer_id: int, amount: float, category: str, merchant: str, role: str) -> dict:
"""Score one transaction's behavior anomaly vs its category's peer-cohort stats. Agent B.
Requires role: analyst or admin."""
return score_customer_behavior(customer_id, amount, category, merchant)
@mcp.tool()
@guarded(action="chat_query", free_text_arg="query")
def consult_fraud_policy(query: str, role: str, k: int = 3) -> list[dict]:
"""Semantic search over the indexed credit-card policy/handbook documents. Agent C.
Requires role: viewer or higher. `query` is scanned for prompt injection/jailbreak and PII."""
return consult_policy(query, k=k)
if __name__ == "__main__":
mcp.run()
JWT_SECRET_KEY = os.environ["JWT_SECRET_KEY"]
JWT_ALGORITHM = os.environ.get("JWT_ALGORITHM", "HS256")
JWT_EXPIRE_MINUTES = int(os.environ.get("JWT_EXPIRE_MINUTES", "30"))
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password: str) -> str:
return pwd_context.hash(password)
def get_user(username: str) -> dict | None:
conn = get_connection()
try:
with conn.cursor() as cur:
cur.execute("SELECT * FROM users WHERE username = %s", (username,))
return cur.fetchone()
finally:
conn.close()
def authenticate_user(username: str, password: str) -> dict | None:
user = get_user(username)
if not user or user["disabled"]:
return None
if not verify_password(password, user["hashed_password"]):
return None
return user
Observabilité
Lors de la phase d’Observabilité, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle garantit l’honnêteté des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations ultérieures. Faites un point après les étapes coûteuses. Le système de reprise ne doit pas facturer à nouveau la même appel d’LLM lorsque l’opérateur réessaie un nœud ultérieur. Lors de la phase d’Observabilité, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle garantit l’honnêteté des modifications ultérieures du code. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez les terminations partielles silencieuses.
Déploiement sur AWS et l’interface utilisateur
L’implémentation AWS et les étapes associées fonctionnent le mieux lorsqu’elles sont considérées comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et des notes de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Gardez l’état des graphes simple et structuré. Les blocs imbriqués masquent l’identité du nœud qui a modifié tel champ, ce qui perturbe la reprise après interruption.
Que faire ensuite
La phase « Que faire ensuite » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre.
Liste de contrôle opérationnelle
La phase de liste de contrôle opérationnelle fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre.
Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’erreur doit indiquer une seule responsabilité plutôt qu’un processus embrouillé.
Gardez l’état du graphe plat et typé. Les blocs imbriqués cachent le fait que tel nœud a écrit telle champ et empêchent la reprise après interruption.
Ajoutez un test de base qui met à l’épreuve le chemin critique dans les processus d’intégration continue en utilisant des fixtures, et non des API payantes en temps réel, chaque fois que le budget le permet.
Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des critères de succès et refusez toute complétion partielle silencieuse.
Gardez l’état du graphe plat et typé. Les blocs imbriqués cachent le fait que tel nœud a écrit telle champ et empêchent la reprise après interruption.
Au préalable de promouvoir la pile logicielle, figez les versions, conservez une transcription exemplaire du chemin critique et confirmez les étapes de rollback. Les environnements partagés nécessitent des limites de débit, des vérifications de location et un responsable clair pour la rotation des secrets. Préférez une fiabilité solide à des démonstrations brillantes mais ponctuelles.
Note de lot pour 5d0d59733252 : ne pas inclure les clés du fournisseur dans le répertoire, fixer une limite pour les tokens par session, et stocker les transcriptions à côté des fichiers de test afin que les remplacements ultérieurs de modèles restent comparables.
Lors du travail sur l’étape 0 de la note de renforcement de sécurité, écrivez d’abord le cahier des charges : entrées requises, signal de succès, et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé.
Détail de renforcement de sécurité 0/721 : mesurez le temps d’exécution, la classe d’erreur et l’utilisation des tokens pour cette note, puis décidez si vous souhaitez conserver la modification en vous basant sur un ensemble de questions prédéfini plutôt que sur des observations subjectives.
La première étape de la note de renforcement fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Notez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite des factures inattendues lorsque le processus passe de l’environnement de démonstration à des environnements partagés.
Détail de renforcement 1/721 : mesurez le temps d’exécution, la catégorie de l’erreur et la consommation de jetons pour cette note, puis décidez si vous souhaitez conserver la modification en vous basant sur un ensemble de questions prédéfini plutôt que sur des observations subjectives.
Pour la deuxième étape de la note de renforcement, définissez les entrées, le responsable de l’étape et les critères d’achèvement avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez conjointement le parcours optimal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure.
Détail de renforcement 2/721 : mesurez le temps d’exécution, la classe d’erreur et la consommation de tokens pour cette note, puis décidez si vous souhaitez conserver le changement en vous basant sur un ensemble de questions prédéfini plutôt que sur des anecdotes.
Lorsque vous travaillez sur la troisième étape de la note de renforcement, écrivez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’honnêteté des modifications de code ultérieures. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définez les vérifications de succès et refusez toute exécution partielle silencieuse.
Détail de renforcement 3/721 : mesurez le temps d’exécution, la classe d’erreur et la consommation de tokens pour cette note, puis décidez si vous souhaitez conserver le changement en vous basant sur un ensemble de questions prédéfini plutôt que sur des anecdotes.
La phase 4 des notes de renforcement fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Conservez les configurations en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système.
Détail de renforcement 4/721 : mesurez le temps d’exécution, la classe d’erreur et l’utilisation des tokens pour cette note, puis décidez s’il convient de conserver la modification en vous basant sur un ensemble fixe de critères plutôt que sur des observations subjectives.