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 ofPython code to run via python3 -c. Multi-line supported.
commandarrayone ofargv-style command (e.g. ["pytest", "-v"]).
cwdstringnoWorking directory inside the sidecar (typically a clone path from a chained repo.fetch).
stdinstringnoBytes 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