Skip to content

fix: Improve agent input handling and message filtering#10277

Merged
carlosrcoelho merged 15 commits into
mainfrom
fix-anthropic-input-issue
Oct 21, 2025
Merged

fix: Improve agent input handling and message filtering#10277
carlosrcoelho merged 15 commits into
mainfrom
fix-anthropic-input-issue

Conversation

@edwinjosechittilappilly
Copy link
Copy Markdown
Collaborator

@edwinjosechittilappilly edwinjosechittilappilly commented Oct 14, 2025

Enhances agent.py to ensure input text is never empty, providing defaults to prevent Anthropic API errors. Updates utils.py to filter out messages with empty content and log warnings for conversion failures. Also updates starter project to set a default input value.

Summary by CodeRabbit

  • New Features
    • Simple Agent starter now begins with a pre-filled greeting (“Hello, how are you?”) for immediate interaction.
  • Bug Fixes
    • Agent gracefully handles empty or whitespace inputs and ignores blank messages.
    • More reliable input construction from text and images, with safe fallbacks to prevent API errors and ensure responses continue the conversation.
  • Tests
    • Added comprehensive tests to validate empty/whitespace input handling and multimodal scenarios across multiple model providers.

Enhances agent.py to ensure input text is never empty, providing defaults to prevent Anthropic API errors. Updates utils.py to filter out messages with empty content and log warnings for conversion failures. Also updates starter project to set a default input value.
Introduces unit tests to verify that the AgentComponent correctly filters out empty and whitespace-only messages in chat history, and handles empty or whitespace input values without errors for both OpenAI and Anthropic models. These tests address previous issues with message validation and ensure robust input handling.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Oct 14, 2025

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.

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

Walkthrough

Updates agent input handling to extract and default text from message content, filters out empty messages during conversion, adjusts the Simple Agent starter’s default prompt, and adds unit tests ensuring empty/whitespace inputs are handled without errors across providers.

Changes

Cohort / File(s) Summary of changes
Starter project default input
src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json
Set ChatInput node’s default input_value to "Hello, how are you?"
Agent input construction
src/lfx/src/lfx/base/agents/agent.py
Parse text items from message content; build input_text from non-image text; add defaults when text missing/invalid; final safety fallback to non-empty prompt before setting input_dict["input"]
Message conversion/filtering
src/lfx/src/lfx/base/agents/utils.py
data_to_messages now filters empty-content messages; wraps conversion in try/except; logs and skips invalid/empty items; updated docstring
Agent empty-input tests
src/backend/tests/unit/components/agents/test_agent_component.py
Added tests covering empty/whitespace inputs for OpenAI/Anthropic; verify no errors and responses exist; includes chat history filtering test

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as ChatInput
  participant Agent as AgentComponent
  participant Utils as data_to_messages
  participant Model as LLM (OpenAI/Anthropic)

  User->>UI: Submit message (may be empty/whitespace)
  UI->>Agent: Run with input + chat_history
  Agent->>Utils: Convert data to BaseMessages
  Utils-->>Agent: Filtered messages (non-empty only)

  Agent->>Agent: Extract text from message content<br/>(separate text_items vs images)
  alt No usable text
    Agent->>Agent: Set default prompt ("Process the provided images." or "Continue the conversation.")
  end
  Agent->>Model: input_dict with input_text + context
  Model-->>Agent: Response
  Agent-->>UI: Response (text/data)
  note over Agent,Model: Tests assert no errors on empty/whitespace input
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

size:L, lgtm

Suggested reviewers

  • Cristhianzl
  • ogabrielluiz
  • jordanrfrazier

Pre-merge checks and finishing touches

❌ Failed checks (1 error, 2 warnings)
Check name Status Explanation Resolution
Test Coverage For New Implementations ❌ Error
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Test Quality And Coverage ⚠️ Warning
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title accurately reflects the main purpose of this pull request by stating that agent input handling has been improved and message filtering has been added, which directly corresponds to the updates in agent.py, utils.py, and the starter project default input.
Test File Naming And Structure ✅ Passed The repository’s tests adhere to the prescribed naming conventions and directory layouts: all backend tests use test_*.py under tests/unit or tests/integration, frontend tests follow *.test.ts/*.test.tsx under __tests__ directories, and integration tests are clearly located in tests/integration folders. The new and existing test functions have descriptive names that convey their purpose (e.g., test_agent_handles_empty_input_with_openai), leverage pytest fixtures correctly, and cover both normal and edge cases such as empty or whitespace inputs without introducing structural or organizational inconsistencies.
Excessive Mock Usage Warning ✅ Passed The newly added tests in test_agent_component.py do not rely on any mocks at all; they invoke the AgentComponent against stubbed Message objects and inspect real responses, so there is no mock usage to assess for excess. All tests use actual data conversion and live component methods rather than mocking dependencies. Consequently, there is no risk of over-mocking in these 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 and usage tips.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 14, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 14, 2025
@codecov
Copy link
Copy Markdown

codecov Bot commented Oct 14, 2025

Codecov Report

❌ Patch coverage is 0% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 30.21%. Comparing base (aa3d8e6) to head (ba25496).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/lfx/src/lfx/base/agents/utils.py 0.00% 12 Missing ⚠️
src/lfx/src/lfx/base/agents/agent.py 0.00% 9 Missing ⚠️

❌ Your patch status has failed because the patch coverage (0.00%) is below the target coverage (40.00%). You can increase the patch coverage or adjust the target coverage.
❌ Your project status has failed because the head coverage (40.08%) is below the target coverage (60.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #10277      +/-   ##
==========================================
- Coverage   30.22%   30.21%   -0.01%     
==========================================
  Files        1315     1315              
  Lines       59290    59309      +19     
  Branches     8876     8882       +6     
==========================================
+ Hits        17920    17921       +1     
- Misses      40553    40570      +17     
- Partials      817      818       +1     
Flag Coverage Δ
backend 51.16% <ø> (+0.01%) ⬆️
frontend 10.01% <ø> (ø)
lfx 40.08% <0.00%> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/lfx/src/lfx/base/agents/agent.py 28.87% <0.00%> (-1.73%) ⬇️
src/lfx/src/lfx/base/agents/utils.py 36.78% <0.00%> (-5.33%) ⬇️

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lfx/src/lfx/base/agents/agent.py (1)

152-163: Fix passing a Data object to data_to_messages; wrap in a list

When chat_history is a Data object, passing it directly to data_to_messages will iterate the object and likely error. Wrap it in a list.

Apply this diff:

-                input_dict["chat_history"] = data_to_messages(self.chat_history)
+                input_dict["chat_history"] = data_to_messages([self.chat_history])
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0344577 and 5288a6e.

📒 Files selected for processing (4)
  • src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json (1 hunks)
  • src/backend/tests/unit/components/agents/test_agent_component.py (2 hunks)
  • src/lfx/src/lfx/base/agents/agent.py (1 hunks)
  • src/lfx/src/lfx/base/agents/utils.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
src/backend/tests/unit/components/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

src/backend/tests/unit/components/**/*.py: Mirror the component directory structure for unit tests in src/backend/tests/unit/components/
Use ComponentTestBaseWithClient or ComponentTestBaseWithoutClient as base classes for component unit tests
Provide file_names_mapping for backward compatibility in component tests
Create comprehensive unit tests for all new components

Files:

  • src/backend/tests/unit/components/agents/test_agent_component.py
{src/backend/**/*.py,tests/**/*.py,Makefile}

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

{src/backend/**/*.py,tests/**/*.py,Makefile}: Run make format_backend to format Python code before linting or committing changes
Run make lint to perform linting checks on backend Python code

Files:

  • src/backend/tests/unit/components/agents/test_agent_component.py
src/backend/tests/unit/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

Test component integration within flows using create_flow, build_flow, and get_build_events utilities

Files:

  • src/backend/tests/unit/components/agents/test_agent_component.py
src/backend/tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

src/backend/tests/**/*.py: Unit tests for backend code must be located in the 'src/backend/tests/' directory, with component tests organized by component subdirectory under 'src/backend/tests/unit/components/'.
Test files should use the same filename as the component under test, with an appropriate test prefix or suffix (e.g., 'my_component.py' → 'test_my_component.py').
Use the 'client' fixture (an async httpx.AsyncClient) for API tests in backend Python tests, as defined in 'src/backend/tests/conftest.py'.
When writing component tests, inherit from the appropriate base class in 'src/backend/tests/base.py' (ComponentTestBase, ComponentTestBaseWithClient, or ComponentTestBaseWithoutClient) and provide the required fixtures: 'component_class', 'default_kwargs', and 'file_names_mapping'.
Each test in backend Python test files should have a clear docstring explaining its purpose, and complex setups or mocks should be well-commented.
Test both sync and async code paths in backend Python tests, using '@pytest.mark.asyncio' for async tests.
Mock external dependencies appropriately in backend Python tests to isolate unit tests from external services.
Test error handling and edge cases in backend Python tests, including using 'pytest.raises' and asserting error messages.
Validate input/output behavior and test component initialization and configuration in backend Python tests.
Use the 'no_blockbuster' pytest marker to skip the blockbuster plugin in tests when necessary.
Be aware of ContextVar propagation in async tests; test both direct event loop execution and 'asyncio.to_thread' scenarios to ensure proper context isolation.
Test error handling by mocking internal functions using monkeypatch in backend Python tests.
Test resource cleanup in backend Python tests by using fixtures that ensure proper initialization and cleanup of resources.
Test timeout and performance constraints in backend Python tests using 'asyncio.wait_for' and timing assertions.
Test Langflow's Messag...

Files:

  • src/backend/tests/unit/components/agents/test_agent_component.py
src/backend/**/*component*.py

📄 CodeRabbit inference engine (.cursor/rules/icons.mdc)

In your Python component class, set the icon attribute to a string matching the frontend icon mapping exactly (case-sensitive).

Files:

  • src/backend/tests/unit/components/agents/test_agent_component.py
src/backend/**/components/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/icons.mdc)

In your Python component class, set the icon attribute to a string matching the frontend icon mapping exactly (case-sensitive).

Files:

  • src/backend/tests/unit/components/agents/test_agent_component.py
**/@(test_*.py|*.test.@(ts|tsx))

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

**/@(test_*.py|*.test.@(ts|tsx)): Check if tests have too many mock objects that obscure what's actually being tested
Warn when mocks are used instead of testing real behavior and interactions
Suggest using real objects or test doubles when mocks become excessive
Ensure mocks are used appropriately for external dependencies, not core logic
Recommend integration tests when unit tests become overly mocked
Test files should have descriptive test function names explaining what is tested
Tests should be organized logically with proper setup and teardown
Include edge cases and error conditions for comprehensive coverage
Verify tests cover both positive and negative scenarios where appropriate
Tests should cover the main functionality being implemented
Ensure tests are not just smoke tests but actually validate behavior
For API endpoints, verify both success and error response testing

Files:

  • src/backend/tests/unit/components/agents/test_agent_component.py
**/test_*.py

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

**/test_*.py: Check that backend test files follow naming convention: test_.py
Backend tests should be named test_
.py and follow proper pytest structure
For async Python code, ensure proper async testing patterns (pytest) are used
Backend tests should follow pytest conventions; frontend tests should use Playwright

Files:

  • src/backend/tests/unit/components/agents/test_agent_component.py
🧬 Code graph analysis (2)
src/lfx/src/lfx/base/agents/utils.py (1)
src/backend/base/langflow/memory.py (1)
  • messages (310-314)
src/backend/tests/unit/components/agents/test_agent_component.py (3)
src/lfx/src/lfx/base/agents/utils.py (1)
  • data_to_messages (43-65)
src/lfx/src/lfx/schema/message.py (1)
  • Message (34-297)
src/lfx/src/lfx/components/agents/agent.py (1)
  • AgentComponent (37-601)
🪛 GitHub Actions: Ruff Style Check
src/backend/tests/unit/components/agents/test_agent_component.py

[error] 367-367: ARG002 Unused method argument: component_class

🪛 GitHub Check: Ruff Style Check (3.13)
src/backend/tests/unit/components/agents/test_agent_component.py

[failure] 367-367: Ruff (ARG002)
src/backend/tests/unit/components/agents/test_agent_component.py:367:85: ARG002 Unused method argument: default_kwargs


[failure] 367-367: Ruff (ARG002)
src/backend/tests/unit/components/agents/test_agent_component.py:367:68: ARG002 Unused method argument: component_class

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Lint Backend / Run Mypy (3.10)
  • GitHub Check: Lint Backend / Run Mypy (3.11)
  • GitHub Check: Lint Backend / Run Mypy (3.13)
  • GitHub Check: Lint Backend / Run Mypy (3.12)
  • GitHub Check: Run Frontend Tests / Determine Test Suites and Shard Distribution
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 5
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 4
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 1
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 3
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 2
  • GitHub Check: Run Backend Tests / Integration Tests - Python 3.10
  • GitHub Check: Test Starter Templates
  • GitHub Check: Optimize new Python code in this PR
  • GitHub Check: test-starter-projects
🔇 Additional comments (1)
src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json (1)

478-479: Good default to avoid empty prompts in the starter

Setting a non-empty default improves OOTB behavior and avoids provider errors.

Comment on lines +367 to +383
async def test_agent_filters_empty_chat_history_messages(self, component_class, default_kwargs):
"""Test that empty messages in chat history are filtered out."""
from lfx.base.agents.utils import data_to_messages
from lfx.schema.message import Message

# Create messages with varying content
empty_message = Message(text="", sender="User", sender_name="User")
whitespace_message = Message(text=" ", sender="User", sender_name="User")
valid_message = Message(text="Hello", sender="User", sender_name="User")

# Convert to LC messages (should filter out empty ones)
messages = data_to_messages([empty_message, whitespace_message, valid_message])

# Should only have the valid message
assert len(messages) == 1
assert messages[0].content == "Hello"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix Ruff ARG002: mark unused fixtures as used

component_class and default_kwargs are required fixtures but unused here; delete them to satisfy Ruff.

Apply this diff:

 async def test_agent_filters_empty_chat_history_messages(self, component_class, default_kwargs):
     """Test that empty messages in chat history are filtered out."""
     from lfx.base.agents.utils import data_to_messages
     from lfx.schema.message import Message
+    # Mark fixtures as intentionally unused for linting
+    del component_class, default_kwargs
 
     # Create messages with varying content
     empty_message = Message(text="", sender="User", sender_name="User")
     whitespace_message = Message(text="   ", sender="User", sender_name="User")
     valid_message = Message(text="Hello", sender="User", sender_name="User")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async def test_agent_filters_empty_chat_history_messages(self, component_class, default_kwargs):
"""Test that empty messages in chat history are filtered out."""
from lfx.base.agents.utils import data_to_messages
from lfx.schema.message import Message
# Create messages with varying content
empty_message = Message(text="", sender="User", sender_name="User")
whitespace_message = Message(text=" ", sender="User", sender_name="User")
valid_message = Message(text="Hello", sender="User", sender_name="User")
# Convert to LC messages (should filter out empty ones)
messages = data_to_messages([empty_message, whitespace_message, valid_message])
# Should only have the valid message
assert len(messages) == 1
assert messages[0].content == "Hello"
async def test_agent_filters_empty_chat_history_messages(self, component_class, default_kwargs):
"""Test that empty messages in chat history are filtered out."""
from lfx.base.agents.utils import data_to_messages
from lfx.schema.message import Message
# Mark fixtures as intentionally unused for linting
del component_class, default_kwargs
# Create messages with varying content
empty_message = Message(text="", sender="User", sender_name="User")
whitespace_message = Message(text=" ", sender="User", sender_name="User")
valid_message = Message(text="Hello", sender="User", sender_name="User")
# Convert to LC messages (should filter out empty ones)
messages = data_to_messages([empty_message, whitespace_message, valid_message])
# Should only have the valid message
assert len(messages) == 1
assert messages[0].content == "Hello"
🧰 Tools
🪛 GitHub Actions: Ruff Style Check

[error] 367-367: ARG002 Unused method argument: component_class

🪛 GitHub Check: Ruff Style Check (3.13)

[failure] 367-367: Ruff (ARG002)
src/backend/tests/unit/components/agents/test_agent_component.py:367:85: ARG002 Unused method argument: default_kwargs


[failure] 367-367: Ruff (ARG002)
src/backend/tests/unit/components/agents/test_agent_component.py:367:68: ARG002 Unused method argument: component_class

🤖 Prompt for AI Agents
In src/backend/tests/unit/components/agents/test_agent_component.py around lines
367 to 383, the test function declares unused fixtures component_class and
default_kwargs which triggers Ruff ARG002; remove these parameters from the test
function signature so the test becomes async def
test_agent_filters_empty_chat_history_messages(self): (or if self is not needed
remove that too) and ensure no other references to those fixtures exist inside
the test; run the test suite and Ruff to confirm the warning is resolved.

Comment on lines 166 to +176
image_dicts = [item for item in lc_message.content if item.get("type") == "image"]
lc_message.content = [item for item in lc_message.content if item.get("type") != "image"]
text_items = [item for item in lc_message.content if item.get("type") != "image"]

# Extract text content from remaining items
if text_items:
# If there are text items, extract their text content
input_text = " ".join(item.get("text", "") for item in text_items if item.get("type") == "text").strip()

# If input_text is still a list or empty, provide a default
if isinstance(input_text, list) or not input_text:
input_text = "Process the provided images."
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Preserve images for all providers and robustly extract text

Only checking type == "image" drops OpenAI-style image blocks ('image_url'). That loses user images. Also, extract text from any blocks that have a text field.

Apply this diff:

-            image_dicts = [item for item in lc_message.content if item.get("type") == "image"]
-            text_items = [item for item in lc_message.content if item.get("type") != "image"]
+            image_types = {"image", "image_url", "input_image"}
+            image_dicts = [item for item in lc_message.content if isinstance(item, dict) and item.get("type") in image_types]
+            text_items = [item for item in lc_message.content if isinstance(item, dict) and item.get("type") not in image_types]
 
             # Extract text content from remaining items
             if text_items:
-                # If there are text items, extract their text content
-                input_text = " ".join(item.get("text", "") for item in text_items if item.get("type") == "text").strip()
+                # If there are text items, extract their text content (ignore non-text blocks)
+                input_text = " ".join(
+                    str(item.get("text", "")).strip()
+                    for item in text_items
+                    if item.get("type") == "text"
+                ).strip()
 
             # If input_text is still a list or empty, provide a default
             if isinstance(input_text, list) or not input_text:
                 input_text = "Process the provided images."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
image_dicts = [item for item in lc_message.content if item.get("type") == "image"]
lc_message.content = [item for item in lc_message.content if item.get("type") != "image"]
text_items = [item for item in lc_message.content if item.get("type") != "image"]
# Extract text content from remaining items
if text_items:
# If there are text items, extract their text content
input_text = " ".join(item.get("text", "") for item in text_items if item.get("type") == "text").strip()
# If input_text is still a list or empty, provide a default
if isinstance(input_text, list) or not input_text:
input_text = "Process the provided images."
image_types = {"image", "image_url", "input_image"}
image_dicts = [item for item in lc_message.content if isinstance(item, dict) and item.get("type") in image_types]
text_items = [item for item in lc_message.content if isinstance(item, dict) and item.get("type") not in image_types]
# Extract text content from remaining items
if text_items:
# If there are text items, extract their text content (ignore non-text blocks)
input_text = " ".join(
str(item.get("text", "")).strip()
for item in text_items
if item.get("type") == "text"
).strip()
# If input_text is still a list or empty, provide a default
if isinstance(input_text, list) or not input_text:
input_text = "Process the provided images."

Comment thread src/lfx/src/lfx/base/agents/agent.py Outdated
Comment on lines +50 to +65
List[BaseMessage]: The data as messages, filtering out any with empty content.
"""
return [value.to_lc_message() for value in data]
messages = []
for value in data:
try:
lc_message = value.to_lc_message()
# Only add messages with non-empty content (prevents Anthropic API errors)
content = lc_message.content
if content and ((isinstance(content, str) and content.strip()) or (isinstance(content, list) and content)):
messages.append(lc_message)
else:
logger.warning("Skipping message with empty content in chat history")
except (ValueError, AttributeError) as e:
logger.warning(f"Failed to convert message to BaseMessage: {e}")
continue
return messages
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Refine list-content emptiness check to avoid whitespace-only blocks slipping through

Non-empty list content like [{"type":"text","text":" "}] currently passes, but is effectively empty and can still trigger Anthropic’s “non-empty content” error. Keep messages only if there is at least one non-empty text block or any non-text block (e.g., image).

Apply this diff:

-    messages = []
-    for value in data:
+    messages = []
+    for value in data:
         try:
             lc_message = value.to_lc_message()
-            # Only add messages with non-empty content (prevents Anthropic API errors)
-            content = lc_message.content
-            if content and ((isinstance(content, str) and content.strip()) or (isinstance(content, list) and content)):
-                messages.append(lc_message)
-            else:
-                logger.warning("Skipping message with empty content in chat history")
+            # Only add messages with non-empty content (prevents Anthropic API errors)
+            content = lc_message.content
+            if isinstance(content, str):
+                if content.strip():
+                    messages.append(lc_message)
+                else:
+                    logger.warning("Skipping message with empty string content in chat history")
+            elif isinstance(content, list):
+                # Keep if there is any non-empty text block OR any non-text block (e.g., image/image_url)
+                has_non_empty_text = any(
+                    isinstance(item, dict) and item.get("type") == "text" and str(item.get("text", "")).strip()
+                    for item in content
+                )
+                has_non_text_block = any(
+                    isinstance(item, dict) and item.get("type") != "text"
+                    for item in content
+                )
+                if has_non_empty_text or has_non_text_block:
+                    messages.append(lc_message)
+                else:
+                    logger.warning("Skipping message with empty list content in chat history")
+            else:
+                logger.warning("Skipping message: unsupported content type in chat history")
         except (ValueError, AttributeError) as e:
             logger.warning(f"Failed to convert message to BaseMessage: {e}")
             continue
     return messages
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
List[BaseMessage]: The data as messages, filtering out any with empty content.
"""
return [value.to_lc_message() for value in data]
messages = []
for value in data:
try:
lc_message = value.to_lc_message()
# Only add messages with non-empty content (prevents Anthropic API errors)
content = lc_message.content
if content and ((isinstance(content, str) and content.strip()) or (isinstance(content, list) and content)):
messages.append(lc_message)
else:
logger.warning("Skipping message with empty content in chat history")
except (ValueError, AttributeError) as e:
logger.warning(f"Failed to convert message to BaseMessage: {e}")
continue
return messages
messages = []
for value in data:
try:
lc_message = value.to_lc_message()
# Only add messages with non-empty content (prevents Anthropic API errors)
content = lc_message.content
if isinstance(content, str):
if content.strip():
messages.append(lc_message)
else:
logger.warning("Skipping message with empty string content in chat history")
elif isinstance(content, list):
# Keep if there is any non-empty text block OR any non-text block (e.g., image/image_url)
has_non_empty_text = any(
isinstance(item, dict)
and item.get("type") == "text"
and str(item.get("text", "")).strip()
for item in content
)
has_non_text_block = any(
isinstance(item, dict)
and item.get("type") != "text"
for item in content
)
if has_non_empty_text or has_non_text_block:
messages.append(lc_message)
else:
logger.warning("Skipping message with empty list content in chat history")
else:
logger.warning("Skipping message: unsupported content type in chat history")
except (ValueError, AttributeError) as e:
logger.warning(f"Failed to convert message to BaseMessage: {e}")
continue
return messages
🤖 Prompt for AI Agents
In src/lfx/src/lfx/base/agents/utils.py around lines 50 to 65, the check
allowing list content like [{"type":"text","text":"   "}] slips through as
non-empty; change the validation so a list is considered non-empty only if it
contains at least one non-empty text block (text field with .strip() truthy) or
at least one non-text block (any item whose type != "text" or lacks a text
field). Update the condition that tests list content to iterate the list and set
a flag when a valid block is found (non-empty text or non-text), and only append
lc_message when that flag is true; keep the existing logging for skipped or
failed conversions.

…er to send images in the playground with the agent component
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 16, 2025
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Oct 16, 2025

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 11%
10.84% (2890/26653) 4.54% (926/20374) 6.36% (372/5843)

Unit Test Results

Tests Skipped Failures Errors Time
1207 0 💤 0 ❌ 0 🔥 14.022s ⏱️

Copy link
Copy Markdown
Member

@Cristhianzl Cristhianzl left a comment

Choose a reason for hiding this comment

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

lgtm

@github-actions github-actions Bot added the lgtm This PR has been approved by a maintainer label Oct 16, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 16, 2025
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 16, 2025
@github-actions github-actions Bot added the bug Something isn't working label Oct 17, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 17, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 17, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 17, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 20, 2025
@sonarqubecloud
Copy link
Copy Markdown

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 21, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 21, 2025
The parameters 'component_class' and 'default_kwargs' were removed from the 'test_agent_filters_empty_chat_history_messages' test as they were not used. This simplifies the test signature.
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Oct 21, 2025
@carlosrcoelho carlosrcoelho added this pull request to the merge queue Oct 21, 2025
Merged via the queue into main with commit f42107e Oct 21, 2025
143 of 146 checks passed
@carlosrcoelho carlosrcoelho deleted the fix-anthropic-input-issue branch October 21, 2025 14:33
korenLazar pushed a commit to kiran-kate/langflow that referenced this pull request Nov 13, 2025
…10277)

* Improve agent input handling and message filtering

Enhances agent.py to ensure input text is never empty, providing defaults to prevent Anthropic API errors. Updates utils.py to filter out messages with empty content and log warnings for conversion failures. Also updates starter project to set a default input value.

* Add tests for agent handling of empty and whitespace input

Introduces unit tests to verify that the AgentComponent correctly filters out empty and whitespace-only messages in chat history, and handles empty or whitespace input values without errors for both OpenAI and Anthropic models. These tests address previous issues with message validation and ensure robust input handling.

* [autofix.ci] apply automated fixes

* ✨ (general-bugs-agent-anthropic-integration.spec.ts): add test for user to send images in the playground with the agent component

* Update src/lfx/src/lfx/base/agents/agent.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* [autofix.ci] apply automated fixes

* Remove unused test parameters in agent component tests

The parameters 'component_class' and 'default_kwargs' were removed from the 'test_agent_filters_empty_chat_history_messages' test as they were not used. This simplifies the test signature.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>
Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants