From 6fd956411b7a944ca8f22d849938f29f490ad3fe Mon Sep 17 00:00:00 2001 From: Doron Chen Date: Mon, 10 Aug 2026 21:09:41 +0300 Subject: [PATCH 1/2] fix(open-interpreter): don't double-prefix provider-scoped EVAL_MODEL interpreter.llm.model unconditionally prepended "openai/", so an EVAL_MODEL that already carries a routing prefix (e.g. gcp/gemini-3.5-flash-lite) became malformed (openai/gcp/...). Guard matches the pattern already used by terminus-2 and openhands. Checked against: .agents/gateways/RULES.md rule 23 (EVAL_MODEL is a bare, opaque handle that MAY already carry a provider prefix). Co-Authored-By: Claude Sonnet 5 Signed-off-by: Doron Chen --- containers/agents/open-interpreter/run_oi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/containers/agents/open-interpreter/run_oi.py b/containers/agents/open-interpreter/run_oi.py index f07492f9..47e11b70 100644 --- a/containers/agents/open-interpreter/run_oi.py +++ b/containers/agents/open-interpreter/run_oi.py @@ -5,7 +5,8 @@ interpreter.llm.api_base = os.environ.get("OPENAI_BASE_URL", "http://model:4000") interpreter.llm.api_key = os.environ.get("OPENAI_API_KEY", "sk-proxy") -interpreter.llm.model = "openai/" + os.environ.get("EVAL_MODEL", "default") +model = os.environ.get("EVAL_MODEL", "default") +interpreter.llm.model = model if "/" in model else f"openai/{model}" interpreter.auto_run = True interpreter.offline = False interpreter.disable_telemetry = True From 87a0febae10ab3bfb5d90945a875b22082d4cf87 Mon Sep 17 00:00:00 2001 From: Elron Bandel Date: Wed, 12 Aug 2026 14:17:52 +0300 Subject: [PATCH 2/2] fix(open-interpreter): force the openai wire explicitly, read $MODEL not $EVAL_MODEL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two issues found while reviewing/verifying #339: 1. run-agent's env -i allow-list forwards only MODEL to the agent process — EVAL_MODEL is scrubbed away (same contract zerostack already follows, same bug #320/#334 fixed in ten other agents). run_oi.py read EVAL_MODEL directly with no Dockerfile-level shim, so it always fell back to the literal string "default" regardless of #339's guard fix. 2. #339's "/" guard (copied from openhands/terminus-2's old pattern) does not actually work for provider-scoped handles. Verified live: a handle like gcp/gemini-3.5-flash-lite skips the openai/ prefix (as intended) but then reaches litellm.completion() unmodified, and litellm tries to resolve "gcp" as a real provider name (it isn't — litellm's name for it is vertex_ai) and raises BadRequestError: LLM Provider NOT provided. Reproduced the exact crash #339 was supposed to prevent. open-interpreter's Llm class has no field for litellm's custom_llm_provider (unlike terminus-2/harbor's LiteLLM wrapper, see #348 — same underlying issue, same fix approach). Fixed by wrapping llm.completions (a plain function forwarding **params to litellm.completion(**params)) to inject custom_llm_provider="openai" regardless of what the handle carries. Verified live against a capturing mock: bare handle and provider-prefixed handle (gcp/...) both now reach the wire unmodified, no crash, in both cases before this fix would either mangle the model name (#339's original bug) or crash outright (the case #339's own fix introduced). Signed-off-by: Elron Bandel --- containers/agents/open-interpreter/run_oi.py | 26 ++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/containers/agents/open-interpreter/run_oi.py b/containers/agents/open-interpreter/run_oi.py index 47e11b70..6c4cdd25 100644 --- a/containers/agents/open-interpreter/run_oi.py +++ b/containers/agents/open-interpreter/run_oi.py @@ -5,8 +5,30 @@ interpreter.llm.api_base = os.environ.get("OPENAI_BASE_URL", "http://model:4000") interpreter.llm.api_key = os.environ.get("OPENAI_API_KEY", "sk-proxy") -model = os.environ.get("EVAL_MODEL", "default") -interpreter.llm.model = model if "/" in model else f"openai/{model}" +# EVAL_MODEL/MODEL is a bare, opaque handle that may already carry a routing +# prefix like `aws/claude-opus-4-8` or `gcp/gemini-3.5-flash-lite` (gateways/ +# RULES.md: "MUST NOT split EVAL_MODEL to infer a provider or wire protocol"). +# open-interpreter's Llm class has no field for litellm's custom_llm_provider +# (unlike terminus-2/harbor's LiteLLM wrapper), so a "/" in the handle reaches +# litellm.completion() unmodified and litellm tries to resolve it as a real +# provider name — "gcp"/"aws" aren't litellm provider names (those are +# "vertex_ai"/"bedrock"), so it raises BadRequestError: LLM Provider NOT +# provided. Force the wire explicitly by wrapping llm.completions (a plain +# function reference forwarding **params to litellm.completion(**params)) +# to inject custom_llm_provider="openai" regardless of what the handle +# carries — same fix as #348 (terminus-2), applied via a wrapper since +# open-interpreter has no dedicated field for it. +model = os.environ.get("MODEL", "default") +interpreter.llm.model = model +_completions = interpreter.llm.completions + + +def _completions_via_openai_wire(**params): + params.setdefault("custom_llm_provider", "openai") + yield from _completions(**params) + + +interpreter.llm.completions = _completions_via_openai_wire interpreter.auto_run = True interpreter.offline = False interpreter.disable_telemetry = True