Notas prácticas: Cómo crear un sistema de detección de fraudes basado en agentes listo para producción.
Guía paso a paso para utilizar las notas prácticas: Cómo crear un sistema de detección de fraudes basado en agentes listo para producción: contratos, verificaciones y espacios para código adicional para los equipos que implementan este modelo.
Esta guía reconstruye el proceso desde las materias primas hasta un sistema funcional para: Construir un sistema de detección de fraudes basado en agentes listo para producción — Parte 1: La visión general. El enfoque está en pasos operativos, verificaciones explícitas y código que se puede incorporar a un repositorio sin tener que adivinar su propósito. En la etapa de visión general, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Considere esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace las completaciones parciales silenciosas.
La forma del problema
Al trabajar en “The shape of the stage”, anote primero el contrato: los datos necesarios, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la versión de demostración a entornos compartidos. Haga una verificación después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior.
Visión general del sistema
Al trabajar en la fase de visión general del sistema, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Guarde la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben encontrarse en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema. Haga un punto de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intente nuevamente un nodo posterior.
Orquestación agente: puntuación en tiempo real de fraudes
Al trabajar en la etapa de Orquestación Agente en Tiempo Real, primero anote el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Documente junto con ello el camino óptimo y el camino de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Haga un punto de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador vuelve a intentar un nodo posterior.
Agente A: puntuación de propensión (el modelo entrenado)
Al trabajar en la fase de puntuación de propensión del Agente A, anote primero el contrato: los datos de entrada requeridos, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación ayuda a mantener honestos los cambios posteriores en el código. Prefiera unidades pequeñas y probables sobre scripts extensos. Cuando un paso falla, el fallo debe apuntar a una sola responsabilidad y no a un proceso complicado. Almacene en caché las instrucciones del sistema estables y los esquemas de las herramientas. Reenviar un preámbulo idéntico es una causa común de sobrecarga.
Agente B: puntuación conductual (sin modelo alguno)
Al trabajar en la fase de puntuación del comportamiento del Agente B, anote primero el contrato: los datos necesarios, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Trate esta fase como un contrato entre los datos de entrada y las salidas validadas. Asigne nombres a los artefactos, defina las comprobaciones de éxito y rechace las completaciones parciales silenciosas. Almacene en caché las instrucciones del sistema estables y los esquemas de las herramientas. Reenviar un preámbulo idéntico es una causa común de agotamiento.
Agente C: recuperación de políticas mediante pgvector
Al trabajar en la fase de recuperación de políticas del Agente C, anote primero el contrato: los datos de entrada requeridos, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación ayuda a mantener honestos los cambios posteriores en el código. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando se pasa de entornos de demostración a entornos compartidos. Mida el rendimiento en un conjunto fijo de preguntas antes de ajustar los prompts. El cambio constante de prompts rara vez soluciona un sistema de recuperación deficiente.
Aprovechar la ingeniería: las partes que no aparecen en la ficha del modelo
Al trabajar en la fase de ingeniería de componentes de Harness, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Guarde la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben encontrarse en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema. Almacene en caché las instrucciones del sistema estables y los esquemas de las herramientas. Reenviar un preámbulo idéntico es una causa común de agotamiento del recurso.
"""
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
Observabilidad
Al trabajar en la etapa de Observabilidad, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Documente tanto el camino óptimo como el de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no de mejoras posteriores. Haga un punto de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador vuelve a intentar un nodo posterior. Al trabajar en la etapa de Observabilidad, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Trate esta etapa como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace las completaciones parciales silenciosas.
Despliegue en AWS y la interfaz frontal
La implementación en AWS y la etapa correspondiente funcionan mejor cuando se tratan como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando se pasa de entornos de demostración a entornos compartidos. Mantenga el estado del gráfico simple y con tipos definidos. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación del proceso.
¿Qué sigue?
La etapa de “¿Qué sigue?” funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el grafo. Mantenga el estado del grafo simple y tipado; los bloques anidados ocultan qué nodo escribió qué campo y causan interrupciones en la continuación del proceso.
Lista de verificación operativa
La etapa de la lista de verificación operativa funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance.
Prefiera unidades pequeñas y probables sobre scripts extensos. Cuando un paso falla, el fallo debe apuntar a una sola responsabilidad en lugar de a un proceso complicado.
Mantenga el estado del grafo plano y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación del proceso tras las interrupciones.
Añada una prueba de funcionamiento básica que ejerza la ruta crítica en los procesos de integración continua utilizando fixtures, y no APIs pagadas en tiempo real, siempre que lo permitan los presupuestos.
Trate esta etapa como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace completaciones parciales silenciosas.
Mantenga el estado del grafo plano y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación del proceso tras las interrupciones.
Antes de promocionar la pila tecnológica, congele las versiones, capture una transcripción de referencia para la ruta crítica y confirme los pasos para revertir cambios. Los entornos compartidos requieren límites de velocidad, verificaciones de asignación y un responsable claro para la rotación de credenciales secretas. Prefiera una fiabilidad sólida a demostraciones ingeniosas pero puntuales.
Nota de lote para 5d0d59733252: mantener las claves del proveedor fuera del repositorio, establecer un límite para los tokens por sesión y almacenar las transcripciones junto a los archivos de evaluación para que los cambios posteriores en el modelo sigan siendo comparables.
Al trabajar en la etapa 0 de las notas de fortalecimiento, anote primero el contrato: entradas requeridas, señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza que los cambios posteriores en el código sean transparentes. Prefiera unidades pequeñas y verificables sobre scripts extensos. Cuando un paso falla, el fallo debe apuntar a una única responsabilidad y no a un proceso complicado.
Detalle de fortalecimiento 0/721: mida el tiempo de ejecución, la clase del error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en observaciones anecdóticas.
La etapa 1 de las notas de fortalecimiento funciona mejor cuando se trata como una superficie medible. Capture una transcripción ejemplar, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la fase de demostración a entornos compartidos.
Detalle 1/721 del fortalecimiento: mida el tiempo de ejecución, la clase de error y el gasto en tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.
Para la etapa 2 de las notas de fortalecimiento, defina las entradas, el responsable de cada paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Documente tanto la ruta óptima como la ruta de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son ajustes realizados posteriormente.
Detalle de reforzamiento 2/721: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.
Al trabajar en la tercera fase de la nota de reforzamiento, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Trate esta fase como un contrato entre entradas y salidas validadas. Asigne nombres a los artefactos, defina las comprobaciones de éxito y rechace las completaciones parciales silenciosas.
Detalle de reforzamiento 3/721: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.
La etapa 4 de las notas de fortalecimiento funciona mejor cuando se trata como una superficie medible. Capture una transcripción ejemplar, un caso de fallo y la nota de reversión antes de ampliar el alcance. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema.
Detalle de fortalecimiento 4/721: mida el tiempo de ejecución, la clase del error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en relatos anecdóticos.
Lecturas relacionadas
- Notas prácticas: Cómo diseñar un sistema RAG listo para producción (Arquitectura + — Guía práctica detallada de Notas prácticas: Cómo diseñar un sistema RAG listo para producción (Arquitectura +: contratos, verificaciones y espacios de código listos para usar para los equipos que implementan este patrón).
- Notas prácticas: La stack Teach para construir aplicaciones full-stack en el entorno AI-Agente — Guía práctica detallada de Notas prácticas: La stack Teach para construir aplicaciones full-stack en el entorno AI-Agente: contratos, verificaciones y espacios de código listos para usar para los equipos que implementan este patrón.