To upvote this issue, give it a thumbs up. See this list for the most upvoted issues.
Please avoid AI slops, be concise, and focus on what matters for this issue.
Describe the bug
Getting this error only on 4.7+:
Bedrock response status: 400 body: {"message":"The model returned the following errors: \"thinking.type.enabled\" is not supported for this model. Use \"thinking.type.adaptive\" and \"output_config.effort\" to control thinking behavior."}
Believe it's due to this section where 'enabled' is hardcoded: https://github.com/editor-code-assistant/eca/blame/b986a52a7c73b6bddcbc190fb70ea1bf5b6cc7be/src/eca/llm_providers/bedrock.clj#L162
<=4.6 all work as expected.
To Reproduce
Steps to reproduce the behavior:
Configure ECA with this config file:
{
"providers": {
"bedrock": {
"api": "bedrock",
"url": "https://bedrock-runtime.us-east-1.amazonaws.com",
"key": "...",
"models": {
"us.anthropic.claude-opus-4-6-v1": {},
"us.anthropic.claude-opus-4-7": {},
"us.anthropic.claude-opus-4-8": {},
"us.anthropic.claude-opus-4-5-20251101-v1:0": {},
"us.anthropic.claude-sonnet-4-5-20250929-v1:0": {},
"us.anthropic.claude-haiku-4-5-20251001-v1:0": {}
}
}
}
}
Expected behavior
4.7+ should work like they do in the default Anthropic API integration section, with different possible variants:
|
(def ^:private anthropic-variants |
|
{"low" {:output_config {:effort "low"} :thinking {:type "adaptive"}} |
|
"medium" {:output_config {:effort "medium"} :thinking {:type "adaptive"}} |
|
"high" {:output_config {:effort "high"} :thinking {:type "adaptive"}} |
|
"max" {:output_config {:effort "max"} :thinking {:type "adaptive"}}}) |
|
|
|
(def ^:private anthropic-v2-variants |
|
{"default" {:thinking {:type "adaptive" :display "summarized"}} |
|
"low" {:output_config {:effort "low"} :thinking {:type "adaptive" :display "summarized"}} |
|
"medium" {:output_config {:effort "medium"} :thinking {:type "adaptive" :display "summarized"}} |
|
"high" {:output_config {:effort "high"} :thinking {:type "adaptive" :display "summarized"}} |
|
"xhigh" {:output_config {:effort "xhigh"} :thinking {:type "adaptive" :display "summarized"}} |
|
"max" {:output_config {:effort "max"} :thinking {:type "adaptive" :display "summarized"}}}) |
I was able to bypass this failure with a small change to how config resolution works for Bedrock, and an updated config, but In don't know if this is the correct way forwards here (it'd be great to be able to select different effort amounts in the UI):
modified src/eca/llm_providers/bedrock.clj
@@ -152,22 +152,31 @@
(defn ^:private build-body
[{:keys [messages instructions max-output-tokens tools reason? extra-payload]}]
- (shared/deep-merge
- (assoc-some
- {:messages messages
- :inferenceConfig {:maxTokens (or max-output-tokens default-max-output-tokens)}}
- :system (when-not (string/blank? instructions) [{:text instructions}])
- :toolConfig (->tool-config tools)
- :additionalModelRequestFields (when reason?
- {:reasoning_config {:type "enabled"
- :budget_tokens default-reasoning-budget-tokens}}))
- ;; Drop a reasoning_config smuggled through extraPayload when the caller
- ;; didn't request reasoning — otherwise it would silently re-enable it,
- ;; since the generic reasoning-key strip in llm-api doesn't cover Bedrock.
- (cond-> (select-keys extra-payload allowed-extra-payload-keys)
- (and (not reason?)
- (get-in extra-payload [:additionalModelRequestFields :reasoning_config]))
- (update :additionalModelRequestFields dissoc :reasoning_config))))
+ (let [filtered-extra (cond-> (select-keys extra-payload allowed-extra-payload-keys)
+ (and (not reason?)
+ (get-in extra-payload [:additionalModelRequestFields :reasoning_config]))
+ (update :additionalModelRequestFields dissoc :reasoning_config))
+ ;; When extra-payload supplies its own reasoning_config, use it as-is
+ ;; rather than deep-merging with the default. Models disagree on which
+ ;; keys are valid (e.g. "adaptive" rejects budget_tokens).
+ extra-reasoning (get-in filtered-extra [:additionalModelRequestFields :reasoning_config])
+ default-reasoning (when reason?
+ {:type "enabled"
+ :budget_tokens default-reasoning-budget-tokens})
+ reasoning-config (if extra-reasoning
+ extra-reasoning
+ default-reasoning)]
+ (shared/deep-merge
+ (assoc-some
+ {:messages messages
+ :inferenceConfig {:maxTokens (or max-output-tokens default-max-output-tokens)}}
+ :system (when-not (string/blank? instructions) [{:text instructions}])
+ :toolConfig (->tool-config tools)
+ :additionalModelRequestFields (when reasoning-config
+ {:reasoning_config reasoning-config}))
+ (cond-> filtered-extra
+ extra-reasoning
+ (update :additionalModelRequestFields dissoc :reasoning_config)))))
;; --- AWS event-stream (vnd.amazon.eventstream) binary decoder ---
modified test/eca/llm_providers/bedrock_test.clj
@@ -124,7 +124,8 @@
body))))
(testing "reasoning adds reasoning_config to additionalModelRequestFields"
- (is (match? {:additionalModelRequestFields {:reasoning_config {:type "enabled"}}}
+ (is (match? {:additionalModelRequestFields {:reasoning_config {:type "enabled"
+ :budget_tokens 2048}}}
(#'llm-providers.bedrock/build-body {:messages [] :reason? true}))))
(testing "extra-payload cannot re-enable reasoning when reason? is false"
@@ -137,14 +138,14 @@
(is (nil? (get-in body [:additionalModelRequestFields :reasoning_config])))
(is (= "bar" (get-in body [:additionalModelRequestFields :foo])))))
- (testing "extra-payload reasoning_config is preserved when reason? is true"
- (is (match? {:additionalModelRequestFields {:reasoning_config {:budget_tokens 1024}}}
- (#'llm-providers.bedrock/build-body
- {:messages []
- :reason? true
- :extra-payload {:additionalModelRequestFields
- {:reasoning_config {:budget_tokens 1024}}}})))))
-
+ (testing "extra-payload reasoning_config fully replaces default when reason? is true"
+ (let [body (#'llm-providers.bedrock/build-body
+ {:messages []
+ :reason? true
+ :extra-payload {:additionalModelRequestFields
+ {:reasoning_config {:type "adaptive"}}}})]
+ (is (= {:type "adaptive"}
+ (get-in body [:additionalModelRequestFields :reasoning_config]))))))
;; --- chat! non-streaming ---
(deftest chat!-non-streaming-test
and config.json model section:
"models": {
"us.anthropic.claude-opus-4-6-v1": {},
"us.anthropic.claude-opus-4-7": {
"extraPayload": {
"additionalModelRequestFields": {
"reasoning_config": {
"type": "adaptive"
},
"output_config": { "effort": "high" }
}
}
},
"us.anthropic.claude-opus-4-8": {},
"us.anthropic.claude-opus-4-5-20251101-v1:0": {},
"us.anthropic.claude-sonnet-4-5-20250929-v1:0": {},
"us.anthropic.claude-haiku-4-5-20251001-v1:0": {}
}
Doctor
Paste the relevant parts of /doctor command from chat if applicable:
ECA version: 0.140.0
... leaving out these sections due to paths and such I don't want to leak ...
Logged providers: None
Relevant env vars:
Credential files: None found
Screenshots
If applicable, add screenshots to help explain your problem.
Additional context
Add any other context about the problem here.
To upvote this issue, give it a thumbs up. See this list for the most upvoted issues.
Please avoid AI slops, be concise, and focus on what matters for this issue.
Describe the bug
Getting this error only on 4.7+:
Believe it's due to this section where 'enabled' is hardcoded: https://github.com/editor-code-assistant/eca/blame/b986a52a7c73b6bddcbc190fb70ea1bf5b6cc7be/src/eca/llm_providers/bedrock.clj#L162
<=4.6 all work as expected.
To Reproduce
Steps to reproduce the behavior:
Configure ECA with this config file:
Expected behavior
4.7+ should work like they do in the default Anthropic API integration section, with different possible variants:
eca/src/eca/config.clj
Lines 66 to 78 in b986a52
I was able to bypass this failure with a small change to how config resolution works for Bedrock, and an updated config, but In don't know if this is the correct way forwards here (it'd be great to be able to select different effort amounts in the UI):
and
config.jsonmodel section:Doctor
Paste the relevant parts of
/doctorcommand from chat if applicable:Screenshots
If applicable, add screenshots to help explain your problem.
Additional context
Add any other context about the problem here.