synthelium-sdk 2.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- synthelium_sdk-2.2.1/LICENSE +16 -0
- synthelium_sdk-2.2.1/MANIFEST.in +8 -0
- synthelium_sdk-2.2.1/PKG-INFO +191 -0
- synthelium_sdk-2.2.1/README.md +34 -0
- synthelium_sdk-2.2.1/pyproject.toml +36 -0
- synthelium_sdk-2.2.1/setup.cfg +4 -0
- synthelium_sdk-2.2.1/setup.py +10 -0
- synthelium_sdk-2.2.1/synthelium_sdk/README.md +170 -0
- synthelium_sdk-2.2.1/synthelium_sdk/__init__.py +53 -0
- synthelium_sdk-2.2.1/synthelium_sdk/client.py +704 -0
- synthelium_sdk-2.2.1/synthelium_sdk/exceptions.py +53 -0
- synthelium_sdk-2.2.1/synthelium_sdk/models.py +136 -0
- synthelium_sdk-2.2.1/synthelium_sdk.egg-info/PKG-INFO +191 -0
- synthelium_sdk-2.2.1/synthelium_sdk.egg-info/SOURCES.txt +15 -0
- synthelium_sdk-2.2.1/synthelium_sdk.egg-info/dependency_links.txt +1 -0
- synthelium_sdk-2.2.1/synthelium_sdk.egg-info/requires.txt +1 -0
- synthelium_sdk-2.2.1/synthelium_sdk.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
SYNTHELIUM SDK — LICENCIA PROPIETARIA
|
|
2
|
+
Copyright (c) 2026 Synthelium. Todos los derechos reservados.
|
|
3
|
+
|
|
4
|
+
Este software (el "SDK") se entrega de forma privada a clientes autorizados de
|
|
5
|
+
Synthelium para consumir la API de Synthelium. Su uso está sujeto al acuerdo
|
|
6
|
+
comercial vigente entre el cliente y Synthelium.
|
|
7
|
+
|
|
8
|
+
Queda PROHIBIDO, sin autorización previa y por escrito de Synthelium:
|
|
9
|
+
- redistribuir, sublicenciar, vender o publicar el SDK, total o parcialmente;
|
|
10
|
+
- realizar ingeniería inversa de la API o del servicio a partir del SDK;
|
|
11
|
+
- usar el SDK fuera del alcance del acuerdo comercial del cliente.
|
|
12
|
+
|
|
13
|
+
EL SDK SE ENTREGA "TAL CUAL", SIN GARANTÍAS DE NINGÚN TIPO. SYNTHELIUM NO SERÁ
|
|
14
|
+
RESPONSABLE POR DAÑOS DERIVADOS DEL USO DEL SDK.
|
|
15
|
+
|
|
16
|
+
Contacto: contacto@legaltriage.com.co
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
include LICENSE
|
|
2
|
+
include synthelium_sdk/README.md
|
|
3
|
+
# El SDK es solo el cliente HTTP: NUNCA empaquetar tests internos del servidor
|
|
4
|
+
# (importan core.nucleus / domains.* / api.main → filtrarían nombres internos a PyPI).
|
|
5
|
+
prune tests
|
|
6
|
+
recursive-exclude tests *
|
|
7
|
+
recursive-exclude * __pycache__
|
|
8
|
+
recursive-exclude * *.pyc
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: synthelium-sdk
|
|
3
|
+
Version: 2.2.1
|
|
4
|
+
Summary: Cliente oficial de Synthelium — gobernanza verificable de agentes de IA.
|
|
5
|
+
Author-email: Synthelium <contacto@aletheox.com>
|
|
6
|
+
License: Proprietary — Todos los derechos reservados
|
|
7
|
+
Project-URL: Homepage, https://api.aletheox.com
|
|
8
|
+
Project-URL: Documentation, https://api.aletheox.com/guide
|
|
9
|
+
Keywords: ai,safety,compliance,risk,governance,adversarial
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Topic :: Security
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: License :: Other/Proprietary License
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: httpx>=0.27.0
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# Synthelium SDK
|
|
23
|
+
|
|
24
|
+
Cliente oficial para la API de **Aletheox** — gobernanza verificable de agentes
|
|
25
|
+
de IA. HTTP puro: solo habla con `https://api.aletheox.com`.
|
|
26
|
+
|
|
27
|
+
## Instalación (privada)
|
|
28
|
+
|
|
29
|
+
El SDK se entrega como archivo `.whl` directamente al cliente. **No** está en el
|
|
30
|
+
índice público de PyPI. Instálalo desde el archivo que recibiste:
|
|
31
|
+
|
|
32
|
+
pip install ./synthelium_sdk-2.2.1-py3-none-any.whl
|
|
33
|
+
|
|
34
|
+
Única dependencia: `httpx`.
|
|
35
|
+
|
|
36
|
+
## Uso en 3 líneas
|
|
37
|
+
|
|
38
|
+
from synthelium_sdk import SyntheliumClient, Agent
|
|
39
|
+
|
|
40
|
+
client = SyntheliumClient(api_key="sk-synthelium-...")
|
|
41
|
+
report = client.run_evaluation(Agent(mi_funcion_llm), sector="banking")
|
|
42
|
+
report.print_report()
|
|
43
|
+
|
|
44
|
+
Por defecto el cliente apunta a producción. La key se envía en cada llamada
|
|
45
|
+
protegida; consíguela en `contacto@aletheox.com`.
|
|
46
|
+
|
|
47
|
+
## Campo de Riesgos
|
|
48
|
+
|
|
49
|
+
Evalúa tu agente contra los seis vectores adversariales de tu sector
|
|
50
|
+
(`banking`, `clinical`, `telecom`).
|
|
51
|
+
|
|
52
|
+
**Atajo** — todo de una:
|
|
53
|
+
|
|
54
|
+
report = client.run_evaluation(Agent(mi_funcion_llm), sector="banking")
|
|
55
|
+
print(report.summary())
|
|
56
|
+
|
|
57
|
+
**Granular** — cuando necesitas control fino. Tu agente corre en tu máquina; el
|
|
58
|
+
SDK solo envía la acción propuesta:
|
|
59
|
+
|
|
60
|
+
s = client.start_session("banking")
|
|
61
|
+
sid = s["session_id"]
|
|
62
|
+
while True:
|
|
63
|
+
step = client.probe(sid)
|
|
64
|
+
if step.get("done"):
|
|
65
|
+
break
|
|
66
|
+
accion = mi_agente(step["system"], step["user"])
|
|
67
|
+
client.act(sid, step["vector_id"], accion)
|
|
68
|
+
result = client.finalize(sid)
|
|
69
|
+
|
|
70
|
+
Otros métodos: `client.get_certificates(sid)`, `client.verify_certificate(cert)`,
|
|
71
|
+
`client.session_status(sid)`, `client.list_sectors()`, `client.list_vectors()`,
|
|
72
|
+
`client.health()`.
|
|
73
|
+
|
|
74
|
+
## Constructor de Procesos
|
|
75
|
+
|
|
76
|
+
Define tu propio proceso en lenguaje natural mediante `client.builder`:
|
|
77
|
+
|
|
78
|
+
proceso = client.builder.parse(
|
|
79
|
+
"El proceso comienza con el registro. Luego se verifica la póliza. "
|
|
80
|
+
"El pago se aprueba tras el dictamen.")
|
|
81
|
+
val = client.builder.validate(proceso)
|
|
82
|
+
if val["valid"]:
|
|
83
|
+
built = client.builder.build(proceso)
|
|
84
|
+
print(built["stability_report"]["tipo_estructura"])
|
|
85
|
+
|
|
86
|
+
Plantillas:
|
|
87
|
+
|
|
88
|
+
client.builder.list_templates()
|
|
89
|
+
plantilla = client.builder.get_template("reclamacion_seguros")
|
|
90
|
+
clon = client.builder.clone_template("reclamacion_seguros", "Mi proceso")
|
|
91
|
+
|
|
92
|
+
Procesos guardados: `list_processes()`, `get_process(id)`, `rebuild_process(id)`,
|
|
93
|
+
`delete_process(id)`. Atajo: `client.builder.build_from_text(texto)`.
|
|
94
|
+
|
|
95
|
+
## Capa de Consecuencias (gate)
|
|
96
|
+
|
|
97
|
+
Convierte el veredicto en control activo: antes de una acción crítica, tu agente
|
|
98
|
+
consulta el gate y solo procede si Synthelium lo permite. Si se bloquea, queda
|
|
99
|
+
pendiente de resolución humana — el interventor aprueba, rechaza o escala, y cada
|
|
100
|
+
resolución queda certificada.
|
|
101
|
+
|
|
102
|
+
r = client.gate(sid, action="disbursement")
|
|
103
|
+
if r["proceed"]:
|
|
104
|
+
ejecutar_accion()
|
|
105
|
+
else:
|
|
106
|
+
# Bloqueado: el agente se detiene. El interventor decide en su panel.
|
|
107
|
+
cert_id = r["cert_id"]
|
|
108
|
+
client.approve_gate(sid, cert_id, intervenor="ana@banco.com")
|
|
109
|
+
# o: client.reject_gate(...) / client.escalate_gate(...)
|
|
110
|
+
|
|
111
|
+
Consulta: `client.gate_status(sid, cert_id)`, `client.list_gates(sid)`,
|
|
112
|
+
`client.latest_resolution(sid)`.
|
|
113
|
+
|
|
114
|
+
## Contención activa (guard)
|
|
115
|
+
|
|
116
|
+
Para impedir que una acción fuera de la estructura llegue a ejecutarse, envuelve tu
|
|
117
|
+
proceso con un `guard` y llama `check(...)` **antes** de cada acción. Si está bloqueada,
|
|
118
|
+
`check()` lanza `ActionBlocked` y la acción no corre:
|
|
119
|
+
|
|
120
|
+
from synthelium_sdk import ActionBlocked
|
|
121
|
+
|
|
122
|
+
g = client.guard(process_id="proc-1", session="run-42")
|
|
123
|
+
try:
|
|
124
|
+
g.check("disbursement", payload={"monto": {"value": 6000, "unit": "COP"}})
|
|
125
|
+
ejecutar_accion() # solo se ejecuta si el gate lo permitió
|
|
126
|
+
except ActionBlocked as e:
|
|
127
|
+
# e.enforced=True -> corte VINCULANTE (nodo sellado): no se ejecuta, sin humano.
|
|
128
|
+
# e.requires_human -> bloqueo advisory: el interventor decide en su panel.
|
|
129
|
+
# e.authorized_by -> hash del cert de config que autorizó el corte (Ed25519);
|
|
130
|
+
# prueba verificable offline de que el bloqueo estuvo autorizado.
|
|
131
|
+
manejar_bloqueo(e)
|
|
132
|
+
|
|
133
|
+
Advisory con espera al interventor: `g.check("disbursement", payload=..., wait_human=True)`
|
|
134
|
+
(devuelve cuando se aprueba; lanza si se rechaza/escala/vence).
|
|
135
|
+
|
|
136
|
+
**Política ante caída del gate (por nodo):** un nodo con corte **sellado** es *fail-closed*
|
|
137
|
+
(si no se puede verificar, no se ejecuta); el resto es *fail-open* (procede). El guard cachea
|
|
138
|
+
qué nodos están sellados al crearse; refréscalo con `g.refresh()`.
|
|
139
|
+
|
|
140
|
+
**Sellar el corte de un nodo** (qué nodos cortan de verdad):
|
|
141
|
+
|
|
142
|
+
client.set_enforce("proc-1", "disbursement", True) # sella el corte vinculante
|
|
143
|
+
client.get_enforce("proc-1") # {node_id: enforce}
|
|
144
|
+
|
|
145
|
+
### Shadow mode (observe)
|
|
146
|
+
|
|
147
|
+
Para validar la política en producción **sin riesgo**: tu IA opera normal y, en paralelo,
|
|
148
|
+
`observe()` registra qué decisión habría tomado Synthelium (con su cert Ed25519 OBSERVADO) **sin
|
|
149
|
+
bloquear ni interrumpir nunca**. `observe()` NO lanza: ante un fallo de red retorna y tu agente sigue.
|
|
150
|
+
|
|
151
|
+
g = client.guard(process_id="proc-1", session="run-42")
|
|
152
|
+
r = g.observe("disbursement", payload={"monto": {"value": 6000, "unit": "COP"}})
|
|
153
|
+
ejecutar_accion() # tu IA ejecuta SIEMPRE; observe solo registra
|
|
154
|
+
# r["would_block"] -> la política HABRÍA bloqueado esta acción
|
|
155
|
+
# r["would_be_binding"] -> el corte real HABRÍA sido vinculante (nodo sellado)
|
|
156
|
+
# r["cert_id"] -> registro de la decisión; KPI: "decisiones auditadas"
|
|
157
|
+
|
|
158
|
+
## Monitoreo 24/7
|
|
159
|
+
|
|
160
|
+
Recibe alertas en tiempo real (bloqueos, gates vencidos, patrones de ataque) en tu
|
|
161
|
+
propio webhook, y consulta el Panel del Interventor:
|
|
162
|
+
|
|
163
|
+
client.monitoring.subscribe("https://tu-servidor/webhook")
|
|
164
|
+
client.monitoring.panel() # gates pendientes, bloqueos 24h, alertas activas
|
|
165
|
+
client.monitoring.health()
|
|
166
|
+
|
|
167
|
+
Eventos disponibles: `blocked`, `gate_pending`, `gate_expired`, `pattern_detected`.
|
|
168
|
+
|
|
169
|
+
## Manejo de errores
|
|
170
|
+
|
|
171
|
+
Todas heredan de `SyntheliumError`:
|
|
172
|
+
|
|
173
|
+
| Excepción | Cuándo |
|
|
174
|
+
|---|---|
|
|
175
|
+
| `AuthenticationError` | API key ausente o inválida (401) |
|
|
176
|
+
| `RateLimitError` | Límite de uso alcanzado (429), tras reintentos |
|
|
177
|
+
| `ServerError` | Error del servidor (5xx), tras reintentos |
|
|
178
|
+
| `SyntheliumConnectionError` | No se pudo conectar (red/DNS) |
|
|
179
|
+
| `SyntheliumError` | Base — captura cualquier fallo del SDK |
|
|
180
|
+
|
|
181
|
+
El SDK **reintenta con backoff** ante `429` y timeouts (hasta 3 intentos).
|
|
182
|
+
|
|
183
|
+
## Privacidad
|
|
184
|
+
|
|
185
|
+
Tu agente se ejecuta **siempre en tu propia máquina**. El SDK pide cada escenario
|
|
186
|
+
al servidor, corre tu función localmente y solo envía la acción propuesta. Tu
|
|
187
|
+
código nunca sale de tu host.
|
|
188
|
+
|
|
189
|
+
## Acceso
|
|
190
|
+
|
|
191
|
+
`contacto@aletheox.com`
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Synthelium Control
|
|
2
|
+
|
|
3
|
+
Proyecto independiente. Puerto: **9000**.
|
|
4
|
+
|
|
5
|
+
## Reglas
|
|
6
|
+
|
|
7
|
+
- **Separación absoluta:** este proyecto no conoce ni referencia ningún otro proyecto del computador.
|
|
8
|
+
- **Núcleo inmutable:** `core/kernel_core.py` no se modifica jamás; solo se importa desde `core/nucleus.py`.
|
|
9
|
+
- **Una fase a la vez:** ver estado de fases en `CLAUDE.md`.
|
|
10
|
+
|
|
11
|
+
## Estructura
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Synthelium Control/
|
|
15
|
+
├── CLAUDE.md
|
|
16
|
+
├── README.md
|
|
17
|
+
├── requirements.txt
|
|
18
|
+
├── core/
|
|
19
|
+
│ ├── __init__.py
|
|
20
|
+
│ └── kernel_core.py
|
|
21
|
+
├── domains/
|
|
22
|
+
│ └── __init__.py
|
|
23
|
+
├── api/
|
|
24
|
+
│ └── __init__.py
|
|
25
|
+
├── dashboard/
|
|
26
|
+
└── tests/
|
|
27
|
+
└── __init__.py
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Instalación
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
pip install -r requirements.txt
|
|
34
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "synthelium-sdk"
|
|
7
|
+
version = "2.2.1"
|
|
8
|
+
description = "Cliente oficial de Synthelium — gobernanza verificable de agentes de IA."
|
|
9
|
+
readme = "synthelium_sdk/README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "Proprietary — Todos los derechos reservados" }
|
|
12
|
+
authors = [{ name = "Synthelium", email = "contacto@aletheox.com" }]
|
|
13
|
+
keywords = ["ai", "safety", "compliance", "risk", "governance", "adversarial"]
|
|
14
|
+
dependencies = ["httpx>=0.27.0"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 5 - Production/Stable",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Topic :: Security",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"License :: Other/Proprietary License",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://api.aletheox.com"
|
|
26
|
+
Documentation = "https://api.aletheox.com/guide"
|
|
27
|
+
|
|
28
|
+
[tool.setuptools.packages.find]
|
|
29
|
+
include = ["synthelium_sdk*"]
|
|
30
|
+
|
|
31
|
+
[tool.pytest.ini_options]
|
|
32
|
+
# import-mode=importlib resuelve los nombres de test duplicados (varios test_api.py).
|
|
33
|
+
# Se ignoran: build/ y dist/ (copias del wheel) y los dos scripts de integración
|
|
34
|
+
# manuales que requieren un servidor en vivo en :8900 (no son tests unitarios;
|
|
35
|
+
# se ejecutan a mano con el servidor arriba).
|
|
36
|
+
addopts = "--import-mode=importlib --ignore=build --ignore=dist --ignore=campo_riesgos/test_integration.py --ignore=campo_riesgos/test_integration_v2.py"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
setup.py — stub de compatibilidad.
|
|
3
|
+
|
|
4
|
+
La configuración del paquete vive en pyproject.toml (PEP 621). Este archivo solo
|
|
5
|
+
existe para soportar `pip install .` con herramientas antiguas; toda la metadata
|
|
6
|
+
(nombre, versión, dependencias) se lee desde pyproject.toml.
|
|
7
|
+
"""
|
|
8
|
+
from setuptools import setup
|
|
9
|
+
|
|
10
|
+
setup()
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Synthelium SDK
|
|
2
|
+
|
|
3
|
+
Cliente oficial para la API de **Aletheox** — gobernanza verificable de agentes
|
|
4
|
+
de IA. HTTP puro: solo habla con `https://api.aletheox.com`.
|
|
5
|
+
|
|
6
|
+
## Instalación (privada)
|
|
7
|
+
|
|
8
|
+
El SDK se entrega como archivo `.whl` directamente al cliente. **No** está en el
|
|
9
|
+
índice público de PyPI. Instálalo desde el archivo que recibiste:
|
|
10
|
+
|
|
11
|
+
pip install ./synthelium_sdk-2.2.1-py3-none-any.whl
|
|
12
|
+
|
|
13
|
+
Única dependencia: `httpx`.
|
|
14
|
+
|
|
15
|
+
## Uso en 3 líneas
|
|
16
|
+
|
|
17
|
+
from synthelium_sdk import SyntheliumClient, Agent
|
|
18
|
+
|
|
19
|
+
client = SyntheliumClient(api_key="sk-synthelium-...")
|
|
20
|
+
report = client.run_evaluation(Agent(mi_funcion_llm), sector="banking")
|
|
21
|
+
report.print_report()
|
|
22
|
+
|
|
23
|
+
Por defecto el cliente apunta a producción. La key se envía en cada llamada
|
|
24
|
+
protegida; consíguela en `contacto@aletheox.com`.
|
|
25
|
+
|
|
26
|
+
## Campo de Riesgos
|
|
27
|
+
|
|
28
|
+
Evalúa tu agente contra los seis vectores adversariales de tu sector
|
|
29
|
+
(`banking`, `clinical`, `telecom`).
|
|
30
|
+
|
|
31
|
+
**Atajo** — todo de una:
|
|
32
|
+
|
|
33
|
+
report = client.run_evaluation(Agent(mi_funcion_llm), sector="banking")
|
|
34
|
+
print(report.summary())
|
|
35
|
+
|
|
36
|
+
**Granular** — cuando necesitas control fino. Tu agente corre en tu máquina; el
|
|
37
|
+
SDK solo envía la acción propuesta:
|
|
38
|
+
|
|
39
|
+
s = client.start_session("banking")
|
|
40
|
+
sid = s["session_id"]
|
|
41
|
+
while True:
|
|
42
|
+
step = client.probe(sid)
|
|
43
|
+
if step.get("done"):
|
|
44
|
+
break
|
|
45
|
+
accion = mi_agente(step["system"], step["user"])
|
|
46
|
+
client.act(sid, step["vector_id"], accion)
|
|
47
|
+
result = client.finalize(sid)
|
|
48
|
+
|
|
49
|
+
Otros métodos: `client.get_certificates(sid)`, `client.verify_certificate(cert)`,
|
|
50
|
+
`client.session_status(sid)`, `client.list_sectors()`, `client.list_vectors()`,
|
|
51
|
+
`client.health()`.
|
|
52
|
+
|
|
53
|
+
## Constructor de Procesos
|
|
54
|
+
|
|
55
|
+
Define tu propio proceso en lenguaje natural mediante `client.builder`:
|
|
56
|
+
|
|
57
|
+
proceso = client.builder.parse(
|
|
58
|
+
"El proceso comienza con el registro. Luego se verifica la póliza. "
|
|
59
|
+
"El pago se aprueba tras el dictamen.")
|
|
60
|
+
val = client.builder.validate(proceso)
|
|
61
|
+
if val["valid"]:
|
|
62
|
+
built = client.builder.build(proceso)
|
|
63
|
+
print(built["stability_report"]["tipo_estructura"])
|
|
64
|
+
|
|
65
|
+
Plantillas:
|
|
66
|
+
|
|
67
|
+
client.builder.list_templates()
|
|
68
|
+
plantilla = client.builder.get_template("reclamacion_seguros")
|
|
69
|
+
clon = client.builder.clone_template("reclamacion_seguros", "Mi proceso")
|
|
70
|
+
|
|
71
|
+
Procesos guardados: `list_processes()`, `get_process(id)`, `rebuild_process(id)`,
|
|
72
|
+
`delete_process(id)`. Atajo: `client.builder.build_from_text(texto)`.
|
|
73
|
+
|
|
74
|
+
## Capa de Consecuencias (gate)
|
|
75
|
+
|
|
76
|
+
Convierte el veredicto en control activo: antes de una acción crítica, tu agente
|
|
77
|
+
consulta el gate y solo procede si Synthelium lo permite. Si se bloquea, queda
|
|
78
|
+
pendiente de resolución humana — el interventor aprueba, rechaza o escala, y cada
|
|
79
|
+
resolución queda certificada.
|
|
80
|
+
|
|
81
|
+
r = client.gate(sid, action="disbursement")
|
|
82
|
+
if r["proceed"]:
|
|
83
|
+
ejecutar_accion()
|
|
84
|
+
else:
|
|
85
|
+
# Bloqueado: el agente se detiene. El interventor decide en su panel.
|
|
86
|
+
cert_id = r["cert_id"]
|
|
87
|
+
client.approve_gate(sid, cert_id, intervenor="ana@banco.com")
|
|
88
|
+
# o: client.reject_gate(...) / client.escalate_gate(...)
|
|
89
|
+
|
|
90
|
+
Consulta: `client.gate_status(sid, cert_id)`, `client.list_gates(sid)`,
|
|
91
|
+
`client.latest_resolution(sid)`.
|
|
92
|
+
|
|
93
|
+
## Contención activa (guard)
|
|
94
|
+
|
|
95
|
+
Para impedir que una acción fuera de la estructura llegue a ejecutarse, envuelve tu
|
|
96
|
+
proceso con un `guard` y llama `check(...)` **antes** de cada acción. Si está bloqueada,
|
|
97
|
+
`check()` lanza `ActionBlocked` y la acción no corre:
|
|
98
|
+
|
|
99
|
+
from synthelium_sdk import ActionBlocked
|
|
100
|
+
|
|
101
|
+
g = client.guard(process_id="proc-1", session="run-42")
|
|
102
|
+
try:
|
|
103
|
+
g.check("disbursement", payload={"monto": {"value": 6000, "unit": "COP"}})
|
|
104
|
+
ejecutar_accion() # solo se ejecuta si el gate lo permitió
|
|
105
|
+
except ActionBlocked as e:
|
|
106
|
+
# e.enforced=True -> corte VINCULANTE (nodo sellado): no se ejecuta, sin humano.
|
|
107
|
+
# e.requires_human -> bloqueo advisory: el interventor decide en su panel.
|
|
108
|
+
# e.authorized_by -> hash del cert de config que autorizó el corte (Ed25519);
|
|
109
|
+
# prueba verificable offline de que el bloqueo estuvo autorizado.
|
|
110
|
+
manejar_bloqueo(e)
|
|
111
|
+
|
|
112
|
+
Advisory con espera al interventor: `g.check("disbursement", payload=..., wait_human=True)`
|
|
113
|
+
(devuelve cuando se aprueba; lanza si se rechaza/escala/vence).
|
|
114
|
+
|
|
115
|
+
**Política ante caída del gate (por nodo):** un nodo con corte **sellado** es *fail-closed*
|
|
116
|
+
(si no se puede verificar, no se ejecuta); el resto es *fail-open* (procede). El guard cachea
|
|
117
|
+
qué nodos están sellados al crearse; refréscalo con `g.refresh()`.
|
|
118
|
+
|
|
119
|
+
**Sellar el corte de un nodo** (qué nodos cortan de verdad):
|
|
120
|
+
|
|
121
|
+
client.set_enforce("proc-1", "disbursement", True) # sella el corte vinculante
|
|
122
|
+
client.get_enforce("proc-1") # {node_id: enforce}
|
|
123
|
+
|
|
124
|
+
### Shadow mode (observe)
|
|
125
|
+
|
|
126
|
+
Para validar la política en producción **sin riesgo**: tu IA opera normal y, en paralelo,
|
|
127
|
+
`observe()` registra qué decisión habría tomado Synthelium (con su cert Ed25519 OBSERVADO) **sin
|
|
128
|
+
bloquear ni interrumpir nunca**. `observe()` NO lanza: ante un fallo de red retorna y tu agente sigue.
|
|
129
|
+
|
|
130
|
+
g = client.guard(process_id="proc-1", session="run-42")
|
|
131
|
+
r = g.observe("disbursement", payload={"monto": {"value": 6000, "unit": "COP"}})
|
|
132
|
+
ejecutar_accion() # tu IA ejecuta SIEMPRE; observe solo registra
|
|
133
|
+
# r["would_block"] -> la política HABRÍA bloqueado esta acción
|
|
134
|
+
# r["would_be_binding"] -> el corte real HABRÍA sido vinculante (nodo sellado)
|
|
135
|
+
# r["cert_id"] -> registro de la decisión; KPI: "decisiones auditadas"
|
|
136
|
+
|
|
137
|
+
## Monitoreo 24/7
|
|
138
|
+
|
|
139
|
+
Recibe alertas en tiempo real (bloqueos, gates vencidos, patrones de ataque) en tu
|
|
140
|
+
propio webhook, y consulta el Panel del Interventor:
|
|
141
|
+
|
|
142
|
+
client.monitoring.subscribe("https://tu-servidor/webhook")
|
|
143
|
+
client.monitoring.panel() # gates pendientes, bloqueos 24h, alertas activas
|
|
144
|
+
client.monitoring.health()
|
|
145
|
+
|
|
146
|
+
Eventos disponibles: `blocked`, `gate_pending`, `gate_expired`, `pattern_detected`.
|
|
147
|
+
|
|
148
|
+
## Manejo de errores
|
|
149
|
+
|
|
150
|
+
Todas heredan de `SyntheliumError`:
|
|
151
|
+
|
|
152
|
+
| Excepción | Cuándo |
|
|
153
|
+
|---|---|
|
|
154
|
+
| `AuthenticationError` | API key ausente o inválida (401) |
|
|
155
|
+
| `RateLimitError` | Límite de uso alcanzado (429), tras reintentos |
|
|
156
|
+
| `ServerError` | Error del servidor (5xx), tras reintentos |
|
|
157
|
+
| `SyntheliumConnectionError` | No se pudo conectar (red/DNS) |
|
|
158
|
+
| `SyntheliumError` | Base — captura cualquier fallo del SDK |
|
|
159
|
+
|
|
160
|
+
El SDK **reintenta con backoff** ante `429` y timeouts (hasta 3 intentos).
|
|
161
|
+
|
|
162
|
+
## Privacidad
|
|
163
|
+
|
|
164
|
+
Tu agente se ejecuta **siempre en tu propia máquina**. El SDK pide cada escenario
|
|
165
|
+
al servidor, corre tu función localmente y solo envía la acción propuesta. Tu
|
|
166
|
+
código nunca sale de tu host.
|
|
167
|
+
|
|
168
|
+
## Acceso
|
|
169
|
+
|
|
170
|
+
`contacto@aletheox.com`
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Synthelium SDK
|
|
3
|
+
Cliente HTTP puro para la API de Synthelium (https://api.aletheox.com).
|
|
4
|
+
|
|
5
|
+
Uso mínimo:
|
|
6
|
+
from synthelium_sdk import SyntheliumClient, Agent
|
|
7
|
+
client = SyntheliumClient(api_key="sk-synthelium-...")
|
|
8
|
+
report = client.run_evaluation(Agent(mi_funcion_llm), sector="banking")
|
|
9
|
+
report.print_report()
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from synthelium_sdk.client import (
|
|
13
|
+
Agent,
|
|
14
|
+
Guard,
|
|
15
|
+
MonitoringAPI,
|
|
16
|
+
ProcessBuilderAPI,
|
|
17
|
+
RiskField, # alias histórico de SyntheliumClient
|
|
18
|
+
SyntheliumClient,
|
|
19
|
+
)
|
|
20
|
+
from synthelium_sdk.exceptions import (
|
|
21
|
+
ActionBlocked,
|
|
22
|
+
AuthenticationError,
|
|
23
|
+
RateLimitError,
|
|
24
|
+
ServerError,
|
|
25
|
+
SyntheliumConnectionError,
|
|
26
|
+
SyntheliumError,
|
|
27
|
+
)
|
|
28
|
+
from synthelium_sdk.models import (
|
|
29
|
+
Certificate,
|
|
30
|
+
RegulatoryGap,
|
|
31
|
+
RiskReport,
|
|
32
|
+
VectorResult,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
__version__ = "2.2.1"
|
|
36
|
+
__all__ = [
|
|
37
|
+
"SyntheliumClient",
|
|
38
|
+
"Agent",
|
|
39
|
+
"Guard",
|
|
40
|
+
"ProcessBuilderAPI",
|
|
41
|
+
"MonitoringAPI",
|
|
42
|
+
"RiskField",
|
|
43
|
+
"RiskReport",
|
|
44
|
+
"Certificate",
|
|
45
|
+
"VectorResult",
|
|
46
|
+
"RegulatoryGap",
|
|
47
|
+
"SyntheliumError",
|
|
48
|
+
"ActionBlocked",
|
|
49
|
+
"AuthenticationError",
|
|
50
|
+
"RateLimitError",
|
|
51
|
+
"ServerError",
|
|
52
|
+
"SyntheliumConnectionError",
|
|
53
|
+
]
|