Skip to main content

roxy

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
# o
uv add roxy

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.1.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.1.0
File Size Uploaded Provenance
roxy_guard-0.1.0.tar.gz 8.9 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 17.1 kB

Release files / roxy_guard-0.1.0.tar.gz

Download URL roxy_guard-0.1.0.tar.gz
Size 8.9 kB
Tags Source
SHA-256 checksum
How to use checksums
125e741edb194fa89c105f3837f880b6dfe83a5c8a885f9c044243b47a5152eb
BLAKE2b-256 checksum
How to use checksums
45ce89a49a53f3ed6032b7ada2789aec2261a9a620ab4bf533c28c85eb47ba05
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

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

Download URL roxy_guard-0.1.0-py3-none-any.whl
Size 8.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8606cfb1b7960faffdb3f54d5bb2845640c1ae023f1bfd8d46366989b62e66b4
BLAKE2b-256 checksum
How to use checksums
d9cd1c2e8d24bfdb8b8f04e325e065fb183881b3ca91e81e310269690e56056b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Security for roxy-guard 0.1.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.1.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