diff --git a/api/core/app/entities/queue_entities.py b/api/core/app/entities/queue_entities.py index fb5d0fb299..334e2abf87 100644 --- a/api/core/app/entities/queue_entities.py +++ b/api/core/app/entities/queue_entities.py @@ -329,6 +329,7 @@ class QueueAgentLogEvent(AppQueueEvent): error: str | None status: str data: Mapping[str, Any] + metadata: Optional[Mapping[str, Any]] = None class QueueNodeRetryEvent(QueueNodeStartedEvent): diff --git a/api/core/app/entities/task_entities.py b/api/core/app/entities/task_entities.py index d186038c28..b5b909a3e9 100644 --- a/api/core/app/entities/task_entities.py +++ b/api/core/app/entities/task_entities.py @@ -716,6 +716,7 @@ class AgentLogStreamResponse(StreamResponse): error: str | None status: str data: Mapping[str, Any] + metadata: Optional[Mapping[str, Any]] = None event: StreamEvent = StreamEvent.AGENT_LOG data: Data diff --git a/api/core/app/task_pipeline/workflow_cycle_manage.py b/api/core/app/task_pipeline/workflow_cycle_manage.py index 69d9142814..31df7d2d86 100644 --- a/api/core/app/task_pipeline/workflow_cycle_manage.py +++ b/api/core/app/task_pipeline/workflow_cycle_manage.py @@ -862,5 +862,6 @@ class WorkflowCycleManage: error=event.error, status=event.status, data=event.data, + metadata=event.metadata, ), ) diff --git a/api/core/tools/entities/tool_entities.py b/api/core/tools/entities/tool_entities.py index 354e1e8360..02f66c545d 100644 --- a/api/core/tools/entities/tool_entities.py +++ b/api/core/tools/entities/tool_entities.py @@ -167,6 +167,7 @@ class ToolInvokeMessage(BaseModel): error: Optional[str] = Field(default=None, description="The error message") status: LogStatus = Field(..., description="The status of the log") data: Mapping[str, Any] = Field(..., description="Detailed log data") + metadata: Optional[Mapping[str, Any]] = Field(default=None, description="The metadata of the log") class MessageType(Enum): TEXT = "text" diff --git a/api/core/workflow/graph_engine/entities/event.py b/api/core/workflow/graph_engine/entities/event.py index dca1021163..9d3a3f8f9f 100644 --- a/api/core/workflow/graph_engine/entities/event.py +++ b/api/core/workflow/graph_engine/entities/event.py @@ -203,6 +203,7 @@ class AgentLogEvent(BaseAgentEvent): error: str | None = Field(..., description="error") status: str = Field(..., description="status") data: Mapping[str, Any] = Field(..., description="data") + metadata: Optional[Mapping[str, Any]] = Field(default=None, description="metadata") InNodeEvent = BaseNodeEvent | BaseParallelBranchEvent | BaseIterationEvent | BaseAgentEvent diff --git a/api/core/workflow/nodes/agent/agent_node.py b/api/core/workflow/nodes/agent/agent_node.py index 798d6a550d..38f49d80dc 100644 --- a/api/core/workflow/nodes/agent/agent_node.py +++ b/api/core/workflow/nodes/agent/agent_node.py @@ -89,7 +89,11 @@ class AgentNode(ToolNode): try: # convert tool messages - yield from self._transform_message(message_stream, {}, parameters_for_log) + yield from self._transform_message( + message_stream, + {"provider": (cast(AgentNodeData, self.node_data)).agent_strategy_provider_name}, + parameters_for_log, + ) except PluginDaemonClientSideError as e: yield RunCompletedEvent( run_result=NodeRunResult( @@ -170,7 +174,12 @@ class AgentNode(ToolNode): extra.get("descrption", "") or tool_runtime.entity.description.llm ) - tool_value.append(tool_runtime.entity.model_dump(mode="json")) + tool_value.append( + { + **tool_runtime.entity.model_dump(mode="json"), + "runtime_parameters": tool_runtime.runtime.runtime_parameters, + } + ) value = tool_value if parameter.type == "model-selector": value = cast(dict[str, Any], value) diff --git a/api/core/workflow/nodes/tool/tool_node.py b/api/core/workflow/nodes/tool/tool_node.py index 3e56d9265c..3adce10932 100644 --- a/api/core/workflow/nodes/tool/tool_node.py +++ b/api/core/workflow/nodes/tool/tool_node.py @@ -1,5 +1,5 @@ from collections.abc import Generator, Mapping, Sequence -from typing import Any, cast +from typing import Any, Optional, cast from sqlalchemy import select from sqlalchemy.orm import Session @@ -197,6 +197,7 @@ class ToolNode(BaseNode[ToolNodeData]): json: list[dict] = [] agent_logs: list[AgentLogEvent] = [] + agent_execution_metadata: Optional[Mapping[NodeRunMetadataKey, Any]] = {} variables: dict[str, Any] = {} @@ -264,6 +265,11 @@ class ToolNode(BaseNode[ToolNodeData]): ) elif message.type == ToolInvokeMessage.MessageType.JSON: assert isinstance(message.message, ToolInvokeMessage.JsonMessage) + if self.node_type == NodeType.AGENT: + msg_metadata = message.message.json_object.pop("execution_metadata", {}) + agent_execution_metadata = { + key: value for key, value in msg_metadata.items() if key in NodeRunMetadataKey + } json.append(message.message.json_object) elif message.type == ToolInvokeMessage.MessageType.LINK: assert isinstance(message.message, ToolInvokeMessage.TextMessage) @@ -299,6 +305,7 @@ class ToolNode(BaseNode[ToolNodeData]): status=message.message.status.value, data=message.message.data, label=message.message.label, + metadata=message.message.metadata, ) # check if the agent log is already in the list @@ -309,6 +316,7 @@ class ToolNode(BaseNode[ToolNodeData]): log.status = agent_log.status log.error = agent_log.error log.label = agent_log.label + log.metadata = agent_log.metadata break else: agent_logs.append(agent_log) @@ -319,7 +327,11 @@ class ToolNode(BaseNode[ToolNodeData]): run_result=NodeRunResult( status=WorkflowNodeExecutionStatus.SUCCEEDED, outputs={"text": text, "files": files, "json": json, **variables}, - metadata={NodeRunMetadataKey.TOOL_INFO: tool_info, NodeRunMetadataKey.AGENT_LOG: agent_logs}, + metadata={ + **agent_execution_metadata, + NodeRunMetadataKey.TOOL_INFO: tool_info, + NodeRunMetadataKey.AGENT_LOG: agent_logs, + }, inputs=parameters_for_log, ) )