Skip to content

fix: tolerate extra agent tool fields - #2128

Merged
yohamta0 merged 2 commits into
mainfrom
codex/agent-tool-lenient-inputs
May 8, 2026
Merged

yohamta0 merged 2 commits into
mainfrom
codex/agent-tool-lenient-inputs

Conversation

@yohamta0

@yohamta0 yohamta0 commented May 8, 2026 •

Copy link
Copy Markdown
Member

Summary

  • make built-in AI-agent tool argument decoding tolerant of unknown and irrelevant fields
  • stop rejecting patch calls that include stale operation-specific fields, while preserving required-field and safety validation
  • update the agent prompt and regression tests so all registered tool schemas remain extra-field compatible

Testing

  • go test ./internal/agent -count=1

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Tool input parsing now gracefully handles extra or unused fields instead of rejecting them, making tools more flexible and forgiving of API variations.
  • Improvements

    • Patch tool now ignores unused operation-specific properties in JSON input rather than failing validation, simplifying successful patch operations.

@coderabbitai

coderabbitai Bot commented May 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 36ea064a-4c48-44ab-a1bd-c376d938b399

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces lenient JSON input decoding for all agent tool handlers. A new decodeToolInput helper treats unknown fields as optional and tolerates malformed input, then systematically replaces strict json.Unmarshal calls across fifteen tool handlers. The patch tool's field validation is relaxed to focus on required-field presence and type correctness rather than rejecting unused fields.

Changes

Lenient Tool Input Decoding

Layer / File(s) Summary
Decoding Infrastructure
internal/agent/tools.go
New decodeToolInput function parses JSON permissively: normalizes empty input to {}, uses reflection to populate struct fields from JSON field names, and ignores unknown/malformed optional fields. New jsonFieldName helper derives field names from struct tags with - skip support.
Decoding Tests
internal/agent/tools_test.go
TestDecodeToolInput verifies lenient behavior: unknown fields are silently ignored, malformed required fields produce zero values without error, and invalid JSON surfaces errors.
Schema Validation
internal/agent/tool_registry_test.go
New TestRegisteredTools_SchemasDoNotRejectExtraFields ensures every registered tool's JSON schema does not set additionalProperties to false, enabling lenient decoding without schema conflicts.
Patch Tool Validation
internal/agent/patch.go
patchRun switches to decodeToolInput; validateRequiredFields now explicitly unmarshals required fields as strings and validates presence/type/blank-ness, while unused operation-specific fields are no longer explicitly rejected.
Patch Tool Tests
internal/agent/patch_test.go
Test expectations updated to assert lenient behavior: unused/irrelevant operation-specific fields (including null, empty strings, and malformed structures) are now ignored and patches still apply correctly for create, replace, insert_after, and delete operations.
Tool Handler Migration
internal/agent/ask_user.go, bash.go, dag_def_manage.go, dag_run_manage.go, delegate.go, navigate.go, output.go, policy.go, read.go, remote_agent.go, remote_list.go, runbook_manage.go, session_search.go, web_tools.go
All thirteen tools switch from direct json.Unmarshal to decodeToolInput for input parsing, preserving downstream error handling and business logic while gaining lenient field tolerance.
Documentation
internal/agent/system_prompt.txt
System prompt updated to reflect lenient patch tool behavior and current tool-use guidance for the agent.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • dagucloud/dagu#2118: Both PRs modify patch validation logic—this PR adds lenient field handling via decodeToolInput, while the retrieved PR adds stricter atomic writes and mode preservation.
  • dagucloud/dagu#2119: Both PRs update web_tools.go input parsing to use decodeToolInput for the web_search and web_extract tools.
  • dagucloud/dagu#2112: Both PRs modify runbook_manage.go—the retrieved PR introduces the tool and this PR updates its JSON parsing to use decodeToolInput.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: making agent tool fields toleration of extra inputs, which is the primary objective of this PR.
Description check ✅ Passed The description covers the main objectives (lenient input decoding, preserving validation) and includes testing approach, but lacks structured sections matching the template.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/agent-tool-lenient-inputs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/agent/tools.go`:
- Line 106: The code currently swallows json.Unmarshal errors for matched fields
(the call using json.Unmarshal(raw, field.Addr().Interface())), which hides
type/parse failures; change it to capture the error (err := json.Unmarshal(...))
and propagate or handle it per-field: if the struct field/tag indicates leniency
(e.g., a custom tag like `lenient:"true"` on the reflected field) then
log/ignore the error and continue, otherwise return or wrap and return the error
with context (include the field.Name and raw payload) so callers can fail fast;
update the reflection code that examines field (the variable named field and
raw) to read the tag and branch accordingly instead of using `_ =
json.Unmarshal(...)`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dd4f2dbc-d0f6-43cc-a42c-64986395a075

📥 Commits

Reviewing files that changed from the base of the PR and between 9b28d5e and c2dcd26.

📒 Files selected for processing (20)
  • internal/agent/ask_user.go
  • internal/agent/bash.go
  • internal/agent/dag_def_manage.go
  • internal/agent/dag_run_manage.go
  • internal/agent/delegate.go
  • internal/agent/navigate.go
  • internal/agent/output.go
  • internal/agent/patch.go
  • internal/agent/patch_test.go
  • internal/agent/policy.go
  • internal/agent/read.go
  • internal/agent/remote_agent.go
  • internal/agent/remote_list.go
  • internal/agent/runbook_manage.go
  • internal/agent/session_search.go
  • internal/agent/system_prompt.txt
  • internal/agent/tool_registry_test.go
  • internal/agent/tools.go
  • internal/agent/tools_test.go
  • internal/agent/web_tools.go

Comment thread internal/agent/tools.go Outdated
if !field.CanSet() {
continue
}
_ = json.Unmarshal(raw, field.Addr().Interface())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Do not silently drop decode errors for known fields

At Line 106, unmarshal errors are ignored for every matched field. That also suppresses type errors on fields the selected action actually depends on, coercing malformed inputs to zero values and weakening parse/type guarantees. Consider making leniency opt-in per field/action instead of global.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/agent/tools.go` at line 106, The code currently swallows
json.Unmarshal errors for matched fields (the call using json.Unmarshal(raw,
field.Addr().Interface())), which hides type/parse failures; change it to
capture the error (err := json.Unmarshal(...)) and propagate or handle it
per-field: if the struct field/tag indicates leniency (e.g., a custom tag like
`lenient:"true"` on the reflected field) then log/ignore the error and continue,
otherwise return or wrap and return the error with context (include the
field.Name and raw payload) so callers can fail fast; update the reflection code
that examines field (the variable named field and raw) to read the tag and
branch accordingly instead of using `_ = json.Unmarshal(...)`.

@yohamta0
yohamta0 merged commit 1e361ce into main May 8, 2026
10 checks passed
@yohamta0
yohamta0 deleted the codex/agent-tool-lenient-inputs branch May 8, 2026 07:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant