fix(api-server): pop runtime model before AIAgent kwargs unpack (#27540) - #27678
fix(api-server): pop runtime model before AIAgent kwargs unpack (#27540)#27678briandevans wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Fixes a crash in the API server agent creation path when fallback provider resolution supplies a runtime model override, ensuring model is not passed twice to AIAgent.
Changes:
- Pop
modelfrom runtime kwargs and treat it as an override for the gateway-resolved model. - Add regression tests covering both the override (fallback) and non-override (primary provider) paths.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| gateway/platforms/api_server.py | Prevents TypeError by removing model from runtime_kwargs before **-unpacking into AIAgent, optionally overriding the gateway model. |
| tests/gateway/test_api_server.py | Adds regression tests validating model override behavior and ensuring no duplicate-model crash. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
ffc4bd1 to
36b311a
Compare
|
Confirmed reproduction on a second environment + cherry-picked the patch successfully — sharing in case it helps push this through. Reproduction: Ubuntu 24.04 / Python 3.12, hermes-agent running as a long-lived systemd unit ( Patch verification: Cherry-picked the production change from this PR onto the VPS in-place. After
The On the red CI check: the failing test is Happy to keep running with the cherry-pick locally on production until this merges. Thanks for the fix. |
|
Additional production verification — Windows + Foundry broker through Tailscale-mesh reverse proxy on two machines, hermes-agent v0.14.0, Python 3.11.15. Cross-posting from my (now-closed) duplicate #31139: Repro before this fix: {"error": {"message": "Internal server error: run_agent.AIAgent() got multiple values for keyword argument 'model'", "type": "server_error", ...}}After cherry-picking #27678's {
"id": "chatcmpl-f67cabfe3f6146b1a870ab6b5ac54", "object": "chat.completion",
"created": 1779567828, "model": "hermes-agent",
"choices": [{"index": 0, "message": {"role": "assistant", "content": "pong"}, "finish_reason": "stop"}],
"usage": {"prompt_tokens": 14816, "completion_tokens": 29, "total_tokens": 14845}
}So adding to @andreab67's Ubuntu 24.04 confirmation: also works on Windows 11 Pro under the Foundry production deployment, across two independent machines. No regression observed against the existing model-name advertisement at If a regression test for the kwargs collision would help this PR through review, I have one ready ( |
36b311a to
a7a58af
Compare
|
Thanks @andreab67 and @Koraji95-coder — much appreciated. Rebased onto current main ( @Koraji95-coder — for the regression coverage, the PR already includes |
8cc4917 to
ba98d11
Compare
4a396c6 to
7f0d235
Compare
|
Closing to focus the queue on security/file-safety work where civilian merges are landing. Happy to reopen if maintainers want this picked up. |
|
Reopening — on reflection this is a P1 with two independent civilian production repros, which keeps it in the salvage-priority lane rather than dead-weight. Apologies for the churn. |
|
Housekeeping: closing to keep my open-PR set focused on actively-reviewed work. This has been open ~14d without maintainer review and the surrounding code has continued to move, so it's unlikely to land as-is. The underlying fix still stands — happy to reopen and rebase if it would be useful. Thanks! |
|
Reopening — closed this in error during queue housekeeping. This is in an active salvage niche (security / provider-SDK-drift / install-correctness / civilian-repro'd P1), not stale plumbing. Keeping it open. |
7f0d235 to
d4a759f
Compare
9083ea3 to
0731e2d
Compare
|
Thanks for the focused fix. I verified the premise against current main and do not see blocking problems. The current API server path still calls _resolve_runtime_agent_kwargs() at gateway/platforms/api_server.py:1033, resolves model separately at gateway/platforms/api_server.py:1035, then calls AIAgent(model=model, **runtime_kwargs) at gateway/platforms/api_server.py:1046-1048. The fallback resolver can return a runtime dict containing model at gateway/run.py:1388-1397, so the duplicate-keyword crash is still reachable. The proposed direction matches the existing native gateway path: _resolve_session_agent_runtime already pops runtime_kwargs.pop("model", None) and lets that model override at gateway/run.py:2825-2833; _resolve_turn_agent_config then builds a sanitized runtime dict without model at gateway/run.py:2893-2905. I also checked the named sibling Feishu path: gateway/platforms/feishu_comment.py:1074-1080 forwards individual runtime fields instead of **runtime_kwargs, so it does not have the same double-bind shape. Automated hermes-sweeper review. |
9a50db8 to
c09fcfe
Compare
|
Rebased onto current main — still conflict-free (mergeable/clean) and CI is fully green (0 failures across all checks). The fix is unchanged: it mirrors the established |
`_resolve_runtime_agent_kwargs()` can return a "model" key when the
primary provider auth fails and `_try_resolve_fallback_provider()` falls
through to a `fallback_providers[*]` entry (gateway/run.py:750). The
gateway path already handles this correctly via
`runtime_kwargs.pop("model", None)` at gateway/run.py:1867. The
api_server platform path was missing that pop, so on the first turn
after fallback kicks in:
agent = AIAgent(
model=model,
**runtime_kwargs, # also contains "model" from the fallback path
...
)
raises `TypeError: AIAgent() got multiple values for keyword argument
'model'` and every subsequent turn in the session fails the same way
until restart.
Mirror the established gateway/run.py pattern: pop "model" from
runtime_kwargs, log the override, and let the runtime model win — same
semantics so the API server platform behaves consistently with the
Telegram/Discord/Slack path.
Two regression tests in `TestAdapterInit`:
- runtime returns "model" → AIAgent constructed with the runtime model,
no TypeError (the NousResearch#27540 reproduction).
- runtime omits "model" → gateway-resolved model passes through unchanged
(the common-case happy path).
Fixes NousResearch#27540
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
c09fcfe to
d842575
Compare
|
Closing — issue #27540 could not be reproduced on current |
What does this PR do?
The api_server gateway adapter crashes with
TypeError: AIAgent() got multiple values for keyword argument 'model'on the first turn after a fallback provider takes over._try_resolve_fallback_provider()returns a"model"key in its kwargs dict, but_create_agent()was**-unpacking that dict alongside an explicitmodel=argument. This PR pops"model"fromruntime_kwargsfirst and treats it as an override for the gateway-resolved model — mirroring the canonicalruntime_kwargs.pop("model", None)pattern already used inGatewayRunner._resolve_model_runtime(gateway/run.py:1867). With the pop, the fallback's model wins, there's no double-bind, and the override path is logged.Related Issue
Fixes #27540
Type of Change
Changes Made
gateway/platforms/api_server.py— in_create_agent,runtime_model = runtime_kwargs.pop("model", None); if present, log"API server: runtime provider supplied explicit model override: %s -> %s"andmodel = runtime_modelbefore theAIAgent(model=model, **runtime_kwargs, ...)call. MirrorsGatewayRunner._resolve_model_runtime(gateway/run.py:1866-1874).tests/gateway/test_api_server.py— newtest_create_agent_handles_runtime_model_override_from_fallback(runtime returns{"model": "openai/gpt-5", "provider": "openrouter", ...}→_create_agent()must not raise,AIAgent(model=...)receives the fallback model). Plus happy-pathtest_create_agent_keeps_gateway_model_when_runtime_omits_model(runtime omits"model"→ gateway-resolved model passes through unchanged).How to Test
uv run --with pytest --with pytest-xdist --with pytest-asyncio python3 -m pytest tests/gateway/test_api_server.py tests/gateway/test_api_server_runs.py -v— 173 passed.test_create_agent_handles_runtime_model_override_from_fallbackreproduces the exactTypeError: ... got multiple values for keyword argument 'model'from the issue. With the fix applied, all 3test_create_agent_*tests pass.Checklist
Code
fix(scope):,feat(scope):, etc.)Documentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/ASibling Audit