CodeRunner tools
Create Python tools that an agent runs inside a Wacht sandbox.
CodeRunner tools
A CodeRunner tool runs a Python function inside the agent's sandbox. Reach for it when the agent needs deterministic execution rather than reasoning: parsing files, probing generated media, calling a model SDK, turning structured input into an artifact.
For an HTTP endpoint you own, use an Api tool. For a third-party SaaS action, use Composio. For your own tool server, use Mcp.
Runtime contract
CodeRunner runs Python. The tool configuration carries:
| Field | Notes |
|---|---|
type | "CodeRunner" (PascalCase). |
runtime | "python" (the only runtime). |
code | Python source, must define run. |
input_schema | Wacht SchemaField[]. |
output_schema | Optional SchemaField[]. When set, the return value is validated against it and must be a JSON object. |
env_variables | Optional per-tool variables, stored encrypted. |
timeout_seconds | Defaults to 30. |
allow_network | Defaults to false — outbound network is blocked unless you opt in. |
Your source must define a run function:
def run(input):
return {"ok": True}input is a JSON object, filtered and validated against input_schema. The return value must be JSON-serializable. run may be async def; a returned coroutine is awaited. If the script defines no callable run, the tool fails with CodeRunner script must define a callable run(input) function.
Provider SDKs
When the deployment has the matching provider key configured, CodeRunner injects it as an environment variable and initializes a ready client global:
| Env var | Client global |
|---|---|
OPENAI_API_KEY | openai_client |
ANTHROPIC_API_KEY | anthropic_client |
GEMINI_API_KEY | gemini_client |
If a provider key isn't configured, touching that client raises a clear runtime error rather than failing silently.
The sandbox image ships a fixed Python set, including openai, anthropic, google-genai, groq, cohere, mistralai, together, boto3, requests, httpx, tenacity, pydantic, jsonschema, pandas, numpy, Pillow, python-docx, docxtpl, python-pptx, and reportlab. You cannot add packages per tool. System binaries like ffmpeg and ffprobe depend on the image — if a tool needs one, probe for it at runtime and return a clear error when it's missing.
Create and attach a tool
{
"name": "media_probe",
"description": "Inspect a media file in the sandbox.",
"tool_type": "code_runner",
"configuration": {
"type": "CodeRunner",
"runtime": "python",
"timeout_seconds": 180,
"allow_network": false,
"input_schema": [
{
"name": "media_path",
"field_type": "STRING",
"required": true,
"description": "Sandbox path to inspect."
}
],
"code": "def run(input):\n return {\"media_path\": input[\"media_path\"]}\n"
}
}wacht api call createAiTool --body @tool.json
wacht api call attachToolToAgent --param agent_id=<agent_id> --param tool_id=<tool_id>For an expensive or side-effecting tool, gate it behind review — see approval policy:
wacht api call updateAgentToolApprovalAction \
--param agent_id=<agent_id> \
--param tool_id=<tool_id> \
--body '{"approval_action":"review"}'Schema casing
configuration.type is PascalCase ("CodeRunner"). field_type and items_type use uppercase Wacht schema names: STRING, INTEGER, NUMBER, BOOLEAN, ARRAY, OBJECT. Lowercase variants are not accepted.