feat(agent): add clarification extensibility hook

This commit is contained in:
Haohao-end 2026-03-15 01:23:52 +08:00
parent 1b6e695520
commit 49da7fc7ca
7 changed files with 174 additions and 0 deletions

View File

@ -9,6 +9,7 @@ from dify_graph.node_events import NodeEventBase, NodeRunResult, StreamCompleted
from dify_graph.nodes.base.node import Node
from dify_graph.nodes.base.variable_template_parser import VariableTemplateParser
from .clarification_helper import should_enable_clarification
from .entities import AgentNodeData
from .exceptions import (
AgentInvocationError,
@ -150,6 +151,11 @@ class AgentNode(Node[AgentNodeData]):
node_id=self._node_id,
node_execution_id=self.id,
)
# Extensibility hook for human clarification (HITL support)
# Currently a no-op, but allows future HITL implementation
if should_enable_clarification(self.node_data):
# Placeholder for future clarification logic
pass
except PluginDaemonClientSideError as e:
transform_error = AgentMessageTransformError(
f"Failed to transform agent message: {str(e)}", original_error=e

View File

@ -0,0 +1,51 @@
"""
Clarification helper for agent node human-in-the-loop support.
This module provides extensibility hooks for future HITL (Human-In-The-Loop) features.
Currently, it serves as a placeholder for clarification request extraction and handling.
"""
from __future__ import annotations
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from .entities import AgentNodeData
def should_enable_clarification(node_data: AgentNodeData) -> bool:
"""
Check if human clarification is enabled for this agent node.
Args:
node_data: The agent node data configuration.
Returns:
True if human clarification is enabled, False otherwise.
"""
return node_data.enable_human_clarification
def extract_clarification_request(
agent_output: dict[str, Any],
enable_clarification: bool,
) -> dict[str, Any] | None:
"""
Extract clarification request from agent output if enabled.
This is a placeholder for future HITL implementation.
Currently returns None as clarification is not yet implemented.
Args:
agent_output: The output from agent execution.
enable_clarification: Whether clarification is enabled.
Returns:
Clarification request dict if found and enabled, None otherwise.
"""
if not enable_clarification:
return None
# Placeholder for future clarification extraction logic
# This will be extended when HITL feature is fully implemented
return None

View File

@ -19,6 +19,8 @@ class AgentNodeData(BaseNodeData):
# If this value is None, it indicates this is a previous version
# and requires using the legacy parameter parsing rules.
tool_node_version: str | None = None
# Enable human clarification for agent reasoning
enable_human_clarification: bool = False
class AgentInput(BaseModel):
value: Union[list[str], list[ToolSelector], Any]

View File

@ -0,0 +1,95 @@
"""
Tests for agent node clarification helper and configuration.
"""
import pytest
from core.workflow.nodes.agent.clarification_helper import (
extract_clarification_request,
should_enable_clarification,
)
from core.workflow.nodes.agent.entities import AgentNodeData
from dify_graph.enums import NodeType
class TestClarificationHelper:
"""Test suite for clarification helper functions."""
def test_should_enable_clarification_when_enabled(self):
"""Test that should_enable_clarification returns True when enabled."""
node_data = AgentNodeData(
id="test_node",
type=NodeType.AGENT,
agent_strategy_provider_name="test_provider",
agent_strategy_name="test_strategy",
agent_strategy_label="Test Strategy",
agent_parameters={},
enable_human_clarification=True,
)
assert should_enable_clarification(node_data) is True
def test_should_enable_clarification_when_disabled(self):
"""Test that should_enable_clarification returns False when disabled."""
node_data = AgentNodeData(
id="test_node",
type=NodeType.AGENT,
agent_strategy_provider_name="test_provider",
agent_strategy_name="test_strategy",
agent_strategy_label="Test Strategy",
agent_parameters={},
enable_human_clarification=False,
)
assert should_enable_clarification(node_data) is False
def test_should_enable_clarification_default_false(self):
"""Test that clarification is disabled by default."""
node_data = AgentNodeData(
id="test_node",
type=NodeType.AGENT,
agent_strategy_provider_name="test_provider",
agent_strategy_name="test_strategy",
agent_strategy_label="Test Strategy",
agent_parameters={},
)
assert should_enable_clarification(node_data) is False
def test_extract_clarification_request_when_disabled(self):
"""Test that extract_clarification_request returns None when disabled."""
result = extract_clarification_request(
agent_output={"text": "test output"},
enable_clarification=False,
)
assert result is None
def test_extract_clarification_request_when_enabled(self):
"""Test that extract_clarification_request returns None when enabled (placeholder)."""
# Currently returns None as placeholder for future implementation
result = extract_clarification_request(
agent_output={"text": "test output"},
enable_clarification=True,
)
assert result is None
def test_agent_node_data_with_clarification_field(self):
"""Test that AgentNodeData properly stores enable_human_clarification."""
node_data = AgentNodeData(
id="test_node",
type=NodeType.AGENT,
agent_strategy_provider_name="test_provider",
agent_strategy_name="test_strategy",
agent_strategy_label="Test Strategy",
agent_parameters={},
enable_human_clarification=True,
)
assert node_data.enable_human_clarification is True
node_data_disabled = AgentNodeData(
id="test_node",
type=NodeType.AGENT,
agent_strategy_provider_name="test_provider",
agent_strategy_name="test_strategy",
agent_strategy_label="Test Strategy",
agent_parameters={},
enable_human_clarification=False,
)
assert node_data_disabled.enable_human_clarification is False

View File

@ -10,6 +10,7 @@ import { isSupportMCP } from '@/utils/plugin-version-feature'
import { useStore } from '../../store'
import { AgentStrategy } from '../_base/components/agent-strategy'
import Field from '../_base/components/field'
import FormInputBoolean from '../_base/components/form-input-boolean'
import { MCPToolAvailabilityProvider } from '../_base/components/mcp-tool-availability'
import MemoryConfig from '../_base/components/memory-config'
import OutputVars, { VarItem } from '../_base/components/output-vars'
@ -101,6 +102,22 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
/>
</>
)}
<Split />
<Field
title={t('nodes.agent.enableHumanClarification.label', { ns: 'workflow' })}
tooltip={t('nodes.agent.enableHumanClarification.tooltip', { ns: 'workflow' })}
className="px-0 py-2"
>
<FormInputBoolean
value={inputs.enable_human_clarification ?? false}
onChange={(value) => {
setInputs({
...inputs,
enable_human_clarification: value,
})
}}
/>
</Field>
</div>
<div>
<OutputVars>

View File

@ -13,6 +13,7 @@ export type AgentNodeType = CommonNodeType & {
memory?: Memory
version?: string
tool_node_version?: string
enable_human_clarification?: boolean
}
export enum AgentFeature {

View File

@ -373,6 +373,8 @@
"nodes.agent.toolbox": "toolbox",
"nodes.agent.tools": "Tools",
"nodes.agent.unsupportedStrategy": "Unsupported strategy",
"nodes.agent.enableHumanClarification.label": "Enable Human Clarification",
"nodes.agent.enableHumanClarification.tooltip": "Allow human intervention to clarify agent reasoning during execution",
"nodes.answer.answer": "Answer",
"nodes.answer.outputVars": "Output Variables",
"nodes.assigner.append": "Append",