Summary
docker-agent does not include a tool_choice field in its Chat Completions API requests, even when tools is present. The OpenAI spec treats omission of tool_choice as implying "auto", so this is technically valid — but strict OpenAI-compatible gateway implementations (notably LiteLLM-based proxies) require the field to be explicitly present and reject requests with a 400 Bad Request when it is absent.
Error
HTTP 400: litellm.BadRequestError: BedrockException -
{"message":"The model returned the following errors: tool_choice.type: Field required"}
This error occurs on every request where tools are present, exhausting all fallback models since the validation fires before the model is reached.
Root Cause
In pkg/model/provider/openai/client.go, ChatCompletionNewParams is built without setting ToolChoice. When the request reaches a LiteLLM gateway that enforces strict Pydantic validation, the missing field causes a 400 rejection.
Per the OpenAI spec, omitting tool_choice is equivalent to "auto" — but LiteLLM in certain configurations requires the object form explicitly:
```json
"tool_choice": { "type": "auto" }
```
Proposed Fix
Explicitly send "tool_choice": "auto" whenever tools is non-empty in the request. This is:
- Spec-compliant — it matches the OpenAI default behavior exactly
- Backwards-compatible — no behavior change for gateways that already handle omission correctly
- Safe for the agentic loop —
"auto" preserves the model's autonomy to decide when to call tools
Optionally, expose a tool_choice: field in the model config schema (alongside the existing parallel_tool_calls) for users who need to override the value.
Workarounds
- Gateway side: Add
drop_params: true to LiteLLM's general_settings to silently accept requests missing optional fields
- Client side: None currently available in
agent.yaml — provider_opts does not forward tool_choice
Environment
- docker-agent version: v1.59.0
- Gateway: LiteLLM proxy (OpenAI-compatible) in front of AWS Bedrock
- All models affected (validation fires before model routing)
Summary
docker-agentdoes not include atool_choicefield in its Chat Completions API requests, even whentoolsis present. The OpenAI spec treats omission oftool_choiceas implying"auto", so this is technically valid — but strict OpenAI-compatible gateway implementations (notably LiteLLM-based proxies) require the field to be explicitly present and reject requests with a400 Bad Requestwhen it is absent.Error
HTTP 400: litellm.BadRequestError: BedrockException -
{"message":"The model returned the following errors: tool_choice.type: Field required"}
This error occurs on every request where tools are present, exhausting all fallback models since the validation fires before the model is reached.
Root Cause
In
pkg/model/provider/openai/client.go,ChatCompletionNewParamsis built without settingToolChoice. When the request reaches a LiteLLM gateway that enforces strict Pydantic validation, the missing field causes a400rejection.Per the OpenAI spec, omitting
tool_choiceis equivalent to"auto"— but LiteLLM in certain configurations requires the object form explicitly:```json
"tool_choice": { "type": "auto" }
```
Proposed Fix
Explicitly send
"tool_choice": "auto"whenevertoolsis non-empty in the request. This is:"auto"preserves the model's autonomy to decide when to call toolsOptionally, expose a
tool_choice:field in the model config schema (alongside the existingparallel_tool_calls) for users who need to override the value.Workarounds
drop_params: trueto LiteLLM'sgeneral_settingsto silently accept requests missing optional fieldsagent.yaml—provider_optsdoes not forwardtool_choiceEnvironment