Skip to content

feat: Adding an Agent component that uses pre and post tool reflection components from ALTK#10478

Closed
korenLazar wants to merge 62 commits into
langflow-ai:mainfrom
kiran-kate:altk_agent2
Closed

feat: Adding an Agent component that uses pre and post tool reflection components from ALTK#10478
korenLazar wants to merge 62 commits into
langflow-ai:mainfrom
kiran-kate:altk_agent2

Conversation

@korenLazar
Copy link
Copy Markdown
Contributor

@korenLazar korenLazar commented Nov 2, 2025

This PR adds an agent that uses post-tool and pre-tool processing components from the Agent Lifecycle ToolKit.
This PR is a continuation of a previous PR that was completed recently.

  • The UI widget of this new agent (called ALTKAgent) exposes options to the user to turn the special processing on/off. Some more advanced parameters can be set as well.
  • The execution of the agent calls the ALTK components to enhance the tool calling capabilities of LLMs. This is done by performing special checks and processing around tool calls.

The current components enabled are:

  1. SPARC: A middleware component that intercepts and reflects on AI agent tool calls before execution. It validates the tool call against the tool specifications and conversation context, applying multiple layers of checks:
  • Syntactic validation: JSON schema checks, parameter existence, type validation + automatic correction.
  • Semantic validation: LLM-based judges assess alignment with user intent and tool descriptions.
  • Unit/value transformation: Automated correction of mismatched units or formats (e.g., converting “October 5” to a timestamp).
  • Feedback aggregation: Produces a reflection report (score, explanation, corrections) that the agent can use to self-correct before executing.

In the current implementation we only check whether the final validation outcome is positive or negative and approve or reject based on it.

*Already exists from the previous PR:
2. Processing of tool outputs when they are large JSON objects (larger than "Response Processing Size Threshold" characters). LLMs need to process these tool outputs to extract useful information from them. This ALTK component prompts the LLM to generate Python code to parse the JSON and then runs that code to extract information from the tool response. More information about this component can be found here.

We concatenate the two components by wrapping the tools first by SPARC and then by the PostToolProcessor.

Summary by CodeRabbit

  • New Features

    • Introduced enhanced agent component with pre-tool validation and post-tool processing capabilities for improved safety and result handling.
    • Added tool guard mechanism for validation and error prevention.
  • Chores

    • Updated dependencies across starter projects including FastAPI, langchain_core, boto3, and scrapegraph_py.
    • Added agent-lifecycle-toolkit to project dependencies.
  • Tests

    • Added comprehensive test coverage for agent components and tool validation mechanisms.

@github-actions github-actions Bot added the community Pull Request from an external contributor label Nov 2, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 2, 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.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Introduces ALTKAgentComponent with pre-tool validation and post-tool processing capabilities, adds agent-lifecycle-toolkit dependency, updates dependency versions across 33 starter project JSON files, and provides comprehensive unit tests for the new agent implementation and related components.

Changes

Cohort / File(s) Summary
Core Dependency Addition
pyproject.toml
Added "agent-lifecycle-toolkit" to project dependencies
ALTK Agent Implementation
src/lfx/src/lfx/components/agents/altk_agent.py
New module implementing ALTKAgentComponent with tool validation, post-tool processing, memory management, and support for OpenAI/Anthropic models. Includes BaseToolWrapper, ValidatedTool, PreToolValidationWrapper, PostToolProcessor, ToolPipelineManager, and ALTKAgentComponent classes
Tool Guard Module
src/lfx/src/lfx/components/agents/tool_guards/tool_guard.py
New tool guard validation module with tool_guard_validation() and evaluate_expression_guard() functions for pre-execution validation
Agent Component Exports
src/lfx/src/lfx/components/agents/__init__.py
Updated public API to export ALTKAgentComponent alongside existing AgentComponent and MCPToolsComponent; added lazy-import and TYPE_CHECKING support
Test Scaffolding
src/lfx/tests/unit/components/__init__.py, src/lfx/tests/unit/components/agents/__init__.py
New package initialization files with module docstrings for test organization
ALTK Agent Unit Tests
src/backend/tests/unit/components/agents/test_altk_agent.py
Comprehensive test suite for ALTKAgentComponent with TestAgentComponent and TestAgentComponentWithClient classes covering build configuration, model validation, calculator tool integration, and OpenAI/Anthropic model variations
Enhanced Agent Tests
src/lfx/tests/unit/components/agents/test_enhanced_agent.py
Unit tests for tool wrapping behavior, pipeline manager orchestration, wrapper ordering, and combined enable/disable scenarios
Starter Project Dependency Updates (33 files)
src/backend/base/langflow/initial_setup/starter_projects/Basic*.json, src/backend/base/langflow/initial_setup/starter_projects/{Blog Writer, Custom Component Generator, Document Q\&A, Financial Report Parser, Hybrid Search RAG, Image Sentiment Analysis, Instagram Copywriter, Invoice Summarizer, Knowledge Retrieval, Market Research, Meeting Summary, Memory Chatbot, News Aggregator, Nvidia Remix, Pokédex Agent, Portfolio Website Code Generator, Price Deal Finder, Research Agent, Research Translation Loop, SEO Keyword Generator, SaaS Pricing, Search agent, Sequential Tasks Agents, Simple Agent, Social Media Agent, Text Sentiment Analysis, Travel Planning Agents, Twitter Thread Generator, Vector Store RAG, Youtube Analysis}.json
Updated FastAPI (0.118.0 → 0.119.0) across all 33 files; langchain_core (0.3.78 → 0.3.79) in 16 files; boto3 (1.40.45 → 1.40.50) in News Aggregator; scrapegraph_py (1.33.0 → 1.34.0) in Search agent

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ALTKAgent as ALTKAgentComponent
    participant TPM as ToolPipelineManager
    participant PreVal as PreToolValidationWrapper
    participant PostProc as PostToolProcessingWrapper
    participant Tool as LangChain Tool
    participant LLM as LLM Client

    User->>ALTKAgent: run_agent(input, tools)
    ALTKAgent->>TPM: process_tools(tools)
    
    Note over TPM: Tool Wrapping Pipeline
    TPM->>PostProc: wrap_tool (if enabled)
    PostProc->>PreVal: wrap_tool (if enabled)
    PreVal->>TPM: return wrapped tool
    
    ALTKAgent->>ALTKAgent: execute agent with wrapped tools
    
    loop For each tool call
        ALTKAgent->>Tool: invoke wrapped tool
        
        alt Pre-validation enabled
            Tool->>PreVal: _run()
            PreVal->>LLM: SPARC validation request
            LLM-->>PreVal: approval/rejection
            
            alt Validation approved
                PreVal->>Tool: proceed to original tool
            else Validation rejected
                PreVal-->>ALTKAgent: formatted error response
            end
        end
        
        Tool->>Tool: original tool execution
        Tool-->>PostProc: tool response
        
        alt Post-processing enabled
            PostProc->>PostProc: inspect response size
            
            alt Response above threshold and JSON-like
                PostProc->>LLM: CodeGenerationComponent.build(response)
                LLM-->>PostProc: generated code/summary
            else Below threshold
                PostProc-->>ALTKAgent: original response
            end
        end
    end
    
    ALTKAgent-->>User: final Message result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • High logic density: ALTKAgentComponent introduces a sophisticated multi-layer tool wrapping architecture (pre-validation, post-processing) with LLM integration for SPARC validation and code generation
  • Architectural scope: New tool wrapper abstraction layer, pipeline manager orchestration, and integration with LangChain's AgentExecutor
  • Cross-cutting changes: 33 JSON starter projects updated with coordinated dependency versions, requiring verification that updates are consistent and intentional
  • Test coverage complexity: Both test suites validate intricate wrapper ordering, conditional enablement, and LLM model variations across OpenAI and Anthropic

Areas requiring extra attention:

  • Tool wrapping pipeline ordering logic in ToolPipelineManager and reverse application sequence in pre/post wrappers
  • SPARC validation format conversion (langchain_tools_to_sparc_tool_specs_format) and error handling during validation failures
  • Memory management and conversation context threading through wrapped tools
  • Dependency version consistency across all 33 starter JSON files (especially boto3 and scrapegraph_py differences)
  • Interaction between CodeGenerationComponent invocation and fallback behavior in PostToolProcessor
  • Agent execution exception handling and logging edge cases

Possibly related PRs

Suggested labels

enhancement, size:XXL, lgtm

Suggested reviewers

  • ogabrielluiz
  • edwinjosechittilappilly
  • jordanrfrazier
  • Cristhianzl

Pre-merge checks and finishing touches

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 warning, 3 inconclusive)
Check name Status Explanation Resolution
Test Quality And Coverage ⚠️ Warning The test suite has significant coverage gaps including zero documented tests for tool_guard.py, untested async functions, missing error handling coverage, and absent negative test cases for validation failures. Add unit tests for tool_guard.py with edge cases, implement async test patterns for ValidatedTool._arun(), add negative test cases for validation failures, and create integration tests for the full agent execution pipeline.
Test Coverage For New Implementations ❓ Inconclusive Test files are claimed in the PR summary but their actual content and coverage cannot be verified. Implementation introduces 8+ new classes and multiple functions requiring comprehensive test coverage. Verify test files exist with substantive test methods covering all new classes (BaseToolWrapper, ALTKBaseTool, ValidatedTool, PreToolValidationWrapper, ToolPipelineManager, PostToolProcessor, PostToolProcessingWrapper, ALTKAgentComponent) and edge cases like validation failures and error handling.
Test File Naming And Structure ❓ Inconclusive Test files referenced in PR summary do not exist in repository; cannot verify naming patterns, pytest structure, and test coverage for altk_agent and enhanced_agent test modules. Confirm test files are present and accessible, then verify test naming follows test_*.py pattern, test functions use descriptive names, proper pytest fixtures/markers are used, and both positive/negative scenarios are covered.
Excessive Mock Usage Warning ❓ Inconclusive Test files mentioned in PR summary could not be located in the repository for direct inspection and mock usage verification. Provide access to the actual test files (test_altk_agent.py and test_enhanced_agent.py) to evaluate mock object counts, appropriateness of mock usage, and opportunities for reducing excessive mocking.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: adding an agent component that uses ALTK pre and post tool reflection components.

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.

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: 9

Caution

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

⚠️ Outside diff range comments (2)
src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json (1)

3489-3495: Critical: Tavily API key is set to OPENAI_API_KEY (secret leak risk).

This will send the OpenAI key to Tavily and 401/403 the request. Bind to a Tavily-specific secret.

Apply this diff:

-                "display_name": "Tavily API Key",
+                "display_name": "Tavily API Key",
                 "dynamic": false,
                 "info": "Your Tavily API Key.",
                 "input_types": [],
                 "load_from_db": true,
                 "name": "api_key",
                 "password": true,
                 "placeholder": "",
-                "required": true,
+                "required": true,
                 "show": true,
                 "title_case": false,
                 "type": "str",
-                "value": "OPENAI_API_KEY"
+                "value": "TAVILY_API_KEY"
src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json (1)

1258-1261: Truncated system prompt string (“Before ”) — fix incomplete user-facing text.

The Agent node’s system_prompt ends mid-sentence; likely accidental and confusing.

- "value": "You are a helpful assistant that must use tools to answer questions and perform tasks regarding RTX Remix.\n\nBefore "
+ "value": "You are a helpful assistant that must use tools to answer questions and perform tasks regarding RTX Remix.\n\nBefore using any tool, think step-by-step, validate the need for the tool, and explain your choice briefly."
♻️ Duplicate comments (2)
src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json (1)

2203-2204: Same FastAPI bump as above — apply the same checks.

Refer to the verification script in the prior comment; results cover this flow too.

src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json (1)

4261-4262: Same langchain_core bump appears in second AstraDB node; apply the same checks.

🧹 Nitpick comments (4)
src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json (2)

640-645: UI nit: max_tokens is int but uses float step 0.1.

Use integer step for cleaner UX.

- "range_spec": { "max": 128000, "min": 0, "step": 0.1, "step_type": "float" }
+ "range_spec": { "max": 128000, "min": 0, "step": 1, "step_type": "int" }

Also applies to: 1289-1293, 2685-2689


3085-3120: Avoid stringify + ast.literal_eval for yfinance news.

Return structured data directly; skip repr/parse round‑trip.

-    def _fetch_yfinance_data(self, ticker: yf.Ticker, method: YahooFinanceMethod, num_news: int | None) -> str:
+    def _fetch_yfinance_data(self, ticker: yf.Ticker, method: YahooFinanceMethod, num_news: int | None):
         try:
             if method == YahooFinanceMethod.GET_INFO:
-                result = ticker.info
+                return ticker.info
             elif method == YahooFinanceMethod.GET_NEWS:
-                result = ticker.news[:num_news]
+                return ticker.news[:num_news]
             else:
-                result = getattr(ticker, method.value)()
-            return pprint.pformat(result)
+                return getattr(ticker, method.value)()
...
-        result = self._fetch_yfinance_data(ticker, method, num_news)
+        result = self._fetch_yfinance_data(ticker, method, num_news)
 
         if method == YahooFinanceMethod.GET_NEWS:
-            data_list = [
-                Data(text=f"{article['title']}: {article['link']}", data=article)
-                for article in ast.literal_eval(result)
-            ]
+            data_list = [Data(text=f"{a['title']}: {a['link']}", data=a) for a in (result or [])]
         else:
-            data_list = [Data(text=result, data={"result": result})]
+            data_list = [Data(text=pprint.pformat(result), data={"result": result})]
src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json (1)

2084-2088: Unsafe default: allow_dangerous_deserialization = true in FAISS.

Loading pickles from untrusted sources shouldn’t be enabled by default in a starter project. Recommend defaulting to false and documenting the risk.

- "value": true
+ "value": false

If you expect users to load existing indices, gate this with a prominent warning in the node description.

src/backend/tests/unit/components/agents/test_altk_agent.py (1)

51-153: Add docstrings for the new tests.

Project guidelines require a descriptive docstring for every backend test; these async tests currently lack one. Please add a short docstring at the start of each test to explain its intent.

     async def test_build_config_update(self, component_class, default_kwargs):
+        """Ensure ALTK agent build config populates provider and model options."""
📜 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 2c25225 and 9771693.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (42)
  • pyproject.toml (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Hybrid Search RAG.json (2 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json (2 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json (2 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Knowledge Retrieval.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Market Research.json (2 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json (3 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json (4 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json (3 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json (2 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json (2 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json (2 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Research Translation Loop.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/SEO Keyword Generator.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json (2 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Search agent.json (3 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json (5 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json (2 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json (4 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json (2 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json (4 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Twitter Thread Generator.json (1 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json (3 hunks)
  • src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json (3 hunks)
  • src/backend/tests/unit/components/agents/test_altk_agent.py (1 hunks)
  • src/lfx/src/lfx/components/agents/__init__.py (1 hunks)
  • src/lfx/src/lfx/components/agents/altk_agent.py (1 hunks)
  • src/lfx/src/lfx/components/agents/altk_agent_new.py (1 hunks)
  • src/lfx/src/lfx/components/agents/enhanced_agent.py (1 hunks)
  • src/lfx/src/lfx/components/agents/tool_guards/tool_guard.py (1 hunks)
  • src/lfx/tests/unit/components/__init__.py (1 hunks)
  • src/lfx/tests/unit/components/agents/__init__.py (1 hunks)
  • src/lfx/tests/unit/components/agents/test_enhanced_agent.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
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_altk_agent.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_altk_agent.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_altk_agent.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_altk_agent.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_altk_agent.py
**/{test_*.py,*.test.ts,*.test.tsx}

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

**/{test_*.py,*.test.ts,*.test.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 simpler test doubles when mocks become excessive
Ensure mocks are used only for external dependencies, not core business logic
Recommend integration tests when unit tests become overly mocked
Check that test files follow the project’s naming conventions (backend: test_*.py; frontend: *.test.ts/tsx)
Verify that tests actually exercise the new or changed functionality, not placeholder assertions
Test files should have descriptive test function names explaining what is being tested
Organize tests logically with proper setup and teardown
Include edge cases and error conditions for comprehensive coverage
Verify tests cover both positive (success) and negative (failure) scenarios
Ensure tests are not mere smoke tests; they should validate behavior thoroughly
Ensure tests follow the project’s testing frameworks (pytest for backend, Playwright for frontend)

Files:

  • src/backend/tests/unit/components/agents/test_altk_agent.py
  • src/lfx/tests/unit/components/agents/test_enhanced_agent.py
**/test_*.py

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

**/test_*.py: Backend tests must be named test_*.py and use proper pytest structure (fixtures, assertions)
For async backend code, use proper pytest async patterns (e.g., pytest-asyncio)
For API endpoints, include tests for both success and error responses

Files:

  • src/backend/tests/unit/components/agents/test_altk_agent.py
  • src/lfx/tests/unit/components/agents/test_enhanced_agent.py
🧠 Learnings (16)
📚 Learning: 2025-07-18T18:25:54.486Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-07-18T18:25:54.486Z
Learning: Applies to src/backend/tests/unit/components/**/*.py : Create comprehensive unit tests for all new components

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
  • src/lfx/tests/unit/components/agents/__init__.py
  • src/backend/tests/unit/components/agents/test_altk_agent.py
  • src/lfx/tests/unit/components/agents/test_enhanced_agent.py
📚 Learning: 2025-07-18T18:25:54.486Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-07-18T18:25:54.486Z
Learning: Applies to src/backend/tests/unit/components/**/*.py : Mirror the component directory structure for unit tests in src/backend/tests/unit/components/

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
  • src/lfx/tests/unit/components/agents/__init__.py
  • src/backend/tests/unit/components/agents/test_altk_agent.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Test component configuration updates in backend Python tests by asserting correct updates to build configuration objects.

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
  • src/backend/tests/unit/components/agents/test_altk_agent.py
  • src/lfx/tests/unit/components/agents/test_enhanced_agent.py
📚 Learning: 2025-07-18T18:25:54.486Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-07-18T18:25:54.486Z
Learning: Applies to src/backend/base/langflow/components/**/__init__.py : Update __init__.py with alphabetical imports when adding new components

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
  • src/lfx/src/lfx/components/agents/__init__.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : 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').

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.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'.

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
  • src/lfx/tests/unit/components/agents/__init__.py
  • src/backend/tests/unit/components/agents/test_altk_agent.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.md : Create comprehensive unit tests for all new components. If unit tests are incomplete, create a Markdown file with manual testing steps in the same directory as the unit tests, using the same filename as the component but with a '.md' extension.

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to 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/'.

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
📚 Learning: 2025-08-05T22:51:27.961Z
Learnt from: edwinjosechittilappilly
Repo: langflow-ai/langflow PR: 0
File: :0-0
Timestamp: 2025-08-05T22:51:27.961Z
Learning: The TestComposioComponentAuth test in src/backend/tests/unit/components/bundles/composio/test_base_composio.py demonstrates proper integration testing patterns for external API components, including real API calls with mocking for OAuth completion, comprehensive resource cleanup, and proper environment variable handling with pytest.skip() fallbacks.

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
  • src/lfx/tests/unit/components/agents/__init__.py
  • src/backend/tests/unit/components/agents/test_altk_agent.py
  • src/lfx/tests/unit/components/agents/test_enhanced_agent.py
📚 Learning: 2025-07-18T18:25:54.486Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-07-18T18:25:54.486Z
Learning: Applies to src/backend/tests/unit/components/**/*.py : Use ComponentTestBaseWithClient or ComponentTestBaseWithoutClient as base classes for component unit tests

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
  • src/lfx/tests/unit/components/agents/__init__.py
  • src/backend/tests/unit/components/agents/test_altk_agent.py
📚 Learning: 2025-07-18T18:25:54.487Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-07-18T18:25:54.487Z
Learning: Applies to src/backend/tests/unit/**/*.py : Test component integration within flows using create_flow, build_flow, and get_build_events utilities

Applied to files:

  • src/lfx/tests/unit/components/__init__.py
  • src/backend/tests/unit/components/agents/test_altk_agent.py
  • src/lfx/tests/unit/components/agents/test_enhanced_agent.py
📚 Learning: 2025-07-18T18:25:54.486Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-07-18T18:25:54.486Z
Learning: Starter project files auto-format after langflow run; these formatting changes can be committed or ignored

Applied to files:

  • src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json
  • src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json
  • src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json
  • src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json
  • src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json
  • src/backend/base/langflow/initial_setup/starter_projects/SEO Keyword Generator.json
  • src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Test backward compatibility across Langflow versions in backend Python tests by mapping component files to supported versions using 'VersionComponentMapping'.

Applied to files:

  • src/backend/tests/unit/components/agents/test_altk_agent.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Use 'MockLanguageModel' for testing language model components without external API calls in backend Python tests.

Applied to files:

  • src/backend/tests/unit/components/agents/test_altk_agent.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Test components that require external APIs using appropriate pytest markers (e.g., 'api_key_required', 'no_blockbuster') and environment variables for API keys.

Applied to files:

  • src/backend/tests/unit/components/agents/test_altk_agent.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Test Langflow's REST API endpoints in backend Python tests using the async client fixture and asserting response codes and payloads.

Applied to files:

  • src/backend/tests/unit/components/agents/test_altk_agent.py
🧬 Code graph analysis (7)
src/lfx/src/lfx/components/agents/tool_guards/tool_guard.py (1)
src/backend/base/langflow/memory.py (1)
  • messages (310-314)
src/backend/tests/unit/components/agents/test_altk_agent.py (3)
src/lfx/src/lfx/components/agents/altk_agent.py (1)
  • ALTKAgentComponent (181-437)
src/backend/tests/base.py (2)
  • ComponentTestBaseWithClient (162-163)
  • ComponentTestBaseWithoutClient (166-167)
src/lfx/src/lfx/custom/custom_component/component.py (2)
  • _should_process_output (1137-1145)
  • to_frontend_node (954-1006)
src/lfx/src/lfx/components/agents/altk_agent_new.py (6)
src/lfx/src/lfx/schema/message.py (1)
  • Message (34-297)
src/backend/base/langflow/memory.py (2)
  • messages (310-314)
  • delete_message (224-234)
src/lfx/src/lfx/base/agents/events.py (2)
  • ExceptionWithMessageError (16-27)
  • process_agent_events (329-362)
src/lfx/src/lfx/base/agents/utils.py (2)
  • data_to_messages (43-52)
  • get_chat_output_sender_name (209-224)
src/lfx/src/lfx/custom/custom_component/component.py (2)
  • log (1479-1496)
  • _send_message_event (1616-1639)
src/lfx/src/lfx/schema/data.py (1)
  • Data (26-288)
src/lfx/src/lfx/components/agents/__init__.py (2)
src/lfx/src/lfx/components/agents/altk_agent.py (1)
  • ALTKAgentComponent (181-437)
src/lfx/src/lfx/components/agents/enhanced_agent.py (1)
  • EnhancedAgentComponent (845-1080)
src/lfx/tests/unit/components/agents/test_enhanced_agent.py (1)
src/lfx/src/lfx/components/agents/enhanced_agent.py (20)
  • EnhancedAgentComponent (845-1080)
  • BaseToolWrapper (70-107)
  • ToolPipelineManager (587-643)
  • PostToolProcessingWrapper (799-839)
  • PreToolValidationWrapper (386-518)
  • ValidatedTool (110-291)
  • PostToolProcessor (649-796)
  • _run (138-145)
  • _run (321-323)
  • _run (696-706)
  • is_available (101-107)
  • is_available (444-446)
  • is_available (576-578)
  • wrap_tool (78-87)
  • wrap_tool (398-441)
  • wrap_tool (534-573)
  • wrap_tool (809-839)
  • _initialize_tool_wrappers (929-947)
  • process_tools (616-622)
  • add_wrapper (608-614)
src/lfx/src/lfx/components/agents/enhanced_agent.py (6)
src/lfx/src/lfx/schema/message.py (2)
  • json (310-312)
  • Message (34-297)
src/backend/base/langflow/memory.py (2)
  • messages (310-314)
  • delete_message (224-234)
src/lfx/src/lfx/base/agents/events.py (2)
  • ExceptionWithMessageError (16-27)
  • process_agent_events (329-362)
src/lfx/src/lfx/base/agents/utils.py (2)
  • data_to_messages (43-52)
  • get_chat_output_sender_name (209-224)
src/lfx/src/lfx/schema/data.py (2)
  • Data (26-288)
  • get_text (63-72)
src/lfx/src/lfx/components/agents/tool_guards/tool_guard.py (1)
  • tool_guard_validation (7-16)
src/lfx/src/lfx/components/agents/altk_agent.py (5)
src/lfx/src/lfx/schema/message.py (2)
  • json (310-312)
  • Message (34-297)
src/backend/base/langflow/memory.py (2)
  • messages (310-314)
  • delete_message (224-234)
src/lfx/src/lfx/base/agents/agent.py (1)
  • LCToolsAgentComponent (234-283)
src/lfx/src/lfx/base/agents/events.py (2)
  • ExceptionWithMessageError (16-27)
  • process_agent_events (329-362)
src/lfx/src/lfx/base/agents/utils.py (1)
  • data_to_messages (43-52)
🔇 Additional comments (43)
src/backend/base/langflow/initial_setup/starter_projects/Knowledge Retrieval.json (1)

243-246: FastAPI 0.119.0 version bump — verified and consistent across all starter projects.

Verification confirms all 36 starter project JSON files have been updated to version 0.119.0, with no leftover 0.118.0 references remaining. The change is a straightforward version bump with no logic modifications.

src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json (2)

1582-1583: Based on the web search, FastAPI 0.119.0/0.119.1 exists and jsonable_encoder remains stable in its API. The search results show no breaking changes specifically related to the jsonable_encoder function signature or behavior in version 0.119.0. The encoder function maintains its standard interface across these versions.

Verify all ChatOutput instances consistently use jsonable_encoder as the encoder utility.

The grep output confirms consistent encoder usage across the codebase. All ChatOutput implementations uniformly reference from fastapi.encoders import jsonable_encoder and call it identically in _serialize_data() methods. No divergent encoder paths detected.

The FastAPI 0.119.0 bump poses no encoding regression risk—the jsonable_encoder API remains unchanged in this version. The same encoder utility is referenced consistently throughout all project files, and no special handling is required for this dependency upgrade.


300-302: langchain_core 0.3.79 is compatible — no breaking changes to Runnable.abatch or Tool imports.

This is a patch release fixing tool call chunk construction. Both Runnable.abatch (used in BatchRunComponent) and StructuredTool imports remain unchanged. No API compatibility issues detected.

src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json (1)

411-414: FastAPI 0.119.0 — jsonable_encoder compatibility checked; run smoke tests

Release notes: jsonable_encoder removed deprecated skip_defaults and sqlalchemy_safe and changed the default for exclude (set() → None). I scanned the repo — jsonable_encoder is used widely but only as simple calls (no removed params) — e.g., src/lfx/src/lfx/components/input_output/chat_output.py and src/lfx/src/lfx/components/data/save_file.py — so the bump looks safe; run unit/integration smoke tests to confirm runtime behavior. (fastapi.tiangolo.com)

src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json (2)

626-629: FastAPI 0.119.0 — approved; versions uniform across all templates.

Verification confirms all 31 starter projects consistently use version 0.119.0 for FastAPI with no stale versions present.


892-893: Based on the verification results, I can now generate the rewritten review comment:

Confirm langchain_core 0.3.79 stability — patch version maintains API compatibility.

Patch version bumps (the third digit) contain only bug fixes and new features, with breaking changes reserved for minor version bumps. The upgrade from an earlier 0.3.x version to 0.3.79 is backward compatible. Codebase scans show extensive stable API usage across langchain_core modules (tools, messages, documents, agents, runnables) with no deprecated imports detected. Current implementations use public interfaces that maintain stability across patch releases.

src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting.json (1)

572-574: Verified: FastAPI 0.119.0 is consistently applied across all starter projects with no 0.118.x remnants.

All 36+ fastapi references across the starter projects are at version 0.119.0, and no 0.118.x versions remain. The change in Basic Prompting.json is consistent with the project-wide update.

src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json (1)

496-498: FastAPI version consistency verified across all starter projects — no issues found.

The verification confirms that all 33+ starter project manifests in src/backend/base/langflow/initial_setup/starter_projects/ consistently use fastapi version 0.119.0. The file at lines 496-498 of Image Sentiment Analysis.json is correct, and there are no mixed versions or inconsistencies across the manifests.

src/backend/base/langflow/initial_setup/starter_projects/Market Research.json (2)

465-465: FastAPI bump to 0.119.0 — mirror check across templates

Aligns with the broader PR. Please confirm no template still references older fastapi, and that ChatOutput JSON still builds with the encoder import.

Use the same scan script posted above to confirm uniform fastapi versions across all JSON templates.


1510-1510: Compatibility verified — all langchain packages compatible with 0.3.79

langchain==0.3.23 requires langchain-core in the 0.3.x range (>=0.3,<0.4), and langchain_core 0.3.79 satisfies this constraint. Template versions for langchain-openai (0.3.23), langchain-anthropic (0.3.14), and langchain-google-genai (2.0.6) all align with or fit within pyproject.toml's version ranges.

src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json (1)

338-338: Ecosystem verified — all starter projects aligned on fastapi 0.119.0

Verification confirms version consistency across the codebase. Of the 33 starter projects, 32 pin fastapi to 0.119.0 (Knowledge Ingestion.json is the sole exception with no fastapi dependency). The fastapi.encoders.jsonable_encoder import used in ChatOutput components across projects remains compatible with this version—it is a stable utility in the fastapi ecosystem.

The Portfolio Website Code Generator change at line 338 maintains alignment with existing projects.

src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json (1)

400-401: I can see the codebase uses jsonable_encoder extensively with the custom_encoder parameter in several places. However, the script output didn't show the pyproject.toml content with version pins. Let me gather that information:Based on my verification, here are the key findings:

Key Finding: FastAPI 0.119.0 supports both Pydantic v2 models and pydantic.v1 models at the same time in the same app, with no breaking changes to jsonable_encoder. There are no major nor breaking changes in this release of 0.119.0. The codebase uses jsonable_encoder with the custom_encoder parameter, which remains fully supported.

However, critical info is missing: the actual pyproject.toml pins for Starlette and Pydantic cannot be verified from the script output. FastAPI 0.119.0 requires Starlette >=0.40.0,<0.49.0, so confirm the repository's Starlette pin matches this range to avoid compatibility issues.


Verify ecosystem compatibility for FastAPI 0.119.0.

The codebase extensively uses jsonable_encoder from fastapi.encoders with custom_encoder parameters—all of which remain stable in FastAPI 0.119.0. The version bump presents no documented breaking changes to encoder behavior. However, confirm:

  1. Starlette version in pyproject.toml falls within >=0.40.0,<0.49.0 (required by FastAPI 0.119.0)
  2. Pydantic version compatibility—FastAPI 0.119.0 now supports both v1 and v2 models simultaneously

No action needed for jsonable_encoder usage across 11 files in src/lfx/; the custom encoder pattern is supported.

src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json (1)

869-869: Dependency version bumps are consistent and properly documented.

The changes update three dependencies across component metadata:

  • fastapi: 0.118.0 → 0.119.0 (ChatOutput, SaveToFile)
  • langchain_core: 0.3.78 → 0.3.79 (Agent)
  • boto3: 1.40.45 → 1.40.50 (SaveToFile)

These are declarative metadata updates in JSON configuration. The versions use standard semantic versioning and align with the PR's stated goal of updating dependencies across starter projects.

Also applies to: 1137-1137, 1781-1781, 1793-1793

src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json (1)

382-382: Dependency version updates match the pattern established in News Aggregator.json.

Both fastapi (0.118.0 → 0.119.0) and langchain_core (0.3.78 → 0.3.79) are updated consistently. The SaaS Pricing project does not include boto3 dependencies, so the boto3 update in News Aggregator does not apply here.

Also applies to: 850-850

src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json (2)

3448-3449: Based on my verification research, I now have sufficient information to generate the final response.

langchain_core 0.3.79 is compatible with langchain_astradb 0.6.1; no critical changes detected.

The review comment's concern about Document API compatibility can be resolved by examining the actual version constraints and release policy:

  • langchain-astradb 0.6.1 officially supports langchain-core>=0.3.52,<0.4, and 0.3.79 falls within this range.
  • Patch versions (the third digit) contain bug fixes and new features without breaking changes—breaking changes to public API result in minor version bumps (the second digit).
  • The Document class from langchain_core.documents is part of the stable public API and has not undergone signature changes within the 0.3.x series.
  • langchain-core is committed to a stable versioning scheme and communicates breaking changes with advance notice and version bumps.

The codebase extensively uses from langchain_core.documents import Document, and all serialization utilities (docs_to_data, serialize) and VectorStore interfaces remain stable across patch versions.


1052-1052: No compatibility issues found with FastAPI 0.119.0 and jsonable_encoder usage.

The codebase widely uses from fastapi.encoders import jsonable_encoder across 6+ backend modules and 15+ embedded starter project templates. Web search confirms FastAPI 0.119.0 changes focus on Pydantic v1→v2 migration support, not breaking changes to jsonable_encoder. All imports resolve correctly without syntax errors. Starlette and Pydantic compatibility is managed at the dependency level (pyproject.toml/lock), not in starter project JSON templates. The version bump is safe.

src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json (1)

489-490: Verify fastapi 0.119.0 version consistency and reasoning across starter projects.

The shell query returned too much noise to confirm whether other starter project JSONs reference different fastapi versions. Two immediate concerns:

  1. Version mismatch: Your lockfile (uv.lock) pins fastapi-0.120.0, but this change uses 0.119.0. Clarify whether this is intentional or a downgrade that needs lockfile alignment.

  2. Incomplete repo-wide check: The grep didn't clearly identify if other starter JSON files also declare fastapi versions. Confirm all starter projects reference the same version or if per-project pinning is intentional.

Cannot execute the Blog Writer smoke test in this sandbox. Manually verify that flow runs successfully after the version change.

src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json (2)

381-382: JSON version metadata is informational only — no functional requirement to update or maintain consistency.

The "version" fields in starter project JSON files (e.g., Pokédex Agent.json) are component metadata that document tested versions when the template was created. They are never read or enforced by runtime code. The actual functional dependency constraint is "fastapi>=0.115.2,<1.0.0" in pyproject.toml, which permits both 0.119.0 and 0.120.0. The upgrade from 0.119.0 → 0.120.0 has no breaking changes, and fastapi.encoders.jsonable_encoder functions identically in both versions.

Likely an incorrect or invalid review comment.


1198-1199: langchain_core → 0.3.79 — confirm compatibility with AgentComponent

Automated checks failed due to inconsistent repo access; manually verify that AgentComponent (langflow.base.agents.agent / lfx.components.agents.agent) does not rely on removed/changed langchain_core APIs — specifically check for sync run/arun, Runnable invoke/ainvoke/abatch, streaming astream/astream_events, and CallbackManager/CallbackManagerForToolRun usage — and update code if any of these are used. Also confirm the starter project file src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json (version 0.3.79) and pyproject.toml/requirements pins are consistent with the changes.

src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json (1)

725-725: Consistent and minimal dependency version bump.

FastAPI has been updated from 0.118.0 to 0.119.0 in both ChatOutput component metadata sections. The version is applied consistently, and the JSON structure remains valid.

As a routine check for dependency updates across starter projects, confirm that FastAPI 0.119.0 is compatible with the rest of the Langflow ecosystem (particularly any components that depend on FastAPI APIs used in this starter project).

Also applies to: 984-984

src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json (2)

1630-1631: Verify FastAPI version consistency between starter projects and lock file.

The lock file resolves to FastAPI 0.120.0, but this change references 0.119.0 in the starter project metadata. While both fall within the pyproject.toml constraint (>=0.115.13,<1.0.0), the mismatch should be confirmed intentional. If the starter projects should reflect the actual pinned version for accuracy, update to 0.120.0.


2538-2539: langchain_core → 0.3.79 compatibility verified: all adapter libs compatible.

All v0.3 series adapters (langchain-openai 0.3.23, langchain-anthropic 0.3.14, langchain-google-genai 2.0.6) are designed to work with langchain-core 0.3.x. langchain-google-genai 2.0.6 requires langchain-core >=0.3,<0.4, and the pinned version 0.3.79 satisfies this constraint. All packages declare langchain-core as a dependency and resolve to the same core version, preventing import and typing mismatches. No breaking changes or runtime drift detected.

src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json (1)

621-622: Align FastAPI minor across starter projects and dependency manifests.

Starter JSONs (src/backend/base/langflow/initial_setup/starter_projects/*.json) are pinned to fastapi 0.119.0, but uv.lock currently pins fastapi 0.120.0 and pyproject.toml manifests allow >=0.115.x; pick the target minor (0.119.x or 0.120.x), update the starter JSONs and pyproject.toml files to match, then regenerate the lockfile.

src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json (2)

364-366: Version consistency verified—no issues found.

All starter project JSONs uniformly specify langchain_core 0.3.79, and this version is compatible with all Python environment constraints:

  • src/backend/base/pyproject.toml pins langchain-core~=0.3.45 (allows 0.3.79)
  • src/lfx/pyproject.toml specifies langchain-core>=0.3.66,<1.0.0 (allows 0.3.79)

The starter projects and Python environment are well-aligned; no mixed-version risk.


3859-3861: JSON starter projects are configuration templates, not primary dependency specifications—no action needed.

The fastapi 0.119.0 version pinned in the JSON starter project files (38+ files) is template metadata, not the application's primary dependency. The actual app dependencies are declared in pyproject.toml with version ranges that already permit 0.119.0:

  • src/backend/base/pyproject.toml: fastapi>=0.115.2,<1.0.0
  • src/lfx/pyproject.toml: fastapi>=0.115.13,<1.0.0

FastAPI 0.119.0 (released October 11, 2025) adds temporary support for mixing Pydantic v2 and pydantic.v1 models and does not include breaking changes. The codebase already uses jsonable_encoder for serialization handling across all endpoints and services, which is the standard and correct approach for FastAPI.

Likely an incorrect or invalid review comment.

src/backend/base/langflow/initial_setup/starter_projects/Hybrid Search RAG.json (2)

1857-1859: Ensure langchain_core 0.3.79 compatibility with other components.

The langchain_core version bump should be verified for compatibility with other LangChain packages in use (langchain_astradb 0.6.1, langchain_anthropic 0.3.14, langchain_google_genai 2.0.6, langchain_openai 0.3.23). These are transitive dependencies that may have specific version constraints.


713-715: Dependency version bumps verified as stable.

FastAPI 0.119.0 and langchain_core 0.3.79 are confirmed stable releases with no new unpatched vulnerabilities. Historical security issues in LangChain have been addressed in the 0.3.x line. These patch-level updates are safe to merge.

src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json (2)

317-317: FastAPI 0.119.0 bump — verified across all starters

Verification confirms all 36 fastapi declarations across all starter projects (including Invoice Summarizer at line 317) are consistently pinned to 0.119.0. No 0.118.x versions exist. Change is safe and consistent.


1113-1113: Based on my verification:

  1. Version Consistency: ✓ All starter projects that declare langchain_core use version 0.3.79 (Hybrid Search RAG, Instagram Copywriter, Market Research, News Aggregator, Pokédex Agent, Price Deal Finder, Research Agent, SaaS Pricing, Search agent, Sequential Tasks Agents, Simple Agent, Social Media Agent, Travel Planning Agents, Vector Store RAG, Youtube Analysis).

  2. API Compatibility: ✓ StructuredTool and Tool are available in langchain_core 0.3.79 with full support for typed input schemas and Runnable interface. The imports in Invoice Summarizer.json are compatible.


src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json (1)

651-651: FastAPI 0.119.0 bump verified — all changes consistent, no compatibility issues

Verification confirms all 36 fastapi references across starter projects updated to 0.119.0 with zero lingering 0.118.x versions. FastAPI 0.119.0 contains no major nor breaking changes, and the codebase's 106 uses of jsonable_encoder remain fully compatible. Changes are approved.

src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json (1)

160-164: FastAPI 0.119.0 is uniform across all starter projects — no action needed.

Verification confirms all 36+ starter JSON files reference the same FastAPI version (0.119.0). No version mismatches detected across the codebase. Users exporting flows will have consistent dependency wheels.

src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json (2)

1029-1033: All verification checks passed—no issues found.

  • FastAPI 0.119.0 consistency: ✅ All 32+ starter projects uniformly reference 0.119.0.
  • Breaking changes: ✅ FastAPI 0.119.0 has no breaking changes. jsonable_encoder is actively used in 26+ code paths across the codebase (including chat_output.py) without reported issues.
  • Dependency stability: ✅ langchain_core 0.3.79 is a patch release with no breaking changes.

1923-1927: No alignment issues found—langchain_core 0.3.79 is compatible with all runtime deps.

The starter project pin of 0.3.79 is compatible with both the main environment (langchain==0.3.23 requires langchain-core >=0.3.51, <1.0.0) and the lfx module (requires langchain-core >=0.3.66, <1.0.0). All sampled starter projects consistently use 0.3.79 with no version drift detected.

src/backend/base/langflow/initial_setup/starter_projects/Twitter Thread Generator.json (1)

674-674: Verified: fastapi 0.119.0 is a valid, safe version update.

FastAPI 0.119.0 is a published release with no documented breaking changes from 0.118.0. The update adds temporary support for mixing Pydantic v1 and v2 models and is intended to ease migration to Pydantic v2. This is a routine, backward-compatible maintenance update with no impact on the flow definition or component logic.

src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json (2)

1565-1565: langchain_core version 0.3.79 is valid and safely upgradeable from 0.3.78.

0.3.79 is a published patch release with a bug fix for chunks constructed with tool calls. No documented breaking changes exist between 0.3.78 and 0.3.79, making this a standard maintenance update.


405-405: No action required—fastapi 0.119.0 is valid and safe to update.

FastAPI 0.119.0 is a published release (released Oct 11, 2025). The update adds temporary support for mixing Pydantic v2 and v1 models to ease migration, with no breaking changes between 0.118.0 and 0.119.0. The version increment is backwards compatible and poses no risk to the starter project.

src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json (2)

487-487: FastAPI 0.119.0 is safe to use—no breaking changes found.

There are no new explicit "breaking changes" in FastAPI 0.119.0 versus 0.118.0. The version bump at line 487 is compatible with the ChatOutput component's use of fastapi.encoders.jsonable_encoder.


1625-1625: No breaking changes—version bump is safe to proceed.

langchain_core 0.3.79 is a patch release that fixes chunk construction/merging related to tool-call chunks with no breaking changes compared to 0.3.78. The consistent updates across all three Agent components (lines 1625, 2266, 2907) are backward compatible and pose no risk to StructuredTool/Tool imports or Agent execution paths.

src/backend/base/langflow/initial_setup/starter_projects/Search agent.json (1)

115-115: Dependency version bumps look appropriate.

The three version updates (scrapegraph_py 1.33.0→1.34.0, fastapi 0.118.0→0.119.0, langchain_core 0.3.78→0.3.79) are patch/minor version increments and appear routine for dependency maintenance. As noted in learnings, starter project JSON files are auto-formatted during langflow runs, so these updates are expected.

Also applies to: 556-556, 904-904

src/backend/base/langflow/initial_setup/starter_projects/SEO Keyword Generator.json (1)

574-574: Consistent fastapi dependency update.

The fastapi version bump from 0.118.0 to 0.119.0 is consistent with the same update in the Search agent.json file and is part of the coordinated dependency refresh across starter projects. No concerns.

src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json (3)

2383-2387: File location cannot be verified — codebase structure mismatch detected.

The review references src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json, but the actual codebase is structured as src/lfx/. Additionally, a critical finding from the verification scripts:

  • StructuredTool imports verified: Found across multiple files (component.py, wikidata_api.py, python_code_structured_tool.py, searxng.py, dataframe_to_toolset.py)
  • .args_schema.schema() usage: ZERO matches — no code in the codebase calls this method

This suggests either the file path is incorrect or the assumption about MCPTools usage of .args_schema.schema() may not apply to this codebase. Before proceeding, the correct file location and whether MCPTools is actually a dependency/component in this repository should be confirmed.


770-774: Compatibility confirmed — langchain_core 0.3.79 is compatible and carries no breaking changes.

0.3.79 is a patch release that does not introduce breaking changes, and the repository's langchain_core version pins (src/lfx: >=0.3.66,<1.0.0; src/backend/base: ~=0.3.45) already accommodate it. The custom create_agent_runnable and run_agent implementations rely only on stable langchain_core APIs—Runnable, RunnableBinding, BaseChatModel, BaseMessage, HumanMessage, BaseTool, and StructuredTool—all of which are unchanged in this patch. No modifications or verification steps are required.


498-502: Nvidia Remix.json is a starter project template, not a package dependency file.

The file is located in src/backend/base/langflow/initial_setup/starter_projects/—a directory dedicated to starter templates. The hardcoded fastapi version (0.119.0 at line 500) is a snapshot configuration embedded in the template workflow, not a live dependency specification.

The repo's actual fastapi version is managed transitively through langflow-base~=0.6.4 in pyproject.toml, not in starter template JSON files. All usages of jsonable_encoder across the codebase are straightforward and compatible with fastapi 0.119.0. No repo-wide version consistency issue exists.

Comment on lines 414 to 415
"version": "0.119.0"
},
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

🧩 Analysis chain

FastAPI 0.119.0 bump — align dependencies and test the template.

Confirm top-level dependency pins and that Playground rendering still works with jsonable_encoder usage.


🏁 Script executed:

#!/bin/bash
# Validate FastAPI pins and occurrences
rg -n '"fastapi"\s*:\s*"' src/backend/base/langflow/initial_setup/starter_projects -S
rg -nP '\bfastapi\b' pyproject.toml requirements* poetry.lock uv.lock -S

Length of output: 1792


🏁 Script executed:

#!/bin/bash
# Check JSON file content around lines 414-415
cat "src/backend/base/langflow/initial_setup/starter_projects/Research Translation Loop.json" | head -420 | tail -15

# Check pyproject.toml for fastapi version pin
rg -n 'fastapi' pyproject.toml -A2 -B2

Length of output: 436


🏁 Script executed:

#!/bin/bash
# Direct check of pyproject.toml for fastapi constraint
cat pyproject.toml | grep -A3 -B3 'fastapi'

# Also verify the specific node in context to understand what this template does
cat "src/backend/base/langflow/initial_setup/starter_projects/Research Translation Loop.json" | grep -A10 -B10 '"name": "ChatOutput"' | head -30

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Use Python to parse JSON and confirm fastapi version in ChatOutput node
python3 << 'EOF'
import json

try:
    with open("src/backend/base/langflow/initial_setup/starter_projects/Research Translation Loop.json", "r") as f:
        data = json.load(f)
    
    # Search for ChatOutput nodes
    if "nodes" in data:
        for node in data["nodes"]:
            if node.get("data", {}).get("type") == "ChatOutput":
                deps = node.get("data", {}).get("node", {}).get("template", {}).get("dependencies", {}).get("dependencies", [])
                for dep in deps:
                    if dep.get("name") == "fastapi":
                        print(f"Found fastapi {dep.get('version')} in ChatOutput node")
except Exception as e:
    print(f"Error: {e}")
EOF

# Search all starter project JSON files for fastapi pins
fd -e json "src/backend/base/langflow/initial_setup/starter_projects" --exec grep -l '"fastapi"' {} \;

Length of output: 529


🏁 Script executed:

#!/bin/bash
# Correct fd syntax to find JSON files with fastapi in starter_projects
fd -e json . 'src/backend/base/langflow/initial_setup/starter_projects' --exec grep -l 'fastapi' {} \;

# Count fastapi version occurrences across all starter templates
echo "=== FastAPI versions in starter templates ==="
fd -e json . 'src/backend/base/langflow/initial_setup/starter_projects' --exec grep '"fastapi"' {} + | grep -o '"version"[^}]*' | sort | uniq -c

# Check uv.lock for current fastapi version constraint
echo "=== Current uv.lock fastapi info ==="
rg -A5 'name = "fastapi"$' uv.lock | head -20

Length of output: 3993


🏁 Script executed:

#!/bin/bash
# Extract fastapi versions from all starter templates
echo "=== FastAPI versions across starter templates ==="
fd -e json . 'src/backend/base/langflow/initial_setup/starter_projects' -x bash -c 'echo "File: {}"; grep -o "\"name\": \"fastapi\"[^}]*\"version\": \"[^\"]*\"" {} | head -1' 2>/dev/null | grep -E "(File:|version)" | paste - - | sort | uniq -c | sort -rn

# Get unique fastapi versions
echo ""
echo "=== Unique fastapi versions in templates ==="
fd -e json . 'src/backend/base/langflow/initial_setup/starter_projects' -x grep -o '"version": "[^"]*"' {} \; 2>/dev/null | grep -A0 -B0 'version' | sort | uniq -c | sort -rn

Length of output: 1029


🏁 Script executed:

#!/bin/bash
# Search for jsonable_encoder usage in codebase
echo "=== jsonable_encoder references ==="
rg -n 'jsonable_encoder' src/backend/ --type py -C2 | head -40

# Check FastAPI changelog/release notes context (check if there's a CHANGELOG)
echo ""
echo "=== Checking for release notes or changelog ==="
find . -maxdepth 2 -iname '*change*' -o -iname '*release*' | head -10

# Check which version should be used - look at version constraints more carefully
echo ""
echo "=== Project FastAPI specifiers in uv.lock ==="
rg -B2 -A2 'specifier = ".*fastapi.*0\.1' uv.lock | head -20

Length of output: 3256


🌐 Web query:

FastAPI 0.120.0 release notes jsonable_encoder changes breaking changes

💡 Result:

FastAPI 0.120.0 changes to encoders.jsonable_encoder (breaking/behavioral):

  • Removed deprecated skip_defaults — use exclude_unset instead. [1]
  • Changed default for exclude from set() to None (matches Pydantic). [1]
  • Removed the sqlalchemy_safe parameter. [1][2]

Sources: FastAPI release notes and encoders docs. [1] [2]


🏁 Script executed:

#!/bin/bash
# Check for any use of removed jsonable_encoder parameters
echo "=== Checking for skip_defaults usage ==="
rg -n 'skip_defaults' src/backend/ --type py

echo ""
echo "=== Checking for sqlalchemy_safe usage ==="
rg -n 'sqlalchemy_safe' src/backend/ --type py

echo ""
echo "=== Checking for exclude parameter in jsonable_encoder calls ==="
rg -n 'jsonable_encoder.*exclude' src/backend/ --type py -C1

echo ""
echo "=== All jsonable_encoder calls to verify parameters ==="
rg -n 'jsonable_encoder\(' src/backend/ --type py -A1

Length of output: 1639


Update starter project templates to FastAPI 0.120.0 for version consistency with lock file.

All 32 starter projects currently pin fastapi 0.119.0, but uv.lock resolves to 0.120.0. Verified that jsonable_encoder usage in the codebase (7 call sites across content_types, artifact, compression, data helpers, flows, projects, and endpoints) is compatible with 0.120.0—no calls use removed parameters (skip_defaults, sqlalchemy_safe, exclude). Mismatch should be resolved by updating template versions from 0.119.0 to 0.120.0 to align with lock resolution and maintain consistency across the project.

🤖 Prompt for AI Agents
In src/backend/base/langflow/initial_setup/starter_projects/Research Translation
Loop.json around lines 414 to 415, the starter project template pins FastAPI
"0.119.0" but the lock file resolves to 0.120.0; update this version string from
"0.119.0" to "0.120.0" in the JSON so the template matches the lock file and
avoids version drift across the 32 starter projects.

Comment thread src/lfx/src/lfx/components/agents/altk_agent_new.py Outdated
Comment thread src/lfx/src/lfx/components/agents/altk_agent_new.py Outdated
Comment thread src/lfx/src/lfx/components/agents/altk_agent_new.py Outdated
Comment thread src/lfx/src/lfx/components/agents/altk_agent.py Outdated
Comment on lines +124 to +243
def __init__(
self, wrapped_tool: BaseTool, agent, sparc_component=None, conversation_context=None, tool_specs=None, **kwargs
):
super().__init__(
name=wrapped_tool.name,
description=wrapped_tool.description,
wrapped_tool=wrapped_tool,
sparc_component=sparc_component,
conversation_context=conversation_context or [],
tool_specs=tool_specs or [],
agent=agent,
**kwargs,
)

def _run(self, *args, **kwargs) -> str:
"""Execute the tool with validation."""
self.sparc_component = SPARCReflectionComponent(
config=ComponentConfig(llm_client=self._get_altk_llm_object()),
track=Track.FAST_TRACK, # Use fast track for performance
execution_mode=SPARCExecutionMode.SYNC, # Use SYNC to avoid event loop conflicts
)
return self._validate_and_run(*args, **kwargs)

async def _arun(self, *args, **kwargs) -> str:
"""Async execute the tool with validation."""
self.sparc_component = SPARCReflectionComponent(
config=ComponentConfig(llm_client=self._get_altk_llm_object()),
track=Track.FAST_TRACK, # Use fast track for performance
execution_mode=SPARCExecutionMode.SYNC, # Use SYNC to avoid event loop conflicts
)
return self._validate_and_run(*args, **kwargs)

def _validate_and_run(self, *args, **kwargs) -> str:
"""Validate the tool call using SPARC and execute if valid."""
# Check if validation should be bypassed
if not self.sparc_component:
return self._execute_tool(*args, **kwargs)

# Prepare tool call for SPARC validation
tool_call = {
"id": str(uuid.uuid4()),
"type": "function",
"function": {"name": self.name, "arguments": json.dumps(self._prepare_arguments(*args, **kwargs))},
}

if isinstance(self.conversation_context, list) and isinstance(self.conversation_context[0], BaseMessage):
logger.debug("Converting BaseMessages to list of dictionaries for conversation context of SPARC")
self.conversation_context = [dict(msg) for msg in self.conversation_context]

try:
# Run SPARC validation
run_input = SPARCReflectionRunInput(
messages=self.conversation_context, tool_specs=self.tool_specs, tool_calls=[tool_call]
)

# Check for missing tool specs and bypass if necessary
if not self.tool_specs:
logger.warning(f"No tool specs available for SPARC validation of {self.name}, executing directly")
return self._execute_tool(*args, **kwargs)

result = self.sparc_component.process(run_input, phase=AgentPhase.RUNTIME)

# Check validation result
if result.output.reflection_result.decision.name == "APPROVE":
logger.info(f"✅ SPARC approved tool call for {self.name}")
return self._execute_tool(*args, **kwargs)
logger.info(f"❌ SPARC rejected tool call for {self.name}")
error_msg = self._format_sparc_rejection(result.output.reflection_result)
return error_msg

except Exception as e:
logger.error(f"Error during SPARC validation: {e}")
# Execute directly on error
return self._execute_tool(*args, **kwargs)

def _prepare_arguments(self, *args, **kwargs) -> dict[str, Any]:
"""Prepare arguments for SPARC validation."""
# Remove config parameter if present (not needed for validation)
clean_kwargs = {k: v for k, v in kwargs.items() if k != "config"}

# If we have positional args, try to map them to parameter names
if args and hasattr(self.wrapped_tool, "args_schema"):
try:
schema = self.wrapped_tool.args_schema
if hasattr(schema, "__fields__"):
field_names = list(schema.__fields__.keys())
for i, arg in enumerate(args):
if i < len(field_names):
clean_kwargs[field_names[i]] = arg
except Exception:
# If schema parsing fails, just use kwargs
pass

return clean_kwargs

def _format_sparc_rejection(self, reflection_result) -> str:
"""Format SPARC rejection into a helpful error message."""
if not reflection_result.issues:
return "Error: Tool call validation failed - please review your approach and try again"

error_parts = ["Tool call validation failed:"]

for issue in reflection_result.issues:
error_parts.append(f"\n• {issue.explanation}")
if issue.correction:
try:
correction_data = issue.correction
if isinstance(correction_data, dict):
if "corrected_function_name" in correction_data:
error_parts.append(f" 💡 Suggested function: {correction_data['corrected_function_name']}")
elif "tool_call" in correction_data:
suggested_args = correction_data["tool_call"].get("arguments", {})
error_parts.append(f" 💡 Suggested parameters: {suggested_args}")
except Exception:
# If correction parsing fails, skip it
pass

error_parts.append("\nPlease adjust your approach and try again.")
return "\n".join(error_parts)

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

Prevent SPARC context conversion from throwing.

Same issues as in altk_agent_new: accessing index 0 on an empty list raises immediately, and dict(msg) fails for BaseMessage. Guard the list and convert via message_to_dict. (python.langchain.com)

-from langchain_core.messages import BaseMessage, HumanMessage
+from langchain_core.messages import BaseMessage, HumanMessage
+from langchain_core.messages.base import message_to_dict
@@
-        if isinstance(self.conversation_context, list) and isinstance(self.conversation_context[0], BaseMessage):
-            logger.debug("Converting BaseMessages to list of dictionaries for conversation context of SPARC")
-            self.conversation_context = [dict(msg) for msg in self.conversation_context]
+        if (
+            isinstance(self.conversation_context, list)
+            and self.conversation_context
+            and isinstance(self.conversation_context[0], BaseMessage)
+        ):
+            logger.debug("Converting BaseMessages to list of dictionaries for conversation context of SPARC")
+            self.conversation_context = [message_to_dict(msg) for msg in self.conversation_context]

Committable suggestion skipped: line range outside the PR's diff.

Comment thread src/lfx/src/lfx/components/agents/enhanced_agent.py Outdated
Comment on lines +19 to +24
def evaluate_expression_guard(args: str) -> Dict:
if '/0' in args: # division by zero
result = {'valid': False, 'error_msg': 'error raised in tool guard code: division by zero is illegal\n'}
else:
result = {'valid': True, 'error_msg': None}
return result
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

Division-by-zero guard misses spaced expressions
Current check only matches the exact substring '/0', so input like "10 / 0" slips through and the guard wrongly approves a division-by-zero call. Tighten the detection to tolerate optional whitespace (and similar formats) so the guard blocks the obvious illegal pattern.

-import string
-from typing import Callable, List, Dict
+import re
+import string
+from typing import Callable, List, Dict
@@
-def evaluate_expression_guard(args: str) -> Dict:
-    if '/0' in args:  # division by zero
+def evaluate_expression_guard(args: str) -> Dict:
+    if re.search(r'/\s*0(?:\D|$)', args):  # division by zero
         result = {'valid': False, 'error_msg': 'error raised in tool guard code: division by zero is illegal\n'}
     else:
         result = {'valid': True, 'error_msg': None}
     return result
🤖 Prompt for AI Agents
In src/lfx/src/lfx/components/agents/tool_guards/tool_guard.py around lines 19
to 24, the division-by-zero guard only checks for the literal substring '/0' and
misses spaced forms like '10 / 0'; update the check to use a regular expression
that finds a slash followed by optional whitespace and a zero word-boundary
(e.g. use re.search(r'/\s*0\b', args)) so patterns like '10/0', '10 /0', '10/
0', and '10 / 0' are detected; if a match is found return the same invalid
result, otherwise return valid.

Comment on lines +47 to +392
class TestEnhancedAgentComponent(unittest.TestCase):
"""Test the EnhancedAgentComponent."""

def setUp(self):
self.component = EnhancedAgentComponent()
self.test_tool = SimpleTool()

def test_initialization(self):
"""Test component initialization with default values."""
self.assertTrue(self.component.enable_post_tool_reflection)
self.assertTrue(self.component.enable_tool_validation)
self.assertIsInstance(self.component.pipeline_manager, ToolPipelineManager)

def test_post_reflection_flag(self):
"""Test that post tool reflection flag works correctly."""
# Default value should be True
self.assertTrue(self.component.enable_post_tool_reflection)

# Set to False
self.component.set(enable_post_tool_reflection=False)
self.assertFalse(self.component.enable_post_tool_reflection)

# Set back to True
self.component.set(enable_post_tool_reflection=True)
self.assertTrue(self.component.enable_post_tool_reflection)

# Check that wrapper is properly initialized
self.component._initialize_tool_wrappers()
# The pipeline manager should have wrappers after initialization
self.assertTrue(len(self.component.pipeline_manager.wrappers) > 0)

def test_tool_validation_flag(self):
"""Test that tool validation flag works correctly."""
# Default value should be True
self.assertTrue(self.component.enable_tool_validation)

# Set to False
self.component.set(enable_tool_validation=False)
self.assertFalse(self.component.enable_tool_validation)

# Set back to True
self.component.set(enable_tool_validation=True)
self.assertTrue(self.component.enable_tool_validation)

# Check that wrapper is properly initialized
self.component._initialize_tool_wrappers()
# The pipeline manager should have wrappers after initialization
self.assertTrue(len(self.component.pipeline_manager.wrappers) > 0)

def test_both_features_enabled(self):
"""Test that both features can be enabled at the same time."""
# Both features are enabled by default
self.assertTrue(self.component.enable_post_tool_reflection)
self.assertTrue(self.component.enable_tool_validation)

# Disable both
self.component.set(
enable_post_tool_reflection=False,
enable_tool_validation=False,
)

# Check both flags are disabled
self.assertFalse(self.component.enable_post_tool_reflection)
self.assertFalse(self.component.enable_tool_validation)

# Enable both again
self.component.set(
enable_post_tool_reflection=True,
enable_tool_validation=True,
)

# Check both flags are set
self.assertTrue(self.component.enable_post_tool_reflection)
self.assertTrue(self.component.enable_tool_validation)

# Check that wrappers are initialized
self.component._initialize_tool_wrappers()

# There should be at least 2 wrappers (the ones we're testing)
self.assertGreaterEqual(len(self.component.pipeline_manager.wrappers), 2)

# Check wrapper types and order
wrapper_types = [type(w) for w in self.component.pipeline_manager.wrappers]
self.assertIn(PostToolProcessingWrapper, wrapper_types)
self.assertIn(PreToolValidationWrapper, wrapper_types)

# The post tool wrapper should be registered first
self.assertIsInstance(
self.component.pipeline_manager.wrappers[0],
PostToolProcessingWrapper
)

def test_wrapper_application_order(self):
"""Test that wrappers are applied in the correct order.

The test verifies that:
1. Wrappers are registered in the correct order in EnhancedAgentComponent
2. Wrappers are applied in reverse order of registration in ToolPipelineManager
3. This creates the proper execution flow where validation happens first
and post-processing happens after tool execution
"""
# Create a clean component with both features enabled
component = EnhancedAgentComponent(
enable_post_tool_reflection=True,
enable_tool_validation=True
)

# Mock the wrapper classes to avoid real initialization
with patch("lfx.components.agents.enhanced_agent.PostToolProcessingWrapper") as MockPost, \
patch("lfx.components.agents.enhanced_agent.PreToolValidationWrapper") as MockPre:

# Create mock instances for our wrappers
mock_post = MagicMock()
mock_post.is_available = True
MockPost.return_value = mock_post

mock_pre = MagicMock()
mock_pre.is_available = True
MockPre.return_value = mock_pre

# Reset pipeline and initialize wrappers
component.pipeline_manager = ToolPipelineManager()
component._initialize_tool_wrappers()

# Verify both wrappers were added
self.assertEqual(len(component.pipeline_manager.wrappers), 2)

# Verify the order of registration:
# According to _initialize_tool_wrappers:
# Post processor is added first
# Pre validator is added second
self.assertIs(component.pipeline_manager.wrappers[0], mock_post)
self.assertIs(component.pipeline_manager.wrappers[1], mock_pre)

# Create sequence tracking
call_sequence = []
test_tool = SimpleTool()

# Create distinct return values for each wrapper
post_result = MagicMock(name="post_wrapped")
pre_result = MagicMock(name="pre_wrapped")

# Set up side effects to track wrapper application sequence
def record_pre_call(tool, **kwargs):
call_sequence.append(("pre", tool))
return pre_result

def record_post_call(tool, **kwargs):
call_sequence.append(("post", tool))
return post_result

mock_pre.wrap_tool.side_effect = record_pre_call
mock_post.wrap_tool.side_effect = record_post_call

# Process a test tool through the pipeline
wrapped_tools = component.pipeline_manager.process_tools([test_tool])

# Verify both wrappers were called once
mock_pre.wrap_tool.assert_called_once()
mock_post.wrap_tool.assert_called_once()

# The pipeline reverses the order of wrapper application:
# 1. First applied: mock_pre (outermost, last registered)
# 2. Second applied: mock_post (innermost, first registered)

self.assertEqual(len(call_sequence), 2)
self.assertEqual(call_sequence[0][0], "pre")
self.assertEqual(call_sequence[1][0], "post")

# First wrapper (pre) should receive the original tool
self.assertEqual(call_sequence[0][1], test_tool)

# Second wrapper (post) should receive the result from pre_wrapper
self.assertEqual(call_sequence[1][1], pre_result)

# Final result should be what post_wrapper returned
self.assertEqual(wrapped_tools[0], post_result)

# This confirms the wrapping order is:
# post_wrapper(pre_wrapper(tool))
# Which creates this execution flow:
# 1. pre_wrapper validates the call (outermost)
# 2. Tool is executed
# 3. post_wrapper processes the result (innermost)

def test_tool_pipeline_manager(self):
"""Test the ToolPipelineManager class."""
manager = ToolPipelineManager()
wrapper1 = TestToolWrapper()
wrapper2 = TestToolWrapper()

# Add wrappers
manager.add_wrapper(wrapper1)
manager.add_wrapper(wrapper2)

# Check wrappers were added
self.assertEqual(len(manager.wrappers), 2)
self.assertIn(wrapper1, manager.wrappers)
self.assertIn(wrapper2, manager.wrappers)

# Process tools
tools = [SimpleTool()]
processed_tools = manager.process_tools(tools)

# Each wrapper should be applied once per tool
self.assertEqual(wrapper1.wrap_count, 1)
self.assertEqual(wrapper2.wrap_count, 1)

# Should return same number of tools
self.assertEqual(len(processed_tools), len(tools))

def test_disabled_wrapper_not_applied(self):
"""Test that disabled wrappers are not applied."""
manager = ToolPipelineManager()
wrapper1 = TestToolWrapper(is_available=True)
wrapper2 = TestToolWrapper(is_available=False)

manager.add_wrapper(wrapper1)
manager.add_wrapper(wrapper2)

tools = [SimpleTool()]
manager.process_tools(tools)

# Only the available wrapper should be applied
self.assertEqual(wrapper1.wrap_count, 1)
self.assertEqual(wrapper2.wrap_count, 0)

def test_post_tool_processing_wrapper(self):
"""Test that the post tool processing wrapper works correctly."""
with patch.object(PostToolProcessingWrapper, "wrap_tool") as mock_wrap:
# Create a mock for the wrapped tool
mock_post_processor = MagicMock(spec=PostToolProcessor)
mock_wrap.return_value = mock_post_processor

wrapper = PostToolProcessingWrapper(response_processing_size_threshold=10)
agent_mock = MagicMock()

# Call the wrap_tool method
result = wrapper.wrap_tool(self.test_tool, agent=agent_mock, user_query="test query")

# Check that wrap_tool was called with correct arguments
mock_wrap.assert_called_once_with(self.test_tool, agent=agent_mock, user_query="test query")

# Check that the result is what we expected
self.assertEqual(result, mock_post_processor)

@patch("lfx.components.agents.enhanced_agent._check_sparc_available", return_value=False)
def test_pre_tool_validation_wrapper_no_sparc(self, mock_check):
"""Test that the pre-tool validation wrapper works without SPARC."""
wrapper = PreToolValidationWrapper()

# Wrap the tool

wrapped_tool = wrapper.wrap_tool(self.test_tool)

self.assertIsInstance(wrapped_tool, ValidatedTool)
self.assertEqual(wrapped_tool.name, self.test_tool.name)
self.assertEqual(wrapped_tool.description, self.test_tool.description)
self.assertEqual(wrapped_tool.wrapped_tool, self.test_tool)
self.assertIsNone(wrapped_tool.sparc_component)

def test_combined_tool_wrapping(self):
"""Test that tools can be wrapped with both processors.

This test verifies:
1. The proper registration order of wrappers
2. Wrappers are applied in reverse order of registration
3. The execution flow follows this pattern:
- Pre-validator is applied first (outermost wrapper)
- Post-processor is applied next (innermost wrapper)
"""
# Create a pipeline and track wrapper application
pipeline = ToolPipelineManager()

# Create mock wrapper instances with tracking
post_wrapper = MagicMock()
post_wrapper.is_available = True
post_result = MagicMock(name="post_processed_tool")
post_wrapper.wrap_tool.return_value = post_result

pre_wrapper = MagicMock()
pre_wrapper.is_available = True
pre_result = MagicMock(name="pre_validated_tool")
pre_wrapper.wrap_tool.return_value = pre_result

# Record wrapper application sequence
call_sequence = []

# Setup wrapper side effects to track call sequence
def record_post_wrapper_call(tool, **kwargs):
call_sequence.append(("post", tool))
return post_result

def record_pre_wrapper_call(tool, **kwargs):
call_sequence.append(("pre", tool))
return pre_result

post_wrapper.wrap_tool.side_effect = record_post_wrapper_call
pre_wrapper.wrap_tool.side_effect = record_pre_wrapper_call

# Register wrappers in the same order as EnhancedAgentComponent:
# Post wrapper first, Pre wrapper second
pipeline.add_wrapper(post_wrapper)
pipeline.add_wrapper(pre_wrapper)

# Verify registration order matches implementation
self.assertEqual(len(pipeline.wrappers), 2)
self.assertIs(pipeline.wrappers[0], post_wrapper)
self.assertIs(pipeline.wrappers[1], pre_wrapper)

# Process a tool through the pipeline
original_tool = self.test_tool
result = pipeline.process_tools([original_tool], test_arg="value")

# Verify both wrappers were called once
post_wrapper.wrap_tool.assert_called_once()
pre_wrapper.wrap_tool.assert_called_once()

# Verify call sequence and parameters
self.assertEqual(len(call_sequence), 2)

# According to ToolPipelineManager.process_tools, wrappers should be
# applied in REVERSE order of registration:

# First called wrapper should be pre_wrapper (last registered)
self.assertEqual(call_sequence[0][0], "pre")
self.assertIs(call_sequence[0][1], original_tool)
pre_wrapper.wrap_tool.assert_called_with(original_tool, test_arg="value")

# Second called wrapper should be post_wrapper (first registered)
self.assertEqual(call_sequence[1][0], "post")
self.assertIs(call_sequence[1][1], pre_result)
post_wrapper.wrap_tool.assert_called_with(pre_result, test_arg="value")

# The final result should be the post_wrapper's return value
self.assertEqual(result, [post_result])

# This confirms the wrapping order is:
# post_wrapper(pre_wrapper(original_tool))
# Which creates this execution flow:
# 1. pre_wrapper validates the call (outermost wrapper)
# 2. original_tool executes
# 3. post_wrapper processes the result (innermost wrapper)


if __name__ == "__main__":
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Nov 2, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Move this suite to pytest-style tests
Our backend testing guideline requires test_*.py modules to use pytest fixtures/assertions rather than unittest.TestCase. Please refactor these tests into pytest-style functions (or classes using pytest fixtures) so they run consistently with the rest of the suite. As per coding guidelines.

🤖 Prompt for AI Agents
In src/lfx/tests/unit/components/agents/test_enhanced_agent.py around lines
47-392, the file uses unittest.TestCase style which must be converted to
pytest-style tests; refactor by replacing the TestEnhancedAgentComponent class
and its setUp with module or function-level pytest fixtures (e.g., a component
fixture returning EnhancedAgentComponent and a test_tool fixture), convert each
test_* method into a top-level pytest function that accepts the needed fixtures,
replace self.assertX calls with plain assert expressions, convert
unittest.mock.patch usage to pytest's monkeypatch or keep patch as a context
manager but used inside functions, and remove the if __name__ == "__main__"
block; ensure imports are adjusted (remove unittest import, add pytest) and all
tests maintain original assertions and mocking behavior.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 3, 2025

✅ Actions performed

Review triggered.

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.

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: 2

🧹 Nitpick comments (5)
src/lfx/src/lfx/components/agents/altk_agent_new.py (5)

211-227: Consider initializing SPARCReflectionComponent once during tool creation.

Both _run and _arun recreate the SPARCReflectionComponent on every invocation, which is inefficient. Additionally, using SPARCExecutionMode.SYNC in the async _arun method may not provide the performance benefits of async execution.

Consider initializing the component once during __init__:

     def __init__(
         self,
         wrapped_tool: BaseTool,
         agent,
         sparc_component=None,
         conversation_context=None,
         tool_specs=None,
         **kwargs,
     ):
         super().__init__(
             name=wrapped_tool.name,
             description=wrapped_tool.description,
             wrapped_tool=wrapped_tool,
             sparc_component=sparc_component,
             conversation_context=conversation_context or [],
             tool_specs=tool_specs or [],
             agent=agent,
             **kwargs,
         )
+        # Initialize SPARC component once if we have the agent
+        if agent and not self.sparc_component:
+            try:
+                llm_object = self._get_altk_llm_object()
+                if llm_object:
+                    self.sparc_component = SPARCReflectionComponent(
+                        config=ComponentConfig(llm_client=llm_object),
+                        track=Track.FAST_TRACK,
+                        execution_mode=SPARCExecutionMode.SYNC,
+                    )
+            except Exception as e:
+                logger.warning(f"Could not initialize SPARC component: {e}")
 
     def _run(self, *args, **kwargs) -> str:
         """Execute the tool with validation."""
-        self.sparc_component = SPARCReflectionComponent(
-            config=ComponentConfig(llm_client=self._get_altk_llm_object()),
-            track=Track.FAST_TRACK,  # Use fast track for performance
-            execution_mode=SPARCExecutionMode.SYNC,  # Use SYNC to avoid event loop conflicts
-        )
         return self._validate_and_run(*args, **kwargs)
 
     async def _arun(self, *args, **kwargs) -> str:
         """Async execute the tool with validation."""
-        self.sparc_component = SPARCReflectionComponent(
-            config=ComponentConfig(llm_client=self._get_altk_llm_object()),
-            track=Track.FAST_TRACK,  # Use fast track for performance
-            execution_mode=SPARCExecutionMode.SYNC,  # Use SYNC to avoid event loop conflicts
-        )
         return self._validate_and_run(*args, **kwargs)

588-590: Consider implementing async support or removing the commented code.

The _arun method is commented out. If async execution is not currently needed, remove the commented code to keep the codebase clean. If it's planned for future implementation, add a TODO comment explaining the plan.

-    # async def _arun(self, *args: Any, **kwargs: Any) -> str:
-    #     # Run the wrapped tool synchronously for now (can be enhanced for async later)
-    #     return self._run(*args, **kwargs)
+    async def _arun(self, *args: Any, **kwargs: Any) -> str:
+        """Async execution - delegates to sync for now.
+        
+        TODO: Enhance for true async execution when ALTK components support it.
+        """
+        return self._run(*args, **kwargs)

700-704: Remove unused variable assignment.

The variable actual_tool is assigned but then immediately used without any transformation. This appears to be leftover code from refactoring. Use tool directly or add logic to actually unwrap nested tools if needed.

-        # If the tool is already wrapped by another wrapper, we need to get the innermost tool
-        actual_tool = tool
-
         return PostToolProcessor(
-            wrapped_tool=actual_tool,
+            wrapped_tool=tool,
             user_query=user_query,
             agent=agent,
             response_processing_size_threshold=self.response_processing_size_threshold,
         )

887-903: Simplify redundant chat_history handling logic.

The code has multiple overlapping conditional blocks that check similar conditions for chat_history. This can be consolidated for better readability and maintainability.

         if hasattr(self, "chat_history") and self.chat_history:
-            if (
-                hasattr(self.chat_history, "to_data")
-                and callable(self.chat_history.to_data)
-                and self.chat_history.__class__.__name__ == "Data"
-            ):
-                input_dict["chat_history"] = data_to_messages(self.chat_history)
-            # Handle both lfx.schema.message.Message and langflow.schema.message.Message types
-            if all(
-                hasattr(m, "to_data") and callable(m.to_data) and "text" in m.data
-                for m in self.chat_history
-            ):
-                input_dict["chat_history"] = data_to_messages(self.chat_history)
-            if all(isinstance(m, Message) for m in self.chat_history):
+            # Check if it's a Data object or list of Messages
+            if isinstance(self.chat_history, Data):
+                input_dict["chat_history"] = data_to_messages(self.chat_history)
+            elif all(isinstance(m, Message) for m in self.chat_history):
                 input_dict["chat_history"] = data_to_messages(
                     [m.to_data() for m in self.chat_history]
                 )

819-832: Consolidate duplicate chat_history processing logic.

The chat_history conversion logic appears twice: once at lines 819-832 in update_runnable_instance and again at lines 887-903 in run_agent. Consider extracting this into a helper method to avoid duplication and ensure consistency.

Add a helper method:

def _prepare_chat_history(self) -> list[BaseMessage]:
    """Convert chat_history to list of BaseMessages."""
    if not hasattr(self, "chat_history") or not self.chat_history:
        return []
    
    if isinstance(self.chat_history, Data):
        return data_to_messages(self.chat_history)
    elif all(isinstance(m, Message) for m in self.chat_history):
        return [m.to_lc_message() for m in self.chat_history]
    
    return []

Then use it in both places:

# In update_runnable_instance
conversation_context.extend(self._prepare_chat_history())

# In run_agent
input_dict["chat_history"] = self._prepare_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 9771693 and 594be51.

📒 Files selected for processing (1)
  • src/lfx/src/lfx/components/agents/altk_agent_new.py (1 hunks)
🔇 Additional comments (6)
src/lfx/src/lfx/components/agents/altk_agent_new.py (6)

47-50: LGTM: Simple and clear utility function.

The helper function correctly sets the advanced flag on component inputs for better UI organization.


68-106: LGTM: Clean abstract base class design.

The BaseToolWrapper provides a solid foundation for the tool wrapper pipeline with clear interface contracts.


148-156: LGTM: Robust LLM extraction logic.

The method safely iterates through agent steps to find the bound LLM model with proper type checking.


495-542: LGTM: Well-designed pipeline manager.

The ToolPipelineManager correctly applies wrappers in reverse order, ensuring that pre-tool validation (outermost) wraps post-tool processing (innermost) as intended. The architecture is clean and extensible.


656-664: LGTM: AttributeError fix properly implemented.

The code now correctly checks that output is not None and has a result attribute before accessing it, addressing the past critical issue. Falls back to returning the raw tool_response when processing fails.


792-807: LGTM: Wrapper accumulation issue resolved.

The method now correctly clears the wrapper list before rebuilding, preventing the wrapper list from growing unbounded. This addresses the past critical issue.

Comment thread src/lfx/src/lfx/components/agents/altk_agent_new.py Outdated
Comment on lines +375 to +377
if not agent:
logger.warning("Cannot wrap tool with PostToolProcessor: missing 'agent'")
return tool
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Nov 3, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix incorrect warning message.

The warning message mentions "PostToolProcessor" but this is the PreToolValidationWrapper. Update the message to reflect the correct wrapper type.

         if not agent:
-            logger.warning("Cannot wrap tool with PostToolProcessor: missing 'agent'")
+            logger.warning("Cannot wrap tool with PreToolValidationWrapper: missing 'agent'")
             return tool
🤖 Prompt for AI Agents
In src/lfx/src/lfx/components/agents/altk_agent_new.py around lines 375 to 377,
the logger.warning message incorrectly references "PostToolProcessor" while this
function is the PreToolValidationWrapper; update the warning text to mention
"PreToolValidationWrapper" (or a similarly accurate wrapper name) so the log
correctly reflects the component, keeping the rest of the message intact.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@coderabbitai review

Copy link
Copy Markdown
Contributor Author

@korenLazar korenLazar Nov 4, 2025

Choose a reason for hiding this comment

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

@coderabbitai review

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.

@korenLazar, I've reviewed the code in this thread. The issue identified is valid and straightforward to fix:

Issue Summary

On Line 377 in src/lfx/src/lfx/components/agents/altk_agent_new.py, within the PreToolValidationWrapper.wrap_tool() method, there's a copy-paste error in the warning message:

Current (incorrect):

logger.warning("Cannot wrap tool with PostToolProcessor: missing 'agent'")

Should be:

logger.warning("Cannot wrap tool with PreToolValidationWrapper: missing 'agent'")

This warning message incorrectly references PostToolProcessor when it should reference PreToolValidationWrapper to accurately reflect which component is logging the warning.

Recommended Fix

Update the warning message to correctly identify the wrapper class that's generating it. This will make debugging and log analysis much clearer when this warning is encountered.


🧠 Learnings used
Learnt from: edwinjosechittilappilly
Repo: langflow-ai/langflow PR: 8504
File: src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json:391-393
Timestamp: 2025-06-12T15:25:01.072Z
Learning: The repository owner prefers CodeRabbit not to review or comment on JSON files because they are autogenerated.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 4, 2025

✅ Actions performed

Review triggered.

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.

@korenLazar korenLazar changed the title Altk agent2 feat: Adding an Agent component that uses pre and post tool reflection components from ALTK Nov 4, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 4, 2025
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: 1

🧹 Nitpick comments (2)
src/lfx/src/lfx/components/agents/altk_agent.py (2)

213-217: Consider reusing SPARCReflectionComponent instances.

Both _run and _arun create a new SPARCReflectionComponent instance on every tool call. If a tool is invoked multiple times during agent execution, this could impact performance. Consider instantiating the component once (e.g., in __init__ or lazily on first use) and reusing it, unless the component is stateful and requires fresh instances per call.

Also applies to: 222-226


880-919: Consider extracting chat history processing into helper methods.

The chat history and image content processing logic in run_agent is quite complex with multiple nested conditions. While this complexity is necessary to handle various input formats, extracting this logic into separate helper methods (e.g., _prepare_chat_history, _extract_image_content) could improve readability and maintainability.

📜 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 594be51 and 5fc2ede.

📒 Files selected for processing (2)
  • src/lfx/src/lfx/components/agents/__init__.py (1 hunks)
  • src/lfx/src/lfx/components/agents/altk_agent.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lfx/src/lfx/components/agents/init.py
🔇 Additional comments (2)
src/lfx/src/lfx/components/agents/altk_agent.py (2)

642-644: Verify the security implications of disabling the Docker sandbox.

The CodeGenerationComponent is configured with use_docker_sandbox=False, which means generated Python code will execute in the main process without isolation. If the code generation process can be influenced by untrusted tool responses or user inputs, this could pose a security risk.

Ensure that:

  1. The code generation component has appropriate safeguards against executing malicious code
  2. The ALTK library provides sufficient input validation and sanitization
  3. This setting is intentional and documented for your deployment environment

If uncertain about the security posture, consider enabling the Docker sandbox or implementing additional code inspection/validation before execution.


1-968: Overall: Well-structured implementation with addressed past issues.

The ALTK Agent implementation successfully integrates pre-tool validation (SPARC) and post-tool processing in a modular pipeline architecture. The past review comments regarding exception handling have been properly addressed:

✅ Line 630: Now catches ValueError and SyntaxError in addition to other exceptions
✅ Lines 657-659: Safe access to output.result with proper None and attribute checks

The code demonstrates good defensive programming with fallbacks, proper error logging, and graceful degradation when components fail. The wrapper pipeline design is extensible and the execution order (pre-tool → tool → post-tool) is correctly implemented through reverse-order wrapper application.

agent = kwargs.get("agent")

if not agent:
logger.warning("Cannot wrap tool with PostToolProcessor: missing 'agent'")
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 | 🟡 Minor

Fix the error message to reflect the correct wrapper type.

The warning message references "PostToolProcessor" but this code is in PreToolValidationWrapper. This copy-paste error could confuse debugging.

Apply this diff:

-            logger.warning("Cannot wrap tool with PostToolProcessor: missing 'agent'")
+            logger.warning("Cannot wrap tool with PreToolValidationWrapper: missing 'agent'")
📝 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
logger.warning("Cannot wrap tool with PostToolProcessor: missing 'agent'")
logger.warning("Cannot wrap tool with PreToolValidationWrapper: missing 'agent'")
🤖 Prompt for AI Agents
In src/lfx/src/lfx/components/agents/altk_agent.py around line 376, the warning
message incorrectly references "PostToolProcessor" but this is inside
PreToolValidationWrapper; update the log string to reference
"PreToolValidationWrapper" (e.g., "Cannot wrap tool with
PreToolValidationWrapper: missing 'agent'") so the message matches the actual
wrapper type; keep formatting and logging call unchanged.

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 4, 2025
@mendonk mendonk mentioned this pull request Nov 6, 2025
@edwinjosechittilappilly
Copy link
Copy Markdown
Collaborator

@coderabbitai what is your opinion on: o create a base for the component for ALTK, so the component code can focus on the user customizable code specific to run the component.
example ALTKBaseComponent, just like Agent Component?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 7, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read the ALTKAgentComponent implementation
cat src/lfx/src/lfx/components/agents/altk_agent.py

Length of output: 37180


🏁 Script executed:

#!/bin/bash
# Read the AgentComponent base class to understand the pattern
cat src/lfx/src/lfx/components/agents/agent.py

Length of output: 26591


🏁 Script executed:

#!/bin/bash
# Check if there are other agent components to understand the pattern
fd -e py -p "src/lfx/src/lfx/components/agents/" --type f

Length of output: 187


@edwinjosechittilappilly Great question! I can see the parallel you're drawing with how AgentComponent serves as a base class. Here's my architectural opinion:

The Case for ALTKBaseComponent

What Could Be Abstracted:

  1. ALTK LLM Client Mapping - The _get_altk_llm_object() method that maps LangChain LLMs to ALTK-compatible clients (currently supports OpenAI and Anthropic)

  2. Tool Wrapper Infrastructure:

    • BaseToolWrapper abstract class
    • ALTKBaseTool with common tool execution patterns
    • ToolPipelineManager for orchestrating multiple wrappers
  3. ALTK Component Configuration Patterns:

    • Standard imports from ALTK library (altk.core.llm, altk.core.toolkit, etc.)
    • Common error handling for ALTK operations
    • Agent phase management (RUNTIME, etc.)
  4. Tool Specification Conversion:

    • Utilities like convert_langchain_tools_to_sparc_tool_specs_format()

Benefits:

  • ✅ Reusability across multiple ALTK-based components
  • ✅ Centralized ALTK integration logic
  • ✅ Clearer separation: ALTK infrastructure vs. component-specific behavior
  • ✅ Easier to maintain ALTK version compatibility in one place
  • ✅ Follows the established pattern (AgentComponent as base)

Considerations

Current State:

  • Currently only one ALTK component exists (ALTKAgentComponent)
  • The wrapper infrastructure is comprehensive (~600 lines) but well-organized
  • No other ALTK components in the codebase yet

Questions to Consider:

  1. Are additional ALTK-based components planned (e.g., ALTKToolComponent, ALTKChainComponent)?
  2. Would those components reuse the tool wrapper infrastructure?
  3. Is there a roadmap for expanding ALTK integration?

Recommendation

If you're planning 2+ additional ALTK components: Create ALTKBaseComponent now. Extract:

class ALTKBaseComponent(Component):
    """Base class for ALTK-enhanced components."""
    
    def _get_altk_llm_object(self, use_output_val: bool = True) -> Any:
        """Map LangChain LLM to ALTK client."""
        # Current implementation
        
    @staticmethod
    def get_tool_pipeline_manager() -> ToolPipelineManager:
        """Factory for tool pipeline manager."""
        return ToolPipelineManager()

If this is the only ALTK component for now: Keep the current structure and refactor when a second ALTK component emerges. This avoids premature abstraction while keeping the door open for future extraction.

Hybrid Approach (Recommended): Extract just the utility functions into an altk_utils.py module now (minimal refactor), then create ALTKBaseComponent when the second ALTK component is added:

# lfx/components/agents/altk_utils.py
def get_altk_llm_object(agent, use_output_val=True):
    """Shared ALTK LLM mapping utility."""
    ...

def convert_tools_to_sparc_specs(tools):
    """Shared tool conversion utility."""
    ...

This gives you immediate reusability without over-engineering. What's your timeline for additional ALTK components?

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR introduces the ALTK (Agent Lifecycle Toolkit) Agent component, which adds pre-tool validation and post-tool processing capabilities to Langflow. The component validates tool calls using SPARC reflection before execution and processes JSON tool responses using code generation.

  • Implements modular tool wrapper architecture with BaseToolWrapper, PreToolValidationWrapper, and PostToolProcessingWrapper
  • Adds ALTKAgentComponent extending AgentComponent with configurable validation and processing
  • Integrates with ALTK library for validation and code generation features

Reviewed Changes

Copilot reviewed 38 out of 39 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/lfx/src/lfx/components/agents/altk_agent.py New ALTK agent implementation with pre-tool validation and post-tool JSON processing
src/lfx/src/lfx/components/agents/init.py Exports new ALTKAgentComponent
src/lfx/tests/unit/components/agents/init.py Test module docstring
src/lfx/tests/unit/components/init.py Test module docstring
src/backend/tests/unit/components/agents/test_altk_agent.py Comprehensive tests for ALTK agent with multiple model providers
pyproject.toml Adds agent-lifecycle-toolkit dependency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +422 to +423
logger.debug("Field name:", param_name)
logger.debug("Field info:", param_info)
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

The logger.debug() calls are using incorrect syntax. They appear to be using print-style multiple arguments, but logging methods expect a single message string. These should be logger.debug(f'Field name: {param_name}') and logger.debug(f'Field info: {param_info}') respectively.

Copilot uses AI. Check for mistakes.
)
return self._validate_and_run(*args, **kwargs)


Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

There is an extra blank line after the return statement at line 218, creating unnecessary whitespace. Remove this blank line for consistency with the rest of the codebase.

Copilot uses AI. Check for mistakes.

import ast
import json
import os
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Import of 'os' is not used.

Copilot uses AI. Check for mistakes.
from lfx.memory import delete_message
from lfx.schema.content_block import ContentBlock
from lfx.schema.data import Data
from lfx.schema.log import SendMessageFunctionType
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

Import of 'SendMessageFunctionType' is not used.

Copilot uses AI. Check for mistakes.
@edwinjosechittilappilly
Copy link
Copy Markdown
Collaborator

edwinjosechittilappilly commented Nov 7, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain
🏁 Script executed:

#!/bin/bash
# Read the ALTKAgentComponent implementation
cat src/lfx/src/lfx/components/agents/altk_agent.py

Length of output: 37180

🏁 Script executed:

#!/bin/bash
# Read the AgentComponent base class to understand the pattern
cat src/lfx/src/lfx/components/agents/agent.py

Length of output: 26591

🏁 Script executed:

#!/bin/bash
# Check if there are other agent components to understand the pattern
fd -e py -p "src/lfx/src/lfx/components/agents/" --type f

Length of output: 187

@edwinjosechittilappilly Great question! I can see the parallel you're drawing with how AgentComponent serves as a base class. Here's my architectural opinion:

The Case for ALTKBaseComponent

What Could Be Abstracted:

  1. ALTK LLM Client Mapping - The _get_altk_llm_object() method that maps LangChain LLMs to ALTK-compatible clients (currently supports OpenAI and Anthropic)

  2. Tool Wrapper Infrastructure:

    • BaseToolWrapper abstract class
    • ALTKBaseTool with common tool execution patterns
    • ToolPipelineManager for orchestrating multiple wrappers
  3. ALTK Component Configuration Patterns:

    • Standard imports from ALTK library (altk.core.llm, altk.core.toolkit, etc.)
    • Common error handling for ALTK operations
    • Agent phase management (RUNTIME, etc.)
  4. Tool Specification Conversion:

    • Utilities like convert_langchain_tools_to_sparc_tool_specs_format()

Benefits:

  • ✅ Reusability across multiple ALTK-based components
  • ✅ Centralized ALTK integration logic
  • ✅ Clearer separation: ALTK infrastructure vs. component-specific behavior
  • ✅ Easier to maintain ALTK version compatibility in one place
  • ✅ Follows the established pattern (AgentComponent as base)

Considerations

Current State:

  • Currently only one ALTK component exists (ALTKAgentComponent)
  • The wrapper infrastructure is comprehensive (~600 lines) but well-organized
  • No other ALTK components in the codebase yet

Questions to Consider:

  1. Are additional ALTK-based components planned (e.g., ALTKToolComponent, ALTKChainComponent)?
  2. Would those components reuse the tool wrapper infrastructure?
  3. Is there a roadmap for expanding ALTK integration?

Recommendation

If you're planning 2+ additional ALTK components: Create ALTKBaseComponent now. Extract:

class ALTKBaseComponent(Component):
    """Base class for ALTK-enhanced components."""
    
    def _get_altk_llm_object(self, use_output_val: bool = True) -> Any:
        """Map LangChain LLM to ALTK client."""
        # Current implementation
        
    @staticmethod
    def get_tool_pipeline_manager() -> ToolPipelineManager:
        """Factory for tool pipeline manager."""
        return ToolPipelineManager()

If this is the only ALTK component for now: Keep the current structure and refactor when a second ALTK component emerges. This avoids premature abstraction while keeping the door open for future extraction.

Hybrid Approach (Recommended): Extract just the utility functions into an altk_utils.py module now (minimal refactor), then create ALTKBaseComponent when the second ALTK component is added:

# lfx/components/agents/altk_utils.py
def get_altk_llm_object(agent, use_output_val=True):
    """Shared ALTK LLM mapping utility."""
    ...

def convert_tools_to_sparc_specs(tools):
    """Shared tool conversion utility."""
    ...

This gives you immediate reusability without over-engineering. What's your timeline for additional ALTK components?

Good suggestion @coderabbitai I would suggest altk_uitils.py which could ideally lead to better component code.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 7, 2025

Tip

For best results, initiate chat on the files or code changes.

@edwinjosechittilappilly Excellent! Let's create that altk_utils.py module. Here's a concrete implementation plan:

Proposed Structure for altk_utils.py

Create src/lfx/src/lfx/components/agents/altk_utils.py with the following structure:

"""Utility functions and constants for ALTK integration."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from langchain_core.tools import BaseTool

if TYPE_CHECKING:
    from langchain.agents import AgentExecutor
    from langchain_core.runnables import Runnable

# Constants
MODEL_PROVIDERS_LIST = ["Anthropic", "OpenAI"]
INPUT_NAMES_TO_BE_OVERRIDDEN = ["agent_llm"]


def set_advanced_true(component_input) -> None:
    """Mark a component input as advanced.
    
    Args:
        component_input: The input configuration object to mark as advanced.
    """
    component_input.advanced = True


def get_altk_llm_object(
    agent: Runnable | AgentExecutor,
    use_output_val: bool = True
) -> Any:
    """Map LangChain LLM to ALTK-compatible client.
    
    Converts LangChain model instances to their ALTK equivalents for
    integration with ALTK components (SPARC, post-processing, etc.).
    
    Args:
        agent: The LangChain agent or runnable containing the LLM.
        use_output_val: Whether to use output validation (default: True).
        
    Returns:
        An ALTK-compatible LLM client (ALTKAnthropicChatModel or ALTKOpenAIChatModel).
        
    Raises:
        ValueError: If the LLM type is not supported.
    """
    from altk.core.llm.altk_openai import ALTKOpenAIChatModel
    from altk.core.llm.anthropic import ALTKAnthropicChatModel
    from langchain_anthropic import ChatAnthropic
    from langchain_openai import ChatOpenAI

    llm = agent.runnable.bound.kwargs["llm"] if hasattr(agent, "runnable") else agent.llm
    
    if isinstance(llm, ChatOpenAI):
        return ALTKOpenAIChatModel(
            model=llm.model_name,
            api_key=llm.openai_api_key,
            use_output_val=use_output_val,
        )
    elif isinstance(llm, ChatAnthropic):
        return ALTKAnthropicChatModel(
            model=llm.model,
            api_key=llm.anthropic_api_key,
            use_output_val=use_output_val,
        )
    else:
        msg = f"Unsupported LLM type: {type(llm)}"
        raise ValueError(msg)


def convert_langchain_tools_to_sparc_tool_specs_format(tools: list[BaseTool]) -> list[dict]:
    """Convert LangChain tool definitions to SPARC-compatible format.
    
    Transforms LangChain BaseTool instances into the dictionary format
    expected by ALTK's SPARC validation component.
    
    Args:
        tools: List of LangChain BaseTool instances.
        
    Returns:
        List of dictionaries with SPARC-compatible tool specifications.
    """
    tool_specs = []
    for tool in tools:
        tool_spec = {
            "name": tool.name,
            "description": tool.description,
        }
        
        # Extract parameters from tool args schema if available
        if hasattr(tool, "args_schema") and tool.args_schema:
            tool_spec["parameters"] = tool.args_schema.model_json_schema()
        
        tool_specs.append(tool_spec)
    
    return tool_specs

Then Update altk_agent.py

Replace the existing implementations with imports:

from lfx.components.agents.altk_utils import (
    MODEL_PROVIDERS_LIST,
    INPUT_NAMES_TO_BE_OVERRIDDEN,
    set_advanced_true,
    get_altk_llm_object,
    convert_langchain_tools_to_sparc_tool_specs_format,
)

And update the methods in classes:

  • Remove _get_altk_llm_object from ALTKBaseTool and call get_altk_llm_object(self.agent, use_output_val) instead
  • Remove the static method convert_langchain_tools_to_sparc_tool_specs_format from PreToolValidationWrapper and use the imported function

Benefits

Cleaner separation: ALTK infrastructure separate from component logic
Reusability: Future ALTK components can import these utilities
Testability: Utilities can be unit tested independently
Maintainability: Single source of truth for ALTK integration patterns
Reduced file size: altk_agent.py becomes more focused

Next Steps

  1. Create altk_utils.py with the structure above
  2. Update imports in altk_agent.py
  3. Run existing tests to ensure no breakage
  4. Consider adding dedicated unit tests for altk_utils.py

Would you like me to help with any specific part of this refactoring?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 7, 2025

Tip

For best results, initiate chat on the files or code changes.

@edwinjosechittilappilly Excellent! I'm glad we're aligned on the altk_utils.py approach. This will definitely make the component code cleaner and more maintainable.

Here's what I'd recommend extracting first into altk_utils.py:

Priority Extractions

High Priority (immediate reusability):

  • _get_altk_llm_object() - LLM client mapping logic
  • convert_langchain_tools_to_sparc_tool_specs_format() - Tool spec conversion
  • set_advanced_true() - Input configuration helper

Medium Priority (when 2nd component emerges):

  • BaseToolWrapper, ALTKBaseTool - Core abstractions
  • ToolPipelineManager - Wrapper orchestration

This keeps the immediate refactor lightweight while setting up the foundation. When you're ready to proceed with the extraction, I'm happy to help review the refactored code structure! 🐰

(^◡^)っ✨

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 10, 2025
Copy link
Copy Markdown
Contributor

@ogabrielluiz ogabrielluiz Nov 10, 2025

Choose a reason for hiding this comment

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

Hey @korenLazar

Could you move the classes that are not supposed to be used as components to the src/lfx/base/agents folder?

Any classes in the src/lfx/components/ folders are loaded to the UI so we have to move them out of it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

resolved

Cristhianzl and others added 19 commits November 13, 2025 19:11
* fix youtube transcript api

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…ow-ai#10248)

* Fix non-processible erro when empty body is sent to fastAPI

* Annotate FlowDataRequest with Body for embedding

* Refine requestBody type for vertex order retrieval

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…ow-ai#10181)

* feat: add script to build static component index for fast startup

This script generates a prebuilt index of all built-in components in the lfx.components package, saving it as a JSON file for quick loading at runtime. It includes versioning and integrity verification through SHA256 hashing.

* chore: update package dependencies and versioning

- Bump revision to 3 in uv.lock.
- Update dependency markers for several packages to improve compatibility with Python versions and platforms.
- Increment versions for langflow (1.6.4) and langflow-base (0.6.4).
- Adjust dependency markers for packages related to darwin platform to enhance specificity.

* chore: update .gitignore to include component index cache

- Added entry for user-specific component index cache directory to .gitignore.
- Included member_servers.json in the ignore list for better file management.

* feat: enhance component loading with custom index support

- Introduced functions to detect development mode and read a custom component index from a specified path or URL.
- Added caching mechanism for dynamically generated component indices to improve performance.
- Updated `import_langflow_components` to utilize the new index reading and caching logic, allowing for faster startup in production mode.
- Added `components_index_path` to settings for user-defined index configuration.

* feat: add GitHub Actions workflow to automatically update component index

- Introduced a new workflow that triggers on pull requests and manual dispatch to update the component index.
- The workflow checks for changes in the component index and commits updates if necessary.
- Added a comment feature to notify users when the component index is updated.

* [autofix.ci] apply automated fixes

* fix: enhance development mode detection logic

- Updated the `_dev_mode` function to improve clarity and functionality in detecting development mode.
- Refined environment variable checks to explicitly handle "1"/"true"/"yes" for development and "0"/"false"/"no" for production.
- Maintained the editable install heuristic as a fallback for determining the mode when the environment variable is not set.

* refactor: simplify development mode detection logic

- Revised the `_dev_mode` function to clarify the detection of development mode.
- Removed the editable install heuristic, making the environment variable `LFX_DEV` the sole determinant for development mode.
- Updated documentation to reflect the new behavior and ensure accurate understanding of the mode switching.

* docs: update DEVELOPMENT.md to clarify component development mode

- Added tips for enabling dynamic component loading with `LFX_DEV=1` for faster development.
- Emphasized the importance of using `LFX_DEV=1` for live reloading of components during development.
- Included instructions for manually rebuilding the component index for testing purposes.

* add component index

* test: add unit tests for component index functionality

- Introduced comprehensive unit tests for the component index system, covering functions such as _dev_mode, _read_component_index, _save_generated_index, and import_langflow_components.
- Tests include various scenarios for development mode detection, reading and saving component indices, and handling custom paths and URLs.
- Enhanced test coverage to ensure robustness and reliability of the component index features.

* chore: update GitHub Actions workflow for component index updates

- Modified the workflow to include separate checkout steps for pull requests and manual dispatch events.
- Added an environment variable `LFX_DEV` to the build step for enhanced development mode support.
- Improved clarity in the workflow structure to accommodate different triggering events.

* chore: update component index with new timezones and remove deprecated entries

- Added new timezone options including America/Boise, Australia/North, and Etc/GMT-2.
- Removed outdated timezone entries to streamline the selection process.
- Updated the component index structure to enhance clarity and maintainability.

* docs: clarify output path determination in build_component_index.py

- Updated comment to specify that the output path is relative to the script location and intended for development/CI use, not from the installed package.
- Enhanced clarity for future developers regarding the script's execution context.

* refactor: update component import logic and structure

- Changed the comment to reflect the correct module path for extracting subpackage names.
- Flattened the custom components dictionary if it has a "components" wrapper for consistency.
- Merged built-in and custom components into a single structure, ensuring the output maintains a "components" wrapper.
- Updated the component count calculation to reflect the new merged structure.

* refactor: streamline component merging logic

- Simplified the merging of built-in and custom components by removing the "components" wrapper at the cache level.
- Updated the component count calculation to directly reflect the new structure of the merged components.
- Enhanced code clarity by refining comments related to the merging process.

* chore: enhance GitHub Actions workflow for component index updates

- Updated the workflow to conditionally comment on pull requests from community forks, instructing users to manually update the component index.
- Refined the commit and push logic to ensure it only executes for changes made within the same repository.

* chore: update component index [skip ci]

* chore: refine GitHub Actions workflow for component index checks

- Enhanced the logic to check for changes in the component index file, ensuring it only triggers actions for changes made within the same repository.
- Updated the PR comment step to clarify that it applies only to pull requests from the same repository, improving workflow accuracy.

* chore: update component index [skip ci]

* chore: update component index [skip ci]

* refactor: rename version retrieval function for clarity

- Changed the function name from _get_lfx_version to _get_langflow_version to accurately reflect the version being retrieved.
- Updated the version retrieval logic in the build_component_index function to use the new function name.

* fix: update version check to reflect langflow instead of lfx

- Changed the version check logic in the _read_component_index and _save_generated_index functions to use "langflow" instead of "lfx".
- Ensured that the component index version matches the installed langflow version for better accuracy.

* fix: sort timezone options in CurrentDateComponent

- Updated the timezone options in the CurrentDateComponent to be sorted for better user experience.
- Ensured that the dropdown displays timezones in a consistent and organized manner.

* chore: update component index with new timezone options and MistralAI model configurations

- Replaced outdated timezone options with a more relevant and diverse set for improved user experience.
- Added new configurations for the MistralAI model component, including input fields for API key, model selection, and request parameters.
- Updated version number to reflect recent changes.

* chore: update component index [skip ci]

* chore: update component index [skip ci]

* chore: update component index [skip ci]

* chore: update component index [skip ci]

* chore: minify component index output to reduce file size

* test: Add unit tests for build_component_index script functionality

* chore: enhance push logic in update-component-index workflow to handle concurrent updates with retries

* chore: update component index [skip ci]

* fix: standardize logging messages for MCP server initialization

* chore: update component index [skip ci]

* test: Add unit tests for build_component_index script functionality

* chore: update component index [skip ci]

* fix: improve error handling for missing LangChain dependencies in run.py

* feat: add deterministic normalization for component index serialization

* chore: update component index [skip ci]

* chore: update component index

* chore: update component index

* chore: update component index

* chore: enhance component index update workflow with detailed diff statistics and SHA256 comparison

* chore: update component index

* chore: update component loading message to reflect total components discovered

* chore: sort model options for improved readability in NVIDIA component

* chore: filter out 'localtime' from timezone options for improved user experience

* chore: update component index with sorted lists

* chore: update component index with mistral

* chore: update component index

* fix: improve error message for langflow tests to include detailed instructions for environment setup

* refactor: rename and enhance _dev_mode function to _parse_dev_mode for improved clarity and functionality; support boolean and list modes for module loading

* docs: enhance DEVELOPMENT.md with updated instructions for Component Development Mode, including dynamic loading options for specific components

* fix: enhance error handling in _read_component_index to log specific issues with fetching and parsing component indices, including corrupted JSON and missing SHA256 hash

* chore: update component index

* feat: add metadata to component index including number of modules and components for improved indexing information

* feat: integrate telemetry for component index loading, capturing metrics on modules and components, and enhancing performance tracking

* feat: add build command for dynamic component index generation

* fix: add missing import for json in CustomComponent definition in LoopTest.json

* fix: improve handling of dotted imports in prepare_global_scope function

* chore: update component index

* fix: refine import handling in prepare_global_scope to correctly manage aliased and dotted imports

* chore: update component index

* feat: enhance component index update workflow with detailed change analysis and summary

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
…-ai#9526)

* feat: Add CreateData component for dynamic input generation

* [autofix.ci] apply automated fixes

* feat: Refactor imports from langflow to lfx

* Add tests for create data

* Restore old create data component

* Update dynamic_create_data.py

* Update src/lfx/src/lfx/components/processing/dynamic_create_data.py

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>

* Update src/lfx/src/lfx/components/processing/dynamic_create_data.py

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes

* chore: update component index

* [autofix.ci] apply automated fixes

* chore: enhance component index update workflow with script existence check

* chore: update checkout step in component index workflow to use pull request repository and ref

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
* feat: Add run_id fields to telemetry payloads for enhanced tracking

* Introduced run_id to RunPayload, PlaygroundPayload, and ComponentPayload to facilitate better tracking of individual runs and components in telemetry data.

* fix: Update create_response to include run_id in telemetry payloads

* Added run_id field to the telemetry payloads in create_response for both success and error cases, aligning with the OpenAI endpoint's requirements for enhanced tracking.

* feat: Enhance flow execution with run_id for telemetry tracking

* Added run_id parameter to simple_run_flow and related functions to improve tracking of flow executions.
* Updated telemetry logging to include run_id for both successful and failed executions, ensuring better traceability.
* Refactored error handling in webhook_run_flow to maintain consistent telemetry logging.

* feat: Integrate run_id into telemetry for enhanced tracking in chat flow

* Added run_id generation and integration into the retrieve_vertices_order and build_vertex functions to improve telemetry tracking.
* Updated telemetry logging to include run_id for both successful and failed executions, ensuring better traceability of flow executions.

* feat: Enhance telemetry logging with run_id integration in generate_flow_events

* Added run_id generation and integration into the generate_flow_events function to improve tracking of flow executions.
* Updated telemetry logging to include run_id for both successful and failed executions, ensuring better traceability of flow events.
* Refactored log_telemetry function to accept run_id as a parameter for consistent logging across different execution paths.

* tests: Add run_id fields to telemetry payloads in integration tests

* Updated test assertions to validate the inclusion of run_id as None in the serialized output, aligning with the latest telemetry structure.

* feat: Integrate run_id into build_vertex for improved telemetry tracking

* Added run_id generation and integration into the build_vertex function to enhance telemetry tracking of component executions.
* Updated telemetry logging to include run_id for both successful and failed executions, ensuring better traceability of flow events.
* Refactored error handling to maintain consistent logging of run_id across different execution paths.

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

---------

Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…0266)

* chore: update dependency markers and add pytest-cov for coverage reporting

- Refined dependency markers for several packages to improve compatibility with Python 3.12 and specific platforms.
- Added pytest-cov to development dependencies for enhanced test coverage reporting.
- Updated dependencies for pyobjc frameworks to include platform-specific markers for better compatibility.

* chore: enhance lfx_tests command with coverage reporting

- Updated the lfx_tests target in the Makefile to include coverage reporting options for pytest.
- Added coverage metrics output in XML, HTML, and terminal formats to improve test visibility and analysis.

* chore: update codecov configuration for LFX coverage tracking

- Added LFX coverage target and threshold to the codecov.yml file.
- Defined separate coverage flags for frontend, backend, and LFX components.
- Updated ignore patterns to exclude LFX test and component directories from coverage reports.

* chore: add coverage upload steps to Python CI workflow

- Implemented steps to upload coverage reports to Codecov for Python 3.10.
- Added artifact upload for coverage reports, retaining them for 30 days.

* chore: update LFX coverage target in codecov configuration

- Increased the LFX coverage target from 40% to 60% to encourage aspirational improvement.
- Clarified the allowable drop in coverage threshold from 44% to 39% without failing the status check.

* chore: update coverage configuration in pyproject.toml

- Enabled branch coverage in the coverage run configuration.
- Fixed a typo in the main module check to ensure proper execution.
…angflow-ai#10291)

* chore: update pre-commit configuration to refine exclude patterns

Modified the exclude pattern for the detect-secrets hook to prevent false positives by excluding the specific component_index.json file in addition to the docs directory. This change enhances the accuracy of secret detection during pre-commit checks.

* chore: update ruff exclude patterns to include component_index.json

Added the component_index.json file to the exclude patterns in the ruff configuration to prevent false positives during linting. This change enhances the accuracy of code quality checks.

* chore: enhance GitHub Actions comments for component index updates

Updated the GitHub Actions workflow to improve the commenting mechanism for component index updates. Added logic to delete previous comments from the GitHub Actions bot to prevent duplicates and included a marker in the comment body for better tracking. This change ensures that users receive clear instructions on updating the component index when necessary.

---------

Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
* feat: Astra DB Base Class for Components

* [autofix.ci] apply automated fixes

* Update test_astra_component.py

* Update test_vector_store_rag.py

* [autofix.ci] apply automated fixes

* Update src/lfx/src/lfx/base/datastax/astradb_base.py

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

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* Clean up some of the naming

* Bring everything in line with the Base Component

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* Fix importing for circular

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* Update src/lfx/src/lfx/components/datastax/astradb_cql.py

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

* [autofix.ci] apply automated fixes

* Add comprehensive test suite

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* chore: update component index

* Update astradb_chatmemory.py

* Update the starter templates

* chore: update component index

* Update component_index.json

* chore: update component index

* [autofix.ci] apply automated fixes

* chore: update component index

* Remove cassandra chat from datastax bundle

* [autofix.ci] apply automated fixes

* chore: update component index

* chore: update component index

* More cleanup of astradb imports

* [autofix.ci] apply automated fixes

* chore: update component index

* Update the imports a bit

* [autofix.ci] apply automated fixes

* chore: update component index

* Update astradb_base.py

* [autofix.ci] apply automated fixes

* chore: update component index

* Create astradb_graph.py

* Update __init__.py

* chore: update component index

* chore: update component index

* Fix a couple broken tests

* chore: update component index

* [autofix.ci] apply automated fixes

* chore: update component index

* chore: update component index

* 📝 (Vector Store.spec.ts): remove unnecessary empty line to improve code readability

* 🔧 (.github/workflows/typescript_test.yml): free up disk space to optimize workflow performance

* chore: update component index

* 🔧 (.github/workflows/typescript_test.yml): remove unnecessary tool cache directories and docker images to free up disk space

* 🔧 (.github/workflows/typescript_test.yml): remove unnecessary step to free disk space to optimize workflow execution

* chore: update component index

* chore: update component index

* fix: Refactor out unneeded pieces from base component

* Move embedding model stuff to vectorstore

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* fix tests

* Update test_astradb_base_component.py

* Update test_astradb_base_component.py

* [autofix.ci] apply automated fixes

* Update astradb_vectorstore.py

* Fix ruff

* starter proj

* Spacing

* Ruff formatting

* [autofix.ci] apply automated fixes

* Component index update

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>
…licts (langflow-ai#10354)

* fix: resolve SLF001 private member access violations

This commit fixes SLF001 (private member access) violations by:

1. Creating and using public getters for internal code:
   - CustomComponent: Use get_vertex(), get_results(), set_results(),
     get_artifacts(), set_artifacts() instead of direct private access
   - TracingService: Use component.get_vertex() instead of ._vertex
   - ComposioBaseComponent: Add classmethods get_actions_cache(),
     get_action_schema_cache(), get_all_auth_field_names()
   - ChatComponent: Use get_vertex() and get_id() methods

2. Adding noqa comments for third-party library private access:
   - chroma._collection and chroma._client (langchain-chroma)
   - request._send (FastAPI/Starlette)
   - langwatch and opik client private members

3. Fixing B008 errors (function calls in argument defaults):
   - FastAPI: Use Annotated[Type, Depends()] pattern
   - Typer: Add noqa comments for CLI argument defaults

4. Fixing PLR2004 (magic values in tests):
   - Add per-file-ignores for src/lfx/tests/* in pyproject.toml

This reduces ruff errors from 298 to 107 (64% reduction).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: remove redundant ruff configuration from pyproject.toml files

This commit removes the ruff configuration sections from both the backend and lfx pyproject.toml files, streamlining the project setup. The removed configurations included linting rules, per-file ignores, and other related settings that are no longer necessary.

* config: add comprehensive per-file ruff ignores

Add per-file-ignores to handle legitimate cases that can't be fixed:

1. FastAPI endpoints (TCH rules):
   - api/v1/* and api/v2/* need runtime type evaluation

2. Security warnings (S104, S105, S108, S301, S110):
   - Intentional binding to all interfaces for servers
   - False positives for PASSWORD constants and token variables
   - Intentional pickle usage in caching
   - Legitimate try-except-pass in optional metadata

3. Code execution (S102):
   - Intentional exec/eval in dynamic code tools and validation

4. Third-party library private access (SLF001):
   - Google API, MongoDB, Chroma, MCP, Grandalf libraries
   - Component introspection and code analysis utilities

5. CLI tools (B008):
   - Typer requires function calls in argument defaults

This configuration ensures ruff checks pass consistently with
or without the --config flag.

* refactor: replace private member access with public getters

Replace private member access with public API methods for better
encapsulation and maintainability:

1. Component base inputs:
   - Use get_base_inputs() instead of _base_inputs
   - Updated AgentComponent, CugaComponent, AmazonBedrockConverseModel

2. Component methods:
   - Rename _run_actor() to run_actor() in ApifyActorsComponent
   - Rename _reset_all_output_values() to reset_all_output_values()
   - Use get_output_logs() instead of _output_logs

Files changed:
- src/lfx/src/lfx/components/agents/agent.py
- src/lfx/src/lfx/components/agents/cuga_agent.py
- src/lfx/src/lfx/components/amazon/amazon_bedrock_converse.py
- src/lfx/src/lfx/components/apify/apify_actor.py
- src/lfx/src/lfx/custom/custom_component/component.py
- src/lfx/src/lfx/graph/graph/base.py
- src/lfx/src/lfx/graph/vertex/vertex_types.py

This eliminates 6 SLF001 violations by using proper public APIs.

* fix: add noqa comments for unavoidable third-party private access

Add SLF001 noqa comments for cases where we must access private
members of third-party libraries:

1. Chroma vector store:
   - Access _collection to get document metadata
   - Access _client to retrieve embeddings
   (langchain-chroma library)

2. FastAPI/Starlette Request:
   - Access _send for SSE (Server-Sent Events) connections
   - Required by MCP SSE implementation
   (starlette library)

3. MongoDB Atlas:
   - Access _collection to verify search index
   - Add pragma comment for certificate format documentation
   (langchain-mongodb library)

These are unavoidable as the libraries don't expose public APIs
for these use cases.

Files changed:
- src/backend/base/langflow/api/v1/knowledge_bases.py
- src/backend/base/langflow/api/v1/mcp.py
- src/backend/base/langflow/api/v1/mcp_projects.py
- src/lfx/src/lfx/components/vectorstores/mongodb_atlas.py

* style: auto-fix import sorting and add test secret pragmas

Auto-fixed import sorting violations (I001) in test files using
ruff's --fix option. Also added pragma comments for test API keys
flagged by detect-secrets hook.

Changes:
1. Import sorting (auto-fixed by ruff):
   - Fixed I001 violations in 40 test files
   - Fixed import sorting in langflow/custom/__init__.py

2. Secret pragmas (false positives in tests):
   - Added 'pragma: allowlist secret' for test API keys
   - These are test constants like 'test-key', not real secrets
   - Fixed in test_serve.py, test_serve_app.py, test_common.py,
     test_param_handler.py, test_graph_state_model.py

All changes are formatting-only with no functional impact.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* fix: enhance error handling in AstraDBBaseComponent

Updated the exception handling in AstraDBBaseComponent to log detailed error messages when metadata retrieval fails. This improves debugging capabilities by providing context on the failure, including the database name and the exception message.

Files changed:
- src/lfx/src/lfx/base/datastax/astradb_base.py

* fix: restore critical import order and fix tracing test mock

Fix issues introduced by import sorting auto-fix:

1. Restore import order in langflow/custom/__init__.py:
   - Move 'from lfx import custom' back to first position
   - Import order affects initialization and component loading
   - Added per-file-ignore (I001) to prevent future auto-sorting

2. Fix tracing service test mock:
   - Update mock_component fixture to support get_vertex() method
   - Create proper mock_vertex object so .id returns string value
   - Fixes: AssertionError in test_trace_component

3. Update .secrets.baseline:
   - Pre-commit hook updated baseline for new test files

Note: test_refresh_starter_projects and test_get_all failures are
pre-existing on main branch (only 'agents' category loads due to
upstream component loading issues), not caused by this PR.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* config: update ruff configuration for enhanced linting

- Set target Python version to 3.10.
- Added exclusions for specific directories and files to improve linting accuracy.
- Enhanced linting rules with new flake8 configurations for better type checking and immutability handling.

These changes aim to refine the linting process and ensure compatibility with the latest coding standards.

* style: format code for consistency and clarity

- Adjusted the formatting of the `env_file` option in `serve_command` for improved readability.
- Restored import order in `schema.py` by moving `EdgeData` and `NodeData` imports to the correct section, enhancing code organization.

These changes aim to maintain consistent code style and improve clarity in the command and schema files.

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…ut component (langflow-ai#10313)

* fix: add direct langchain fallback for trustcall extractor in structured output component

chore: update component index

bump ollama, add min length to schema to ensure non-empty output, broaden exception handling, and resolve ruff checks

chore: update component index

add pytest match string to fix ruff check

refactored s.o.c to use get_chat_result in the lc fallback and added more user-friendly logs. updated unit tests accordingly.

chore: update component index

resolve ruff errors

* chore: update component index

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* Update version to 1.6.7

* bump lfx too

* choosed current versino in openapi.json of 1.6.5 vs 1.6.7

* choosed current versino in openapi.json of 1.6.5 vs 1.6.7

* more version bumps

* missed this one

* change pypi_nightly_tag.py version to read it from pyproject.toml directly

* get_latest_version was missing arg build_type

* naming error

* using lfx logic to explore for MAIN_PAGE

* using lfx logic to explore for MAIN_PAGE

* allow --prerelease

* change script in nightly_build

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

---------

Co-authored-by: Olfa Maslah <olfamaslah@Olfas-MacBook-Pro.local>
Co-authored-by: Olfa Maslah <olfamaslah@macbookpro.war.can.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* fix youtube transcript api

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* feat: Add user registration endpoints in API v2. Desktop Model-credits initiative.

* [autofix.ci] apply automated fixes

* fix: adjust registration API endpoints to REST compliance.

* [autofix.ci] apply automated fixes

* feat: Implement registration API queries for fetching and posting registrations

* feat: Enhance registration API with secure file handling and add hooks for fetching registration

* refactor: Lazy file creation.

* Commit: Delete unused file use-get-registratrions.ts

* feat: Add unit and integration tests for registration API

* refactor: Simplify registration response model by removing success and message fields

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* refactor: Remove success and message assertions from registration tests

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 13, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 13, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 13, 2025
@korenLazar korenLazar closed this Nov 13, 2025
@korenLazar
Copy link
Copy Markdown
Contributor Author

I opened a new PR instead of this one:
#10587

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community Pull Request from an external contributor enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.