Skip to content

Sanitize malformed tool-call inputs before sending agent history to Anthropic#2378

Open
RNViththagan wants to merge 2 commits into
wso2:release/ballerina-5.12.xfrom
RNViththagan:fix/copilot-tool-input-object
Open

Sanitize malformed tool-call inputs before sending agent history to Anthropic#2378
RNViththagan wants to merge 2 commits into
wso2:release/ballerina-5.12.xfrom
RNViththagan:fix/copilot-tool-input-object

Conversation

@RNViththagan

@RNViththagan RNViththagan commented Jun 22, 2026

Copy link
Copy Markdown
Member

Related to wso2/product-integrator#1741

Sometimes a tool call's input comes back as a string instead of an object — the SDK keeps the raw text when the JSON is invalid. Anthropic then rejects every following request in that chat with tool_use.input: Input should be an object, leaving the thread permanently stuck.

This is a workaround for the issue at the client side — it sanitizes the history before sending it to the provider so already-poisoned threads stop 400-ing. The root cause (the model producing invalid JSON for the tool call) is a separate follow-up.

  • Add sanitizeMessages, which fixes up any such tool-call input (parse it if possible, otherwise drop it to {}) before history is sent to the model
  • Run it on both paths that send history to the provider — during a turn and when loading past chat
  • Safe for healthy chats: clean history is left untouched, and the affected calls had already failed
  • Add unit tests for the sanitization

Summary by CodeRabbit

  • New Features

    • Added message sanitization to ensure AI message histories are properly formatted for provider compatibility, automatically repairing malformed tool-call inputs in chat history replay scenarios.
  • Tests

    • Added comprehensive unit tests to verify message sanitization and repair functionality works correctly across various malformed input scenarios.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

A new resilience/messageSanitization.ts module is added with repairToolCallInputs and sanitizeMessages functions that detect and coerce string-typed tool_use.input fields back into objects. These are wired into AgentExecutor.ts's prepareStep hook and ai-utils.ts's populateHistoryForAgent, plus covered by a new Mocha unit test suite.

Changes

Tool-call input sanitization for Anthropic compatibility

Layer / File(s) Summary
Core sanitization module and public API
src/features/ai/agent/resilience/messageSanitization.ts, src/features/ai/agent/resilience/index.ts
messageSanitization.ts implements isMalformedToolCallPart, coerceInput, repairToolCallInputs (in-place string→object coercion with repair counter and warning log), and sanitizeMessages (thin wrapper). resilience/index.ts re-exports both public functions.
Integration into agent execution paths
src/features/ai/agent/AgentExecutor.ts, src/features/ai/utils/ai-utils.ts
AgentExecutor.ts calls sanitizeMessages(stepMessages) before addCacheControlToMessages in the prepareStep hook. ai-utils.ts calls sanitizeMessages(messages) after populateHistoryForAgent constructs the ModelMessage[].
Mocha test runner and unit tests
test/ai/unit_tests/resilience/index.ts, test/ai/unit_tests/resilience/message-sanitization.test.ts
Test runner configures Mocha TDD with glob discovery and process-exit handling. Tests cover repairToolCallInputs for all malformed shapes (unparseable, truncated, empty, array, non-object), valid no-op behavior, multi-message repair counting, and shape tolerance; and sanitizeMessages for in-place repair and clean-history no-op.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 A string where an object should dwell,
Made Anthropic's validator yell!
Now coerceInput swoops in,
Turns bad JSON to win —
The migration agent is well! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description covers the core issue and fix, but it does not follow the required template and omits most mandatory sections such as Purpose, Goals, Approach, testing, and release notes. Rewrite the PR description using the repository template and fill in the required sections, especially Purpose, Goals, Approach, Automation tests, Security checks, and Documentation.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change—sanitizing malformed tool-call inputs before sending agent history to Anthropic—which is the core objective of this PR.
Linked Issues check ✅ Passed The PR fully addresses issue #1741 by implementing the required sanitization of malformed tool-call inputs before sending messages to Anthropic, applied to both agent turn and history-loading paths, with unit tests included.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the sanitization requirement: new resilience module with sanitization logic, integration into message processing paths, tests, and related infrastructure—no unrelated modifications detected.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@RNViththagan RNViththagan marked this pull request as ready for review June 22, 2026 16:15
@RNViththagan

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

2 participants