Skip to content

feat: AI node supports workflow calling tools#4955

Merged
shaohuzhang1 merged 1 commit intov2from
pr@v2@feat_ai_workflow_tool
Mar 26, 2026
Merged

feat: AI node supports workflow calling tools#4955
shaohuzhang1 merged 1 commit intov2from
pr@v2@feat_ai_workflow_tool

Conversation

@shaohuzhang1
Copy link
Contributor

feat: AI node supports workflow calling tools

@f2c-ci-robot
Copy link

f2c-ci-robot bot commented Mar 26, 2026

Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

tool_init_params, source_id, source_type, chat_id, tools)
return NodeResult(
{'result': r, 'chat_model': chat_model, 'message_list': message_list,
'history_message': [{'content': message.content, 'role': message.type} for message in
Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. Import statements: The uuid module is imported twice, which is unnecessary.
  2. Class/function definitions: Ensure all class names and function names are consistent with CamelCase convention (e.g., _write_context, not _Write_context). It's generally a good practice to use underscores at the beginning of private methods/functions.
  3. JSON usage consistency: Use standard Python library imports (json) instead of importing them again under different aliases (json as ...).
  4. Docstrings/Comments: Add more docstrings and comments to explain complex functions and logic, especially those related to handling tools and workflows.
  5. SQL query optimizations: Consider using ORM queries efficiently, such as eager loading relationships or reducing the number of database roundtrips where applicable.
  6. Code reuse: Refactor reusable code into separate modules or functions whenever possible to improve maintainability and reduce redundancy.

Here's an optimized version of the script incorporating some suggested improvements:

import json
import re
import time
from functools import reduce
from typing import List, Dict

from langchain_core.tools import StructuredTool
from application.flow.common import Workflow, WorkflowMode
from application.flow.i_step_node import NodeResult, INode, ToolWorkflowPostHandler, ToolWorkflowCallPostHandler
from application.flow.step_node.ai_chat_step_node.i_chat_node import IChatNode
from application.flow.tools import Reasoning, mcp_response_generator
from common.exception.app_exception import AppApiException
from common.utils.rsa_util import rsa_long_decrypt
from common.utils.shared_resource_auth import filter_authorized_ids
from common.utils.tool_code import ToolExecutor
from django.db.models import QuerySet, OuterRef, Subquery


class YourClass:
    def _handle_mcp_request(self, mcp_source, mcp_servers, mcp_tool_id, mcp_tool_ids, tool_ids,
                            application_ids, skill_tool_ids, mcp_output_enable, chat_model, message_list, history_message,
                            question, chat_id):
        # Remove redundant UUID import
        import uuid

        mcp_servers_config = {}

        for item in [mcp_source] + [mcp_tool for mcp_tool in mcp_tool_ids]:
            if isinstance(item, str):  # Check if item is a string before attempting to decode JSON
                try:
                    decoded_json = json.loads(rsa_long_decrypt(item))
                    mcp_servers_config.update(decoded_json)
                except Exception as e:
                    print(f"Failed to parse MCP configuration: {e}")

        # Continue existing functionality here...

# Example Usage
instance_of_class = YourClass()
result = instance_of_class._handle_mcp_request(...)

source_id, source_type, temp_dir, chat_id, extra_tools)
async for chunk in async_gen:
result_queue.put(('data', chunk))
except Exception as e:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here's some advice and comments on your provided code:

  1. Line 59: The function _upsert_fragment has inconsistent use of brackets () and [ ]. Consider being consistent.
  2. Line 67: There seems to be a logical error in this line related to checking conditions within the loop.
  3. Line 70: The result_queue.put call could benefit from using .join() before processing results asynchronously to ensure proper synchronization.
  4. Overall Structure:
    • _yield_mcp_response: Async generator should handle exceptions better with try-except blocks.
    • mcp_response_generator: Synchronous wrapper might not work well with global event loops; consider asynchronous alternatives.

Specific Recommendations:

# Ensure consistent bracket usage throughout the code for readability.
def _upsert_fragment(key, raw_id, func_name, part_args):
    if part_args == '':
        part_args = {}

... rest of methods...
...

async def save_tool_record(tool_id, tool_info, tool_result, source_id, source_type):
    ...

... add more context-based improvements where appropriate...

Feel free to adapt these comments based on further review and understanding of your specific requirements!


class ToolWorkflowPostHandler(WorkFlowPostHandler):
def __init__(self, chat_info, tool_id):
super().__init__(chat_info)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The provided code seems to have several issues:

  1. Class Duplication: The third class definition of ToolWorkflowPostHandler is identical to the first one, which can lead to confusion and errors if not resolved.

  2. Variable Initialization Issue: In the second class definition, there are no values assigned to self.chat_info, making it impossible to use or modify this variable within the handlers.

  3. Method Overriding and Reinitialization: Even though this might be an oversight, reassigning self.chat_info and self.tool_id after calling the base class method can cause unexpected behavior.

  4. Documentation Lack: Comments are sparse, making it difficult to understand the purpose and functionality of each part of the code.

To improve the code:

  • Remove the duplicate class definition of ToolWorkflowPostHandler.
  • Assign initial values to self.chat_info and self.tool_id before the call to super().__init__().
  • Ensure that all necessary methods override their Base class equivalents properly with valid implementations.

Here's a corrected version (assuming you want to keep only one implementation):

class ToolWorkflowPostHandler(WorkFlowPostHandler):
    def __init__(self, chat_info, tool_id):
        super().__init__()
        self.chat_info = chat_info
        self.tool_id = tool_id

    # Assuming handler needs specific logic related to 'tool_id'
    def handler(self, workflow):
        print(f"Handling Workflow for Tool ID {self.tool_id}")
        # Add actual business logic here based on workflow state

This revision ensures that ChatInfo and tool_id are initialized correctly during the initialization process and provides a clear structure for handling work items associated with tools through workflows.

@f2c-ci-robot
Copy link

f2c-ci-robot bot commented Mar 26, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@shaohuzhang1 shaohuzhang1 merged commit c8465ef into v2 Mar 26, 2026
3 checks passed
@shaohuzhang1 shaohuzhang1 deleted the pr@v2@feat_ai_workflow_tool branch March 26, 2026 03:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant