diff --git a/docs/advanced/configuration.mdx b/docs/advanced/configuration.mdx
index c245b364..29b003ec 100644
--- a/docs/advanced/configuration.mdx
+++ b/docs/advanced/configuration.mdx
@@ -33,6 +33,18 @@ Configure Strix using environment variables or a config file.
the LiteLLM and native OpenAI routing paths.
+
+ Extra fields merged into the JSON body of every request to the main model, as a JSON object
+ (e.g. `{"service_tier":"flex","safety_identifier":"9f86d081..."}`). Use it
+ for provider parameters Strix doesn't expose, such as OpenAI's `service_tier`
+ or `safety_identifier`. Applies to both the LiteLLM and native OpenAI routing
+ paths. Fields are not validated, so the provider or gateway must accept them;
+ unknown fields are usually rejected. Extra fields can override fields Strix
+ sends and break requests, so don't set request-shaping fields such as `model`, `messages`, `input`,
+ `tools` or `stream`, and use `STRIX_REASONING_EFFORT` rather than
+ `reasoning_effort`.
+
+
Request timeout in seconds for LLM calls.
@@ -88,6 +100,12 @@ affecting the agents that do the actual testing.
inherits `LLM_EXTRA_HEADERS`; set this when its endpoint needs custom headers.
+
+ Optional JSON object of extra request-body fields sent on every
+ deduplication-model request. A dedicated dedupe model never inherits
+ `LLM_EXTRA_BODY`; set this when its endpoint needs them too.
+
+
Reasoning effort for the deduplication model. Defaults to the model's own
baseline when unset.
diff --git a/docs/llm-providers/local.mdx b/docs/llm-providers/local.mdx
index 58b37509..cd2ca635 100644
--- a/docs/llm-providers/local.mdx
+++ b/docs/llm-providers/local.mdx
@@ -68,6 +68,21 @@ export LLM_API_KEY="your-bearer-token" # sent as Authorization: Bearer
export LLM_EXTRA_HEADERS='{"X-Feature-Key":"value","X-Tenant":"acme"}'
```
+### Extra request-body fields
+
+Some provider parameters go in the request body rather than a header, and
+Strix has no dedicated setting for them. Set them with `LLM_EXTRA_BODY` as a
+JSON object — they are merged into the body of every request to the model. For example, to
+use OpenAI's cheaper flex processing and attribute requests to a user with a
+safety identifier (a hash, never a raw email):
+
+```bash
+export LLM_EXTRA_BODY='{"service_tier":"flex","safety_identifier":"9f86d081884c7d65"}'
+```
+
+Fields aren't validated, so use only fields your provider accepts, and don't
+set fields Strix already sends, such as `model`, `messages` or `stream`.
+
For endpoints behind a private CA, point Strix at your certificate bundle with
the standard `SSL_CERT_FILE=/path/to/ca-bundle.pem` — never disable TLS
verification against a real endpoint.
diff --git a/strix/config/settings.py b/strix/config/settings.py
index 5aa6da06..b965281a 100644
--- a/strix/config/settings.py
+++ b/strix/config/settings.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Literal
+from typing import Any, Literal
from pydantic import AliasChoices, Field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
@@ -55,6 +55,11 @@ class LlmSettings(BaseSettings):
alias="LLM_EXTRA_HEADERS",
repr=False,
)
+ extra_body: dict[str, Any] | None = Field(
+ default=None,
+ alias="LLM_EXTRA_BODY",
+ repr=False,
+ )
reasoning_effort: ReasoningEffort = Field(default="high", alias="STRIX_REASONING_EFFORT")
force_required_tool_choice: bool = Field(
default=False,
@@ -110,6 +115,11 @@ class DedupeSettings(BaseSettings):
alias="DEDUPE_LLM_EXTRA_HEADERS",
repr=False,
)
+ extra_body: dict[str, Any] | None = Field(
+ default=None,
+ alias="DEDUPE_LLM_EXTRA_BODY",
+ repr=False,
+ )
@field_validator("reasoning_effort", mode="before")
@classmethod
diff --git a/strix/core/inputs.py b/strix/core/inputs.py
index c36f71b6..7bb2b72c 100644
--- a/strix/core/inputs.py
+++ b/strix/core/inputs.py
@@ -250,6 +250,7 @@ def make_model_settings(
request_timeout: float | None = None,
prompt_cache: bool = True,
extra_headers: dict[str, str] | None = None,
+ extra_body: dict[str, Any] | None = None,
has_tools: bool = True,
) -> ModelSettings:
headers = _request_headers(model_name, extra_headers)
@@ -259,13 +260,16 @@ def make_model_settings(
include_usage=True,
extra_args=request_timeout_extra_args(request_timeout),
extra_headers=headers,
+ extra_body=dict(extra_body) if extra_body else None,
)
if (
reasoning_effort is not None
and reasoning_effort != "none"
and model_supports_reasoning(model_name)
):
- model_settings = model_settings.resolve(_reasoning_settings(reasoning_effort))
+ model_settings = model_settings.resolve(
+ _reasoning_settings(reasoning_effort, extra_body),
+ )
if force_required_tool_choice and _accepts_required_tool_choice(model_name):
model_settings = model_settings.resolve(ModelSettings(tool_choice="required"))
@@ -290,7 +294,9 @@ def _request_headers(
return headers or None
-def _reasoning_settings(effort: ReasoningEffort) -> ModelSettings:
+def _reasoning_settings(
+ effort: ReasoningEffort, extra_body: dict[str, Any] | None = None
+) -> ModelSettings:
"""``max`` is not in the OpenAI SDK's ``Reasoning.effort`` enum, so send it as
a raw body field instead — also keeping it clear of LiteLLM's DeepSeek mapping,
which collapses every ``reasoning_effort`` level to plain thinking-enabled.
@@ -298,11 +304,13 @@ def _reasoning_settings(effort: ReasoningEffort) -> ModelSettings:
It goes in ``extra_body``, the field every model implementation forwards as the
request's ``extra_body``; the same value under ``extra_args`` collides with that
- keyword and raises before a request is ever sent.
+ keyword and raises before a request is ever sent. ``resolve`` replaces
+ ``extra_body`` wholesale, so the user's ``LLM_EXTRA_BODY`` fields are carried
+ over, with ``reasoning_effort`` taking precedence.
"""
if effort != "max":
return ModelSettings(reasoning=Reasoning(effort=effort))
- return ModelSettings(extra_body={"reasoning_effort": "max"})
+ return ModelSettings(extra_body={**(extra_body or {}), "reasoning_effort": "max"})
def _prompt_cache_extra_args(model_name: str) -> dict[str, Any] | None:
diff --git a/strix/core/runner.py b/strix/core/runner.py
index 048a59de..0df4a8d8 100644
--- a/strix/core/runner.py
+++ b/strix/core/runner.py
@@ -381,6 +381,7 @@ async def run_strix_scan(
request_timeout=settings.llm.timeout,
prompt_cache=settings.llm.prompt_cache,
extra_headers=settings.llm.extra_headers,
+ extra_body=settings.llm.extra_body,
)
run_config = RunConfig(
model=resolved_model,
diff --git a/strix/interface/main.py b/strix/interface/main.py
index cc3a0321..846a35da 100644
--- a/strix/interface/main.py
+++ b/strix/interface/main.py
@@ -164,12 +164,13 @@ async def warm_up_llm() -> None:
raw_model = dedupe_model
deduper = resolve_dedupe_model(settings.dedupe, dedupe_model)
# A dedicated dedupe model may route to another provider, which must
- # never receive the main endpoint's headers; it has its own
- # DEDUPE_LLM_EXTRA_HEADERS.
+ # never receive the main endpoint's headers or body fields; it has
+ # its own DEDUPE_LLM_EXTRA_HEADERS and DEDUPE_LLM_EXTRA_BODY.
await preflight_request(
deduper,
model_name=dedupe_model,
extra_headers=settings.dedupe.extra_headers,
+ extra_body=settings.dedupe.extra_body,
timeout=llm.preflight_timeout,
api_base_setting="DEDUPE_LLM_API_BASE",
)
diff --git a/strix/interface/scan_setup.py b/strix/interface/scan_setup.py
index 0af126d0..62176f76 100644
--- a/strix/interface/scan_setup.py
+++ b/strix/interface/scan_setup.py
@@ -116,6 +116,7 @@ async def preflight_model_connection(
model,
model_name=model_name,
extra_headers=resolved_settings.llm.extra_headers,
+ extra_body=resolved_settings.llm.extra_body,
timeout=resolved_settings.llm.preflight_timeout,
api_base_setting="LLM_API_BASE",
)
@@ -126,6 +127,7 @@ async def preflight_request(
*,
model_name: str,
extra_headers: dict[str, str] | None,
+ extra_body: dict[str, Any] | None,
timeout: int,
api_base_setting: str,
) -> None:
@@ -144,6 +146,7 @@ async def preflight_request(
request_timeout=timeout,
prompt_cache=False,
extra_headers=extra_headers,
+ extra_body=extra_body,
has_tools=False,
)
try:
diff --git a/strix/llm/compaction.py b/strix/llm/compaction.py
index ecdb9a83..6e40a433 100644
--- a/strix/llm/compaction.py
+++ b/strix/llm/compaction.py
@@ -307,6 +307,7 @@ async def _summarize(model: str, prompt: str, max_tokens: int) -> str | None:
request_timeout=llm.timeout,
prompt_cache=False,
extra_headers=llm.extra_headers,
+ extra_body=llm.extra_body,
has_tools=False,
).resolve(ModelSettings(max_tokens=max_tokens))
try:
diff --git a/strix/report/dedupe.py b/strix/report/dedupe.py
index 93f9ad8a..b1d3e537 100644
--- a/strix/report/dedupe.py
+++ b/strix/report/dedupe.py
@@ -39,11 +39,13 @@ def _dedupe_model_settings(
model_name=model_name,
force_required_tool_choice=False,
request_timeout=request_timeout,
- # The main model's headers apply only when dedupe falls back to the main
- # model; a dedicated dedupe model may route to another provider, which
- # must never receive the main endpoint's credentials. A dedicated model
- # gets its own DEDUPE_LLM_EXTRA_HEADERS instead.
+ # The main model's headers and body fields apply only when dedupe falls
+ # back to the main model; a dedicated dedupe model may route to another
+ # provider, which must never receive the main endpoint's credentials or
+ # identifiers. A dedicated model gets its own DEDUPE_LLM_EXTRA_HEADERS
+ # and DEDUPE_LLM_EXTRA_BODY instead.
extra_headers=dedupe.extra_headers if dedupe.model else llm.extra_headers,
+ extra_body=dedupe.extra_body if dedupe.model else llm.extra_body,
has_tools=False,
)
diff --git a/tests/test_compaction.py b/tests/test_compaction.py
index 2d73d9ac..edf31edb 100644
--- a/tests/test_compaction.py
+++ b/tests/test_compaction.py
@@ -147,7 +147,9 @@ def _patch_budget(monkeypatch: pytest.MonkeyPatch, *, keep_tokens: int, window:
context.auto_compact = True
settings = SimpleNamespace(
context=context,
- llm=SimpleNamespace(api_key=None, api_base=None, timeout=1, extra_headers=None),
+ llm=SimpleNamespace(
+ api_key=None, api_base=None, timeout=1, extra_headers=None, extra_body=None
+ ),
)
monkeypatch.setattr(compaction, "load_settings", lambda: settings)
@@ -228,7 +230,11 @@ async def test_summarize_routes_through_provider_with_settings(
"load_settings",
lambda: SimpleNamespace(
llm=SimpleNamespace(
- api_key=None, api_base=None, timeout=1, extra_headers={"X-Feature-Key": "svc"}
+ api_key=None,
+ api_base=None,
+ timeout=1,
+ extra_headers={"X-Feature-Key": "svc"},
+ extra_body={"service_tier": "flex"},
)
),
)
@@ -239,6 +245,7 @@ async def test_summarize_routes_through_provider_with_settings(
assert captured["model"] == "litellm/openai/some-model"
settings = captured["model_settings"]
assert settings.extra_headers == {"X-Feature-Key": "svc"}
+ assert settings.extra_body == {"service_tier": "flex"}
assert settings.max_tokens == 64
diff --git a/tests/test_dedupe_model.py b/tests/test_dedupe_model.py
index 809867b1..ab01345a 100644
--- a/tests/test_dedupe_model.py
+++ b/tests/test_dedupe_model.py
@@ -148,3 +148,42 @@ def test_config_file_loads_dedupe_model(
assert settings.dedupe.reasoning_effort == "minimal"
# Main model stays independent of the dedupe override.
assert settings.llm.model == "openai/root"
+
+
+def test_dedicated_dedupe_model_uses_own_body_fields_not_main(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv("LLM_EXTRA_BODY", json.dumps({"safety_identifier": "main"}))
+ loader._cached = None
+ try:
+ dedupe = DedupeSettings(
+ STRIX_DEDUPE_MODEL="deepseek/cheap",
+ DEDUPE_LLM_EXTRA_BODY={"service_tier": "flex"},
+ )
+ settings = _dedupe_model_settings(dedupe, "deepseek/cheap", 300)
+ assert settings.extra_body == {"service_tier": "flex"}
+ finally:
+ loader._cached = None
+
+
+def test_dedicated_dedupe_model_gets_no_main_body_fields_by_default(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv("LLM_EXTRA_BODY", json.dumps({"safety_identifier": "main"}))
+ loader._cached = None
+ try:
+ dedupe = DedupeSettings(STRIX_DEDUPE_MODEL="deepseek/cheap")
+ settings = _dedupe_model_settings(dedupe, "deepseek/cheap", 300)
+ assert settings.extra_body is None
+ finally:
+ loader._cached = None
+
+
+def test_fallback_dedupe_inherits_main_body_fields(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setenv("LLM_EXTRA_BODY", json.dumps({"safety_identifier": "main"}))
+ loader._cached = None
+ try:
+ settings = _dedupe_model_settings(DedupeSettings(), "openai/main-model", 300)
+ assert settings.extra_body == {"safety_identifier": "main"}
+ finally:
+ loader._cached = None
diff --git a/tests/test_inputs.py b/tests/test_inputs.py
index 2bdde73a..f54d3717 100644
--- a/tests/test_inputs.py
+++ b/tests/test_inputs.py
@@ -361,6 +361,58 @@ def test_make_model_settings_extra_headers_survive_reasoning_resolve() -> None:
assert settings.extra_headers == {"X-Feature-Key": "svc"}
+def test_make_model_settings_sets_extra_body() -> None:
+ settings = make_model_settings(
+ "none",
+ model_name="openai/gpt-5",
+ extra_body={"service_tier": "flex", "safety_identifier": "user-hash"},
+ )
+
+ assert settings.extra_body == {"service_tier": "flex", "safety_identifier": "user-hash"}
+
+
+def test_make_model_settings_omits_extra_body_when_unset() -> None:
+ assert make_model_settings("none", model_name="gpt-4o").extra_body is None
+
+
+def test_make_model_settings_extra_body_survives_reasoning_resolve() -> None:
+ settings = make_model_settings(
+ "high",
+ model_name="openai/o3",
+ extra_body={"service_tier": "flex"},
+ )
+
+ assert settings.extra_body == {"service_tier": "flex"}
+
+
+def test_make_model_settings_extra_body_merges_with_max_reasoning_field() -> None:
+ settings = make_model_settings(
+ "max",
+ model_name="deepseek/deepseek-v4-flash",
+ extra_body={"safety_identifier": "user-hash"},
+ )
+
+ assert settings.extra_body == {"safety_identifier": "user-hash", "reasoning_effort": "max"}
+
+
+def test_make_model_settings_max_reasoning_overrides_extra_body_reasoning_field() -> None:
+ settings = make_model_settings(
+ "max",
+ model_name="deepseek/deepseek-v4-flash",
+ extra_body={"reasoning_effort": "low"},
+ )
+
+ assert settings.extra_body == {"reasoning_effort": "max"}
+
+
+def test_make_model_settings_does_not_mutate_caller_extra_body() -> None:
+ extra_body = {"safety_identifier": "user-hash"}
+
+ make_model_settings("max", model_name="deepseek/deepseek-v4-flash", extra_body=extra_body)
+
+ assert extra_body == {"safety_identifier": "user-hash"}
+
+
def test_make_model_settings_timeout_survives_reasoning_resolve() -> None:
# Reasoning is resolved via ModelSettings.resolve(); the timeout in extra_args
# must not be dropped when a reasoning override is merged in.
diff --git a/tests/test_llm_extra_body.py b/tests/test_llm_extra_body.py
new file mode 100644
index 00000000..d5cfeddc
--- /dev/null
+++ b/tests/test_llm_extra_body.py
@@ -0,0 +1,97 @@
+"""Tests for LLM_EXTRA_BODY: extra fields merged into every LLM request body."""
+
+from __future__ import annotations
+
+import json
+from typing import TYPE_CHECKING, Any
+
+import httpx
+import litellm
+import openai
+import pytest
+from agents.extensions.models.litellm_model import LitellmModel
+from agents.models.interface import ModelTracing
+from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
+from agents.models.openai_responses import OpenAIResponsesModel
+
+from strix.config import loader
+from strix.config.loader import load_settings
+from strix.core.inputs import make_model_settings
+
+
+if TYPE_CHECKING:
+ from collections.abc import Iterator
+
+ from agents.models.interface import Model
+
+
+_EXTRA_BODY = {"service_tier": "flex", "safety_identifier": "user-hash"}
+
+
+@pytest.fixture(autouse=True)
+def _reset(monkeypatch: pytest.MonkeyPatch) -> Iterator[None]:
+ monkeypatch.delenv("LLM_EXTRA_BODY", raising=False)
+ monkeypatch.setattr(loader, "_cached", None)
+ monkeypatch.setattr(loader, "_override", None)
+ yield
+
+
+def test_extra_body_parsed_from_json_env(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setenv("LLM_EXTRA_BODY", json.dumps({"service_tier": "flex", "n": 1}))
+
+ assert load_settings().llm.extra_body == {"service_tier": "flex", "n": 1}
+
+
+async def _send(model: Model) -> None:
+ await model.get_response(
+ system_instructions=None,
+ input="Reply with just 'OK'.",
+ model_settings=make_model_settings(None, model_name="gpt-5", extra_body=_EXTRA_BODY),
+ tools=[],
+ output_schema=None,
+ handoffs=[],
+ tracing=ModelTracing.DISABLED,
+ previous_response_id=None,
+ conversation_id=None,
+ prompt=None,
+ )
+
+
+def _capturing_client(captured: dict[str, Any]) -> openai.AsyncOpenAI:
+ def handler(request: httpx.Request) -> httpx.Response:
+ captured.update(json.loads(request.content))
+ return httpx.Response(400, json={"error": {"message": "captured"}})
+
+ return openai.AsyncOpenAI(
+ api_key="test",
+ base_url="https://gateway.example/v1",
+ max_retries=0,
+ http_client=httpx.AsyncClient(transport=httpx.MockTransport(handler)),
+ )
+
+
+@pytest.mark.asyncio
+@pytest.mark.parametrize("model_cls", [OpenAIChatCompletionsModel, OpenAIResponsesModel])
+async def test_extra_body_reaches_native_openai_request_body(model_cls: type) -> None:
+ captured: dict[str, Any] = {}
+
+ with pytest.raises(openai.BadRequestError):
+ await _send(model_cls(model="gpt-5", openai_client=_capturing_client(captured)))
+
+ assert {k: captured.get(k) for k in _EXTRA_BODY} == _EXTRA_BODY
+
+
+@pytest.mark.asyncio
+async def test_extra_body_passed_to_litellm(monkeypatch: pytest.MonkeyPatch) -> None:
+ captured: dict[str, Any] = {}
+
+ async def fake_acompletion(**kwargs: Any) -> Any:
+ captured.update(kwargs)
+ raise RuntimeError("captured")
+
+ monkeypatch.setattr(litellm, "acompletion", fake_acompletion)
+
+ with pytest.raises(RuntimeError, match="captured"):
+ await _send(LitellmModel(model="openai/gpt-5", base_url="https://gateway.example/v1"))
+
+ assert captured["extra_body"] == _EXTRA_BODY
diff --git a/tests/test_preflight_timeout.py b/tests/test_preflight_timeout.py
index cf2192f8..6ca4cf77 100644
--- a/tests/test_preflight_timeout.py
+++ b/tests/test_preflight_timeout.py
@@ -60,6 +60,7 @@ def test_preflight_request_fails_after_its_own_timeout_with_a_clear_message() ->
model, # type: ignore[arg-type]
model_name="openai/gpt-4o",
extra_headers=None,
+ extra_body=None,
timeout=1,
api_base_setting="DEDUPE_LLM_API_BASE",
)
@@ -130,3 +131,52 @@ def test_warm_up_checks_the_dedupe_model_with_its_own_headers_and_the_preflight_
"DEDUPE_LLM_API_BASE",
]
assert calls[1][0] is dedupe_model
+
+
+def test_warm_up_checks_each_model_with_its_own_body_fields(
+ monkeypatch: pytest.MonkeyPatch, tmp_path: Path
+) -> None:
+ monkeypatch.setenv("STRIX_LLM", "openai/gpt-4o")
+ monkeypatch.setenv("LLM_API_KEY", "sk-test")
+ monkeypatch.setenv("LLM_EXTRA_BODY", '{"safety_identifier": "main"}')
+ monkeypatch.setenv("STRIX_DEDUPE_MODEL", "anthropic/claude-sonnet-4-5")
+ monkeypatch.setenv("DEDUPE_LLM_EXTRA_BODY", '{"service_tier": "flex"}')
+ _fresh_settings(monkeypatch, tmp_path)
+
+ calls: list[dict[str, Any]] = []
+
+ async def record(_model: Any, **kwargs: Any) -> None:
+ calls.append(kwargs)
+
+ monkeypatch.setattr(scan_setup, "preflight_request", record)
+ monkeypatch.setattr(cli_main, "preflight_request", record)
+ monkeypatch.setattr("strix.config.models.configure_sdk_model_defaults", lambda _settings: None)
+ monkeypatch.setattr("strix.report.dedupe.resolve_dedupe_model", lambda _dedupe, _name: object())
+
+ asyncio.run(cli_main.warm_up_llm())
+
+ assert [kwargs["extra_body"] for kwargs in calls] == [
+ {"safety_identifier": "main"},
+ {"service_tier": "flex"},
+ ]
+
+
+def test_preflight_request_sends_the_extra_body() -> None:
+ seen: list[Any] = []
+
+ class _Recorder:
+ async def get_response(self, *, model_settings: Any, **_: Any) -> None:
+ seen.append(model_settings.extra_body)
+
+ asyncio.run(
+ preflight_request(
+ _Recorder(), # type: ignore[arg-type]
+ model_name="openai/gpt-4o",
+ extra_headers=None,
+ extra_body={"safety_identifier": "main"},
+ timeout=5,
+ api_base_setting="LLM_API_BASE",
+ )
+ )
+
+ assert seen == [{"safety_identifier": "main"}]
diff --git a/tests/test_runner_interrupt.py b/tests/test_runner_interrupt.py
index 054f5b7a..b6271407 100644
--- a/tests/test_runner_interrupt.py
+++ b/tests/test_runner_interrupt.py
@@ -28,6 +28,7 @@ def _wire_runner(monkeypatch: pytest.MonkeyPatch, tmp_path: Any) -> None:
timeout=300,
prompt_cache=True,
extra_headers=None,
+ extra_body=None,
),
runtime=types.SimpleNamespace(max_context_images=3),
)
diff --git a/tests/test_runner_mcp.py b/tests/test_runner_mcp.py
index 25a5c888..cbcad7c7 100644
--- a/tests/test_runner_mcp.py
+++ b/tests/test_runner_mcp.py
@@ -32,6 +32,7 @@ def _settings() -> Any:
timeout=300,
prompt_cache=True,
extra_headers=None,
+ extra_body=None,
),
runtime=types.SimpleNamespace(max_context_images=3),
)
diff --git a/tests/test_runner_rate_limit.py b/tests/test_runner_rate_limit.py
index 3110ae2c..d6bad9ae 100644
--- a/tests/test_runner_rate_limit.py
+++ b/tests/test_runner_rate_limit.py
@@ -42,6 +42,7 @@ async def test_persistent_rate_limit_stops_gracefully(
timeout=300,
prompt_cache=True,
extra_headers=None,
+ extra_body=None,
),
runtime=types.SimpleNamespace(max_context_images=3),
)
diff --git a/tests/test_runner_root_prompt.py b/tests/test_runner_root_prompt.py
index e25d09ab..e4b4a58a 100644
--- a/tests/test_runner_root_prompt.py
+++ b/tests/test_runner_root_prompt.py
@@ -58,6 +58,7 @@ def _patch_engine_scaffold(
timeout=300,
prompt_cache=True,
extra_headers=None,
+ extra_body=None,
),
runtime=types.SimpleNamespace(max_context_images=3),
)
diff --git a/tests/test_runner_teardown.py b/tests/test_runner_teardown.py
index d7e9645d..e3c43696 100644
--- a/tests/test_runner_teardown.py
+++ b/tests/test_runner_teardown.py
@@ -52,6 +52,7 @@ def _settings() -> Any:
timeout=300,
prompt_cache=True,
extra_headers=None,
+ extra_body=None,
),
runtime=types.SimpleNamespace(max_context_images=3),
)