0Pricing
AI Agents · Lección

Cumplimiento normativo: GDPR y SOC2

Minimización de datos, seguimiento del consentimiento y control de acceso para agentes conformes con la normativa.

Cumplimiento normativo: GDPR y SOC2 es una lección gratuita de AI Agents en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Agents, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Agents incluye 4 lecciones en total.

Por qué se aplican las normativas a los agentes de IA

Los agentes de IA procesan datos de usuarios, toman decisiones y realizan acciones. Por ello, están directamente sujetos a normativas de protección de datos (GDPR) y marcos de seguridad (SOC 2).

El cumplimiento no es opcional: las infracciones pueden conllevar multas de hasta el 4 % de los ingresos anuales globales en virtud del GDPR.

GDPR: minimización de datos

El principio de minimización de datos del GDPR exige recopilar únicamente los datos personales estrictamente necesarios para la finalidad indicada. Un agente no debería almacenar transcripciones completas de las conversaciones si para el análisis solo se necesita el resultado (resuelto/no resuelto).

def minimized_log_entry(conversation: list[dict], user_id: str) -> dict:
    '''Store only what is needed — not the full transcript.'''
    return {
        'user_id':       user_id,
        'timestamp':     conversation[-1].get('timestamp'),
        'turns':         len(conversation),
        'resolved':      conversation[-1].get('resolved', False),
        'intent':        conversation[-1].get('intent'),
        'satisfaction':  conversation[-1].get('csat_score'),
        # NOT stored: full message text, PII mentioned in conversation
    }

# WRONG — stores raw messages which may contain PII
# {'messages': conversation, 'user_id': user_id}

if __name__ == '__main__':
    conversation = [
        {'timestamp': 1717000000, 'resolved': True, 'intent': 'reset_password', 'csat_score': 5}
    ]
    print('Minimized log entry:', minimized_log_entry(conversation, user_id='u42'))

GDPR: seguimiento del consentimiento

Antes de que el agente procese datos personales, debe existir una base jurídica, normalmente el consentimiento del usuario. Registre cuándo se otorgó el consentimiento, qué aspectos abarca y respete las retiradas del consentimiento.

from datetime import datetime, timezone

consent_store: dict[str, dict] = {}  # user_id -> consent record

def record_consent(user_id: str, purpose: str, version: str = '1.0'):
    if user_id not in consent_store:
        consent_store[user_id] = {'purposes': {}}
    consent_store[user_id]['purposes'][purpose] = {
        'granted':     True,
        'timestamp':   datetime.now(timezone.utc).isoformat(),
        'version':     version
    }

def withdraw_consent(user_id: str, purpose: str):
    if user_id in consent_store:
        consent_store[user_id]['purposes'].pop(purpose, None)

def has_consent(user_id: str, purpose: str) -> bool:
    return bool(
        consent_store.get(user_id, {}).get('purposes', {}).get(purpose, {}).get('granted')
    )

if __name__ == '__main__':
    record_consent('u42', 'marketing_emails')
    print('Has consent:', has_consent('u42', 'marketing_emails'))
    withdraw_consent('u42', 'marketing_emails')
    print('Has consent after withdrawal:', has_consent('u42', 'marketing_emails'))

GDPR: derecho de supresión (derecho al olvido)

Cuando un usuario solicita la eliminación de sus datos, el agente debe borrar todos los datos personales asociados a él, incluidos los registros del agente, el historial de conversaciones y los perfiles almacenados en caché. Esto debe realizarse en un plazo de 30 días desde la solicitud.

import os

def erase_user_data(user_id: str, conn) -> dict:
    '''Delete all personal data for a user across all storage systems.'''
    deleted = {}

    # 1. Delete from audit log (if not using WORM storage)
    with conn.cursor() as cur:
        cur.execute('DELETE FROM agent_audit_log WHERE user_id = %s', (user_id,))
        deleted['audit_log_rows'] = cur.rowcount

    # 2. Delete conversation history
    with conn.cursor() as cur:
        cur.execute('DELETE FROM conversation_history WHERE user_id = %s', (user_id,))
        deleted['conversations'] = cur.rowcount

    # 3. Remove consent record
    consent_store.pop(user_id, None)
    deleted['consent_record'] = 1

    # 4. Clear cached profile
    profile_cache = {}  # reference to your cache
    profile_cache.pop(user_id, None)
    deleted['profile_cache'] = 1

    conn.commit()
    return {'user_id': user_id, 'erased': deleted}

GDPR: portabilidad de datos

Los usuarios tienen derecho a recibir sus datos en un formato legible por máquinas (por ejemplo, JSON o CSV). Cree una función de exportación que recopile todos los datos almacenados sobre un usuario en los distintos sistemas del agente.

import json

def export_user_data(user_id: str, conn) -> str:
    export = {'user_id': user_id, 'data': {}}

    with conn.cursor() as cur:
        cur.execute(
            'SELECT timestamp, action_type, result FROM agent_audit_log '
            'WHERE user_id = %s ORDER BY timestamp',
            (user_id,)
        )
        rows = cur.fetchall()
        export['data']['audit_log'] = [
            {'timestamp': r[0], 'action': r[1], 'result': r[2]}
            for r in rows
        ]

    export['data']['consent'] = consent_store.get(user_id, {})
    return json.dumps(export, indent=2)

SOC 2: control de acceso

SOC 2 Type II exige demostrar que el acceso a los sistemas y datos está restringido a personas autorizadas. En el caso de un agente, esto significa: acceso basado en roles a las herramientas del agente, MFA para el acceso administrativo y revisiones periódicas de acceso.

ROLE_PERMISSIONS = {
    'agent_basic':    {'web_search', 'read_file', 'query_database'},
    'agent_email':    {'web_search', 'read_file', 'query_database', 'send_email'},
    'agent_admin':    {'web_search', 'read_file', 'write_file', 'query_database',
                       'send_email', 'create_ticket', 'execute_python_sandbox'},
    'human_admin':    {'*'}  # all permissions
}

def get_permitted_actions(role: str) -> set:
    perms = ROLE_PERMISSIONS.get(role, set())
    if '*' in perms:
        return ALLOWED_ACTIONS  # reference to full allowlist
    return perms

def check_role_permission(role: str, action: str) -> bool:
    return action in get_permitted_actions(role)

SOC 2: Cifrado en reposo y en tránsito

SOC 2 exige cifrar los datos confidenciales en reposo (cifrado de bases de datos, discos cifrados) y en tránsito (TLS 1.2 o superior). Para los agentes, esto significa: almacenamiento cifrado de conversaciones, TLS en todas las llamadas a la API y ningún secreto en texto plano en los registros.

from cryptography.fernet import Fernet
import os

# Key stored in environment variable, never in code
ENCRYPTION_KEY = os.environ.get('LOG_ENCRYPTION_KEY', Fernet.generate_key())
cipher = Fernet(ENCRYPTION_KEY)

def encrypt_sensitive_field(value: str) -> str:
    return cipher.encrypt(value.encode()).decode()

def decrypt_sensitive_field(encrypted: str) -> str:
    return cipher.decrypt(encrypted.encode()).decode()

# Usage: encrypt PII before storing in audit log
encrypted_email = encrypt_sensitive_field('user@example.com')
print(encrypted_email[:30], '...')  # starts with gAAAA...

SOC 2: Registros de auditoría de eventos de seguridad

Los auditores de SOC 2 quieren ver registros de los eventos de seguridad: intentos de inicio de sesión, accesos a datos confidenciales, cambios de configuración y vulneraciones de políticas. Estos registros deben almacenarse de forma segura y conservarse durante al menos 1 año.

import logging, json, time

security_logger = logging.getLogger('agent.security')

SECURITY_EVENTS = {
    'auth_success', 'auth_failure', 'policy_violation',
    'data_access_pii', 'admin_action', 'config_change'
}

def log_security_event(event_type: str, agent_id: str,
                       user_id: str, details: dict):
    assert event_type in SECURITY_EVENTS, f'Unknown security event: {event_type}'
    entry = {
        'timestamp':  time.time(),
        'event_type': event_type,
        'agent_id':   agent_id,
        'user_id':    user_id,
        'details':    details
    }
    security_logger.warning(json.dumps(entry))

if __name__ == '__main__':
    import sys
    security_logger.addHandler(logging.StreamHandler(sys.stdout))
    log_security_event('auth_failure', 'agent-1', 'user-42', {'reason': 'bad_token'})

Rastreo de PII en las salidas de los agentes

Los agentes no deben incluir PII en las salidas que se registren o se envíen a servicios de terceros (analítica, supervisión). Analice el contenido saliente en busca de patrones de PII antes de transmitirlo.

import re

PII_PATTERNS = [
    (r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', 'email'),
    (r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b',                         'phone'),
    (r'\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b',           'credit_card'),
    (r'\b\d{3}-\d{2}-\d{4}\b',                                   'ssn')
]

def redact_pii(text: str) -> tuple[str, list[str]]:
    redacted = text
    found_types = []
    for pattern, pii_type in PII_PATTERNS:
        if re.search(pattern, redacted):
            found_types.append(pii_type)
            redacted = re.sub(pattern, f'[{pii_type.upper()}_REDACTED]', redacted)
    return redacted, found_types

text, types = redact_pii('Contact john@example.com or call 555-867-5309')
print(text)
print('PII found:', types)

Creación de una lista de comprobación de cumplimiento

Antes de implementar un agente que gestione datos personales, verifique que estos controles estén establecidos.

COMPLIANCE_CHECKLIST = [
    ('GDPR',  'Consent captured before processing personal data'),
    ('GDPR',  'Data minimization: only necessary data is collected'),
    ('GDPR',  'Right-to-erasure endpoint implemented and tested'),
    ('GDPR',  'Data portability export available'),
    ('GDPR',  'Data retention policy enforced (auto-delete after N days)'),
    ('SOC2',  'Role-based access control implemented for all agent tools'),
    ('SOC2',  'All data encrypted at rest and in transit (TLS 1.2+)'),
    ('SOC2',  'Security events logged and retained for 12+ months'),
    ('SOC2',  'Access reviews scheduled quarterly'),
    ('SOC2',  'Incident response plan documented'),
    ('BOTH',  'PII redaction applied to logs and analytics exports'),
    ('BOTH',  'Vendor DPAs signed for all third-party APIs used'),
]

for framework, control in COMPLIANCE_CHECKLIST:
    print(f'[ ] [{framework}] {control}')

Automatización de la retención de datos

El RGPD exige eliminar los datos cuando ya no sean necesarios para su finalidad original. Automatice este proceso con un trabajo de política de retención que elimine los registros antiguos según períodos de retención configurables.

from datetime import datetime, timedelta, timezone

RETENTION_POLICIES = {
    'conversation_history': 90,    # days
    'agent_audit_log':      365,
    'cached_profiles':      1,
    'session_data':         30
}

def purge_expired_data(conn):
    purged = {}
    for table, retention_days in RETENTION_POLICIES.items():
        cutoff = datetime.now(timezone.utc) - timedelta(days=retention_days)
        try:
            with conn.cursor() as cur:
                cur.execute(
                    f'DELETE FROM {table} WHERE timestamp < %s',
                    (cutoff.timestamp(),)
                )
                purged[table] = cur.rowcount
        except Exception as e:
            purged[table] = f'Error: {e}'
    conn.commit()
    return purged

if __name__ == '__main__':
    class FakeCursor:
        def __enter__(self):
            return self
        def __exit__(self, *exc):
            return False
        def execute(self, sql, params):
            self.rowcount = 3

    class FakeConn:
        def cursor(self):
            return FakeCursor()
        def commit(self):
            pass

    result = purge_expired_data(FakeConn())
    print('Rows purged per table:')
    for table, count in result.items():
        print(f'  {table}: {count}')

¿Qué es el principio de minimización de datos del RGPD?

La minimización de datos es uno de los principios fundamentales del RGPD e influye directamente en cómo deben diseñarse los sistemas de agentes desde el principio.

Repaso del cumplimiento del RGPD y SOC 2

El cumplimiento del RGPD exige: seguimiento del consentimiento, minimización de datos, implementación del derecho de supresión, exportaciones de portabilidad y redacción de PII en los registros.

SOC 2 exige: control de acceso basado en roles, cifrado en reposo y en tránsito, registro de eventos de seguridad y revisiones de acceso. Automatice las políticas de retención para eliminar los datos caducados.

Preguntas frecuentes

¿La lección «Cumplimiento normativo: GDPR y SOC2» es gratis?

Sí — el texto completo de «Cumplimiento normativo: GDPR y SOC2» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Agents, actualiza a CoddyKit PRO. El curso de AI Agents incluye 4 lecciones en total.

¿Qué aprenderé en «Cumplimiento normativo: GDPR y SOC2»?

Minimización de datos, seguimiento del consentimiento y control de acceso para agentes conformes con la normativa. Practicas AI Agents con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar AI Agents?

No se requiere experiencia previa. AI Agents en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Cumplimiento normativo: GDPR y SOC2»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de AI Agents?

Sí. Cada lección de AI Agents incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Registro inmutable de acciones de agentes
  2. Aplicación de políticas a las acciones de agentes
  3. Cumplimiento normativo: GDPR y SOC2
  4. Puntos de aprobación con supervisión humana
← Volver a AI Agents