Skip to main content

roxy-guard

Trazabilidad y control de acceso para flujos de agentes que consumen MCPs.

Cuando un agente delega en otro, y ese en otro, el que termina tocando la base de datos está a varios saltos de quien pidió la tarea. Este SDK registra esa cadena mientras ocurre y somete cada acción sensible al veredicto de Roxy antes de que se ejecute.

Instalación

pip install roxy-guard
# o
uv add roxy-guard

El paquete se instala como roxy-guard y se importa como roxy (igual que pillow → import PIL). El nombre corto ya estaba tomado en PyPI.

CLI

Al instalarlo queda el comando roxy. Apunta al despliegue público por defecto; ROXY_API_URL lo cambia.

roxy check                  # ¿responden dashboard, demo-api y gateway?
roxy runs                   # últimas corridas de agentes
roxy tree <sessionId>       # el árbol de delegación de una corrida
roxy logs --denied          # solo lo que Roxy bloqueó
roxy audit reglas.json      # Z3 sobre tus reglas: ¿hay algún hueco?

--json en cualquiera devuelve la respuesta cruda, para encadenar con jq.

roxy audit es el único que necesita el verificador levantado (--engine o ROXY_ENGINE_URL): no está expuesto en el despliegue público. Sale con código 1 si encuentra un hueco, así que sirve en CI.

Qué funciona sin montar nada

necesita
Trazabilidad (el árbol) solo api_url — funciona contra el despliegue público
roxy check / runs / tree / logs nada, apuntan al despliegue
Control de acceso (guard()) un gateway y un MCP registrado con sus reglas
roxy audit el verificador corriendo

Uso

Se engancha una vez, en la invocación. Los agentes no se tocan.

from roxy import Roxy

roxy = Roxy(api_url="https://roxygt.lat/api")

executor.invoke(
    {"input": "concilia las facturas pendientes"},
    config={"callbacks": [roxy], "metadata": {"purpose": "conciliación mensual"}},
)

print(roxy.tree())  # el árbol completo, como lo ve el dashboard

Cada agente que se lance dentro de esa invocación queda registrado solo, con su padre correcto. No hay ids que pasar de mano en mano.

Sub-agentes en invocaciones separadas

Un sub-agente lanzado con su propio .invoke() llega sin padre — LangChain no puede encadenar dos invocaciones independientes. child_config arma la config con el padre ya declarado:

executor.invoke(entrada, config=roxy.child_config(run_id_del_padre,
                                                  purpose="conciliar INV-1005"))

Control de acceso

from roxy import RoxyUnavailable

try:
    decision = roxy.guard(
        action="update_invoice",
        payload={"invoiceId": "INV-1005", "proposedTotal": 0,
                 "computedSubtotalSum": 600000},
        run_id=run_id,
        mcp_name="invoices-mcp",
    )
except RoxyUnavailable:
    return  # sin veredicto no hay permiso

if not decision.allowed:
    return f"denegado: {decision.reason}"
escribir_en_la_base()

RoxyUnavailable no es una negación ni un permiso: significa que Roxy no pudo decidir. Tratarlo como permiso sería conceder acceso justamente porque la capa de seguridad se cayó.

Delegación entre procesos (A2A)

Cuando el sub-agente corre en otro proceso, la cadena se propaga por headers:

# quien delega
requests.post(url_del_subagente, json=tarea, headers=roxy.headers_to_send(run_id))

# quien recibe
roxy.receive(request.headers, ejecutar_subagente, tarea)

Sin esto el agente remoto arranca un árbol nuevo y la cadena se corta justo donde importa: en el salto entre organizaciones.

Auditoría

roxy.lineage(agent_id)   # de la raíz hasta ese agente
roxy.tree()              # todos los nodos de la sesión

Cómo funciona por dentro

Roxy hereda de BaseCallbackHandler, así que LangChain le avisa cada vez que arranca un chain. En cada aviso el SDK decide si ese chain es un agente que vale la pena registrar y, si lo es, hace POST /agents.

Hay dos detalles que resuelve por su cuenta:

Traducción de ids. LangChain identifica cada run con un UUID; la API de Roxy asigna un ObjectId de Mongo y valida que parentId sea uno de los suyos. El SDK mantiene el mapa run_id → id de Roxy y traduce, porque el id del framework no sirve como padre.

Filtrado de ruido. Una corrida de cuatro agentes dispara unos noventa eventos: prompts, parsers, scratchpads. Registrarlos todos convertiría el árbol en ruido. Se registra un nodo cuando la invocación trae purpose en su metadata o cuando el chain es un AgentExecutor.

Todo el registro es fail-open: si la API no responde, se pierde el nodo y el agente sigue. La traza es observación, no la tarea. El control de acceso es lo contrario, fail-closed: sin veredicto no se ejecuta nada.

Licencia

MIT

Metadata

Release files for roxy-guard 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for roxy-guard 0.2.0
File Size Uploaded Provenance
roxy_guard-0.2.0.tar.gz 12.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for roxy-guard 0.2.0
File Interpreter ABI Platform
roxy_guard-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 24.7 kB

Release files / roxy_guard-0.2.0.tar.gz

Download URL roxy_guard-0.2.0.tar.gz
Size 12.4 kB
Tags Source
SHA-256 checksum
How to use checksums
19e1eee91eceae5d6800d7ea049e635811405d75ec00696e74928c2b30f39e9e
BLAKE2b-256 checksum
How to use checksums
e14ae82eff69f8455e1697dad04f3603349268d1bc6d39f8361627f1931cb96b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / roxy_guard-0.2.0-py3-none-any.whl

Download URL roxy_guard-0.2.0-py3-none-any.whl
Size 12.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
67a6c3fc30c4628a696eb1c9760c20b9e88378a1e9593ac4df62fb51af1059fc
BLAKE2b-256 checksum
How to use checksums
35872f0ca7dde72d21dbb18eb3aa919186620229cab7b0b06669edd2dc1c0ea0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Security for roxy-guard 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page