fix(composio): drop blank optional tool arguments before Composio execution - #14895
Conversation
…cution
Gmail (and other Composio) actions used as an agent Tool go through
SafeLangchainProvider.wrap_tool -> composio_langchain's wrap_tool, which
forwards the LLM's raw tool-call arguments straight to Composio's execute
API. Tool-calling models routinely populate every property they see in a
schema, including optional ones, with empty placeholders - e.g. Gmail's
consolidated "attachment" field as {"name": "", "data": ""} when no
attachment was requested. Composio's backend then rejects the blank value
with "Tool input validation error".
The direct component-run path (ComposioBaseComponent.execute_action) already
drops blank/default optional values before calling the API, but that logic
never ran for the agent Tool-calling path, causing the divergence: running
the Gmail action directly worked, using it as a Tool did not - exactly what
issue langflow-ai#14715 reports.
Wrap execute_tool in SafeLangchainProvider.wrap_tool to strip blank optional
arguments (recursively, for nested objects) before delegating, mirroring
execute_action's existing behavior. Required fields are always forwarded
untouched so a genuinely missing required value still reaches Composio's own
validation.
Fixes langflow-ai#14715
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. Walkthrough
ChangesComposio blank argument filtering
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The PR removes blank optional arguments from agent-driven Composio calls while preserving required inputs, aligning behavior with direct execution and preventing the reported validation failures. No actionable merge-blocking risk remains beyond normal checks and review. Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant LangchainProvider
participant SafeLangchainProvider
participant ComposioExecutor
LangchainProvider->>SafeLangchainProvider: wrap_tool with execute_tool
SafeLangchainProvider->>SafeLangchainProvider: remove blank optional arguments
SafeLangchainProvider->>ComposioExecutor: execute filtered arguments
🚥 Pre-merge checks | ✅ 8 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (8 passed)
Full details: Linked Issues checkExplanation The PR satisfies issue Full details: Test Coverage For New ImplementationsExplanation PASS: The PR adds 180 lines to the existing backend test file Full details: Test Quality And CoverageExplanation Tests provide strong coverage for the new filtering behavior. The added pytest cases cover blank and non-blank scalar, collection, and nested-dictionary values; optional-field removal; preservation of required blank fields; non-dictionary inputs; and preservation of non-blank optional fields. Two regression tests exercise the real Full details: Test File Naming And StructureExplanation The changed backend test file is named Full details: Excessive Mock Usage WarningExplanation PASS. The added tests do not introduce excessive mocks. They use real
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Summary
Fixes #14715.
When a Composio action (e.g. Gmail) is used as a Tool by an agent, drafting/sending an email fails with
"Tool input validation error"from Composio, even though the same action run directly from the component works fine.Root cause
ComposioBaseComponent.execute_action(src/lfx/src/lfx/base/composio/composio_base.py), used when the component runs directly, already skips optional arguments that areNone, empty strings/lists, or equal to the schema default before calling the Composio API.SafeLangchainProvider.wrap_tool→composio_langchain'sLangchainProvider.wrap_tool) has no equivalent filtering: it forwards the LLM's raw tool-call arguments to Composio'sexecuteAPI unchanged.Tool-calling models routinely populate every property they see in a tool's JSON schema, including optional ones, with empty placeholders. For Gmail's consolidated
attachmentfield this produces{"name": "", "data": ""}even when no attachment was requested. Composio's backend rejects that blank value with"Tool input validation error", which matches the exact payload and error reported in the issue. This divergence between the two execution paths explains why the bug only reproduces "as a Tool."Fix
SafeLangchainProvider.wrap_tool(src/lfx/src/lfx/base/composio/safe_provider.py) now wrapsexecute_toolto strip blank optional arguments (recursively, so a nested object likeattachmentwhose leaf values are all blank is dropped too) before delegating to Composio, mirroringexecute_action's existing behavior. Required fields are always forwarded untouched, so a genuinely missing required value still reaches Composio's own validation and error reporting.This is a minimal, surgical change scoped to one file's tool-wrapping logic; no schema-building, UI, or direct-execution code paths were touched.
Test plan
TestIsBlankValue,TestDropBlankOptionalArguments, andTestSafeLangchainProviderDropsBlankOptionalArguments(the latter reproduces the exactGMAIL_CREATE_EMAIL_DRAFTpayload from the issue through the realSafeLangchainProvider.wrap_toolwiring) insrc/bundles/lfx-bundles/tests/test_composio_components.py.uv run pytest src/bundles/lfx-bundles/tests/test_composio_components.py -q→ 30 passed.uv run pytest src/bundles/lfx-bundles/tests/ -q(full bundle suite) → 192 passed, 29 skipped, no regressions.uv run ruff check/uv run pre-commit run --files ...→ clean.Summary by CodeRabbit
Bug Fixes
Tests