{"record":{"id":"2cff828739c4f8ec","repo":"can1357/oh-my-pi","slug":"tool-bridge-is-unavailable-in-this-kernel","errorCode":null,"errorMessage":"tool bridge is unavailable in this kernel","messagePattern":"tool bridge is unavailable in this kernel","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/eval/py/prelude.py","lineNumber":376,"sourceCode":"        current = data\n        for token_type, value in tokens:\n            if token_type == \"index\":\n                if not isinstance(current, list) or value >= len(current):\n                    return None\n                current = current[value]\n            elif token_type == \"key\":\n                if not isinstance(current, dict) or value not in current:\n                    return None\n                current = current[value]\n\n        return current\n\n    def _tool_proxy_from_env() -> tuple[str, str, str]:\n        base = os.environ.get(\"PI_TOOL_BRIDGE_URL\")\n        token = os.environ.get(\"PI_TOOL_BRIDGE_TOKEN\")\n        session = os.environ.get(\"PI_TOOL_BRIDGE_SESSION\")\n        if not base or not token or not session:\n            raise RuntimeError(\"tool bridge is unavailable in this kernel\")\n        return (base.rstrip(\"/\"), token, session)\n\n    import urllib.error, urllib.request\n\n    # urllib discovers environment and macOS SystemConfiguration proxies. This\n    # host-owned loopback endpoint must always connect directly.\n    _BRIDGE_OPENER = urllib.request.build_opener(urllib.request.ProxyHandler({}))\n\n    def _bridge_call(name: str, args: dict):\n        \"\"\"POST one request to the host tool bridge and return its `value`.\"\"\"\n        base, token, session = _tool_proxy_from_env()\n        _run_id_getter = globals().get(\"__omp_current_run_id__\")\n        _run_id = (\n            _run_id_getter()\n            if callable(_run_id_getter)\n            else globals().get(\"__omp_run_id__\")\n        )\n        payload = json.dumps(","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/eval/py/prelude.py#L358-L394","documentation":"The prelude's `tool` proxy forwards calls over an HTTP bridge to the host process, configured entirely through environment variables: `PI_TOOL_BRIDGE_URL`, `PI_TOOL_BRIDGE_TOKEN`, and `PI_TOOL_BRIDGE_SESSION`. This RuntimeError is raised when any of those variables is missing or empty, meaning the Python kernel was not launched with a live tool bridge (e.g. run outside the agent's eval harness).","triggerScenarios":"Calling any `tool.<name>(...)` from a Python kernel that wasn't spawned by the eval harness with bridge env vars injected, or after the host cleared/failed to set the env for the kernel process.","commonSituations":"Running the prelude in a plain `python`/REPL or notebook started manually; the host crashed or restarted and relaunched the kernel without the bridge env; env vars stripped by a wrapper (systemd, docker, CI sanitizer).","solutions":["Run the Python code through the agent's eval harness so the host injects the bridge env vars.","Verify the three variables exist in the kernel: `import os; print(bool(os.environ.get('PI_TOOL_BRIDGE_URL')), bool(os.environ.get('PI_TOOL_BRIDGE_TOKEN')), bool(os.environ.get('PI_TOOL_BRIDGE_SESSION')))`.","If running standalone, replace `tool.*` calls with local equivalents (direct file reads, local computation) instead of host tool calls."],"exampleFix":"// before\nresult = tool.read_file({\"path\": \"src/main.ts\"})  # fails outside harness\n\n// after\nimport os\nif os.environ.get(\"PI_TOOL_BRIDGE_URL\"):\n    result = tool.read_file({\"path\": \"src/main.ts\"})\nelse:\n    with open(\"src/main.ts\") as f:\n        result = f.read()","handlingStrategy":"fallback","validationCode":"import os\nbridge_ready = all(os.environ.get(k) for k in (\"PI_TOOL_BRIDGE_URL\", \"PI_TOOL_BRIDGE_TOKEN\", \"PI_TOOL_BRIDGE_SESSION\"))","typeGuard":null,"tryCatchPattern":"try:\n    result = tool.read_file({\"path\": p})\nexcept RuntimeError as e:\n    if \"tool bridge is unavailable\" in str(e):\n        result = local_read(p)  # local fallback","preventionTips":["Only use tool.* inside kernels spawned by the eval harness.","Check the three PI_TOOL_BRIDGE_* env vars before the first tool call and branch to a local path otherwise.","Beware wrappers (docker, CI, systemd) that strip environment variables from child processes."],"tags":["python","environment","missing-env-var","ipc"],"backgroundTag":"missing-env-var","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}