NewWacht Bench is live — AI-assisted development for Wacht
GuidesAgents

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:

FieldNotes
type"CodeRunner" (PascalCase).
runtime"python" (the only runtime).
codePython source, must define run.
input_schemaWacht SchemaField[].
output_schemaOptional SchemaField[]. When set, the return value is validated against it and must be a JSON object.
env_variablesOptional per-tool variables, stored encrypted.
timeout_secondsDefaults to 30.
allow_networkDefaults 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 varClient global
OPENAI_API_KEYopenai_client
ANTHROPIC_API_KEYanthropic_client
GEMINI_API_KEYgemini_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.

On this page