diff --git a/CHANGELOG.md b/CHANGELOG.md index 286a5784d..e5b978224 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Fix streaming tool calls dropped when provider sends empty-string `id` in subsequent chunks (e.g. DashScope/Qwen Cloud). - Truncate oversized failed tool output, preserving full logs on disk instead of overflowing the model context. - Honor model output limits in OpenAI-compatible Chat Completions and Ollama requests while preserving `extraPayload` overrides. +- Respect `maxSteps` in Markdown agent definitions. ## 0.147.3 diff --git a/src/eca/features/agents.clj b/src/eca/features/agents.clj index 1a964feb0..ddb396fcb 100644 --- a/src/eca/features/agents.clj +++ b/src/eca/features/agents.clj @@ -105,8 +105,9 @@ nil))) (defn ^:private md->agent-config - [{:keys [description mode model steps tools body inherit spawnableBy disabledTools]}] - (let [tools-map (normalize-tools tools) + [{:keys [description mode model maxSteps steps tools body inherit spawnableBy disabledTools]}] + (let [max-steps (or maxSteps steps) + tools-map (normalize-tools tools) spawnable-by (normalize-spawnable-by spawnableBy) disabled-tools (normalize-disabled-tools disabledTools)] (cond-> {} @@ -118,7 +119,7 @@ (mapv str mode) (str mode))) model (assoc :defaultModel (str model)) - steps (assoc :maxSteps (long steps)) + max-steps (assoc :maxSteps (long max-steps)) (seq body) (assoc :systemPrompt body) tools-map (assoc :toolCall (cond-> {:approval {}} diff --git a/test/eca/features/agents_test.clj b/test/eca/features/agents_test.clj index 9ceaf1f22..1851197ad 100644 --- a/test/eca/features/agents_test.clj +++ b/test/eca/features/agents_test.clj @@ -62,7 +62,7 @@ "description: You sleep one second when asked\n" "mode: subagent\n" "model: my-org-anthropic/sonnet-4.5\n" - "steps: 5\n" + "maxSteps: 5\n" "tools:\n" " byDefault: ask\n" " deny:\n" @@ -84,6 +84,11 @@ :deny {"foo" {}}}}} config)))) + (testing "maxSteps takes precedence over the legacy steps alias" + (is (= 7 + (:maxSteps (#'agents/md->agent-config {:maxSteps 7 + :steps 3}))))) + (testing "tool entries with regex patterns" (let [parsed {:tools {"byDefault" "ask" "allow" ["eca__shell_command(npm run .*)"