atlas-iac/dockerfiles/hermes-python-sandbox-tool.py

77 lines
2.8 KiB
Python

"""Hermes tool for running Python in a separate, credential-free pod."""
from __future__ import annotations
import json
import os
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen
from tools.registry import registry, tool_error
def _sandbox_url() -> str:
"""Return the tenant-specific sandbox endpoint injected at startup."""
return os.environ.get("HERMES_CODE_SANDBOX_URL", "").strip()
def _sandbox_available() -> bool:
"""Expose the tool only when this tenant has an isolated endpoint."""
return _sandbox_url().startswith("http://hermes-chat-sandbox-")
def execute_python_sandbox(code: str) -> str:
"""Execute Python remotely and return the sandbox's structured result."""
if not isinstance(code, str) or not code.strip():
return tool_error("Python code is required.")
if len(code.encode("utf-8")) > 128 * 1024:
return tool_error("Python code exceeds the 128 KiB request limit.")
request = Request(
_sandbox_url(),
data=json.dumps({"code": code}).encode("utf-8"),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urlopen(request, timeout=55) as response:
payload = response.read(256 * 1024)
return payload.decode("utf-8", errors="replace")
except HTTPError as exc:
detail = exc.read(4096).decode("utf-8", errors="replace")
return tool_error(f"Python sandbox rejected the request: {detail or exc.code}")
except (URLError, TimeoutError, OSError) as exc:
return tool_error(f"Python sandbox is unavailable: {exc}")
registry.register(
name="python_sandbox",
toolset="python_sandbox",
schema={
"name": "python_sandbox",
"description": (
"Run Python in this user's credential-free computation sandbox. "
"Its /workspace and /opt/data/workspace paths expose the same private "
"workspace, and /tmp is writable for temporary verifiers. "
"Use it for file verification, statistics, probability, Monte Carlo "
"simulation, data transforms, and calculations. The sandbox has no "
"Kubernetes, Vault, model-provider credentials, or access to other "
"users. Public research belongs in web_search."
),
"parameters": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "A self-contained Python 3 program that prints its result.",
}
},
"required": ["code"],
},
},
handler=lambda args, **_: execute_python_sandbox(args.get("code", "")),
check_fn=_sandbox_available,
emoji="🧮",
max_result_size_chars=200_000,
)