Skip to main content

python.run

Runs Python code or a command inside a Python-equipped sidecar container. The pack acquires its own session (separate from the browser sidecar) via SessionSpec.Image: helmdeck-sidecar-python:dev, so it inherits the path-safety guard but doesn't share state with browser-driven packs.

The Python sidecar ships CPython 3.11 + pytest + ruff + mypy preinstalled. Either set code (run inline via python3 -c) or command (run an argv-shape command in cwd) — exactly one must be set.

⚙️ Setup note: this pack only works when the language sidecar is built and pinned. Run make sidecars to build, then add HELMDECK_SIDECAR_PYTHON=helmdeck-sidecar-python:dev to deploy/compose/.env.local and recreate the control-plane container (docker compose up -d --force-recreate control-plane). Without those, the pack returns session_unavailable with No such image: ghcr.io/tosin2013/helmdeck-sidecar-python:latest.

Inputs​

FieldTypeRequiredDefaultNotes
codestringone of—Python code to run via python3 -c. Multi-line supported.
commandarrayone of—argv-style command (e.g. ["pytest", "-v"]).
cwdstringno—Working directory inside the sidecar (typically a clone path from a chained repo.fetch).
stdinstringno—Bytes piped to the process's stdin.

Outputs​

FieldTypeNotes
stdoutstringCaptured stdout.
stderrstringCaptured stderr.
exit_codenumberProcess exit code. Not an error — the agent inspects this to decide.
runtimestringAlways python (handy when an agent dispatches multiple language packs and wants to know which it just ran).

Vault credentials needed​

None directly. If the Python code needs a service-API key, use ${vault:NAME} placeholder substitution at the env-var level (set command to ["sh","-c","TOKEN=${vault:my-token} python3 -c '...'"]).

Use it from your agent (OpenClaw chat-UI worked example)​

Prompt (sent in OpenClaw chat UI / openclaw-cli agent):

Use the helmdeck__python-run tool to execute this Python code: import hashlib; print(hashlib.sha256(b"helmdeck").hexdigest()). Report the hex digest.

Tool call (1 call, no failures):

{
"name": "helmdeck__python-run",
"arguments": {
"code": "import hashlib; print(hashlib.sha256(b\"helmdeck\").hexdigest())"
}
}

Pack response (truncated):

{"pack":"python.run","version":"v1","output":{"exit_code":0,"runtime":"python","stderr":"","stdout":"ab8f104b28f3f2ca9f9f41099400b31114ed7d7599487666f1e6e998616fb8b4\n"},"duration_ms":2456234608,"session_id":"e07f45fc-4fe1-47c6-8259-0d113579f091"}

Agent's final reply:

The SHA‑256 hex digest of the string “helmdeck” is:

ab8f104b28f3f2ca9f9f41099400b31114ed7d7599487666f1e6e998616fb8b4

Verified via OpenClaw 2026.5.6 + helmdeck v0.9.0-dev + openrouter/openai/gpt-oss-120b on 2026-05-07 (cost: $0.1307).

Developer reference (curl)​

Happy path — inline code:

curl -fsS -X POST http://localhost:3000/api/v1/packs/python.run \
-H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
-d '{"code":"import platform; print(\"Python\", platform.python_version()); print(2+2)"}'

Captured response:

{
"pack": "python.run",
"version": "v1",
"output": {
"exit_code": 0,
"runtime": "python",
"stderr": "",
"stdout": "Python 3.11.2\n4\n"
},
"session_id": "944bcb55-5b79-4c9a-b4e4-d2347f0faf6f"
}

Code that raises (non-zero exit, traceback in stderr — pack call still succeeds):

curl -fsS -X POST http://localhost:3000/api/v1/packs/python.run \
-H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
-d '{"code":"raise ValueError(\"oops\")"}'
{
"pack": "python.run",
"version": "v1",
"output": {
"exit_code": 1,
"runtime": "python",
"stderr": "Traceback (most recent call last):\n File \"<string>\", line 1, in <module>\nValueError: oops\n",
"stdout": ""
}
}

Error codes​

CodeTriggersCaptured response
invalid_inputBoth code and command empty{"error":"invalid_input","message":"exactly one of \"code\" or \"command\" must be set"}
invalid_inputBoth code and command setset either code or command, not both
session_unavailablePython sidecar image not presentcontainer create: Error response from daemon: No such image: ...
handler_failedContainer exec itself fails (sidecar OOM, daemon restart)exec error

A non-zero exit_code is not an error — it's a successful pack call where the script chose to exit non-zero.

Session chaining​

needs_session: true, but the session is owned by this pack (separate Python sidecar). To run Python against files in a clone, chain repo.fetch → use the returned clone_path as cwd for python.run. The clone gets bind-mounted into the Python sidecar — no separate fs.copy needed.

Async behavior​

Synchronous. Container startup adds ~1–2 seconds of cold-start the first time; warm sessions reuse the container.

See also​