Skip to content

fix(nodes-langchain): emit ai-tool-called log streaming event for ToolWorkflow, ToolCode, and ToolHttpRequest#28599

Open
octo-patch wants to merge 1 commit inton8n-io:masterfrom
octo-patch:fix/issue-28532-ai-tool-log-events
Open

fix(nodes-langchain): emit ai-tool-called log streaming event for ToolWorkflow, ToolCode, and ToolHttpRequest#28599
octo-patch wants to merge 1 commit inton8n-io:masterfrom
octo-patch:fix/issue-28532-ai-tool-log-events

Conversation

@octo-patch
Copy link
Copy Markdown

Fixes #28532

Problem

When an AI agent uses the Call n8n Sub-Workflow Tool (toolWorkflow), HTTP Request Tool (toolHttpRequest), or Code Tool (toolCode) as tools, the n8n.ai.tool.called log streaming event is never emitted. External observability systems subscribed to this event receive no signal that these tools were invoked.

Root cause: These three tool types use a manual logging execution pattern where they call addInputData/addOutputData directly. This bypasses the logWrapper proxy from @n8n/ai-utilities, which normally intercepts the LangChain _call method and emits ai-tool-called via logAiEvent. Because these tools never go through logWrapper, logAiEvent is never called.

Solution

Call logAiEvent(ctx, 'ai-tool-called', { query, response }) in the success branch of each tool's handler, consistent with the pattern used by logWrapper for LangChain-native tools:

  • WorkflowToolService.ts (ToolWorkflow v2): added after addOutputData in the manualLogging success branch
  • ToolCode.node.ts: added after addOutputData in the else if (log) success branch
  • ToolHttpRequest/utils.ts (configureToolFunction): added after addOutputData in the else success branch

Testing

Added unit tests in ToolWorkflowV2.test.ts verifying:

  • logAiEvent is called with 'ai-tool-called' and the correct query/response data when manualLogging=true
  • logAiEvent is NOT called when manualLogging=false (engine-called path)

… ToolCode, and ToolHttpRequest

These three tools use a manual logging pattern (manualLogging=true) that
calls addInputData/addOutputData directly, bypassing the logWrapper proxy
which normally emits the ai-tool-called event for LangChain-native tools.

As a result, log streaming subscribers never received n8n.ai.tool.called
events when these tools executed, creating an observability blind spot for
the most commonly used AI agent tools.

Fix: call logAiEvent('ai-tool-called', ...) in the success branch of each
tool handler function, consistent with the pattern used by logWrapper.

Fixes n8n-io#28532
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


octo-patch seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/@n8n/nodes-langchain/nodes/tools/ToolWorkflow/v2/ToolWorkflowV2.test.ts">

<violation number="1" location="packages/@n8n/nodes-langchain/nodes/tools/ToolWorkflow/v2/ToolWorkflowV2.test.ts:1017">
P3: The positive-path telemetry test should also assert the logged `response` payload; currently it only checks the query, so it would miss regressions where `ai-tool-called` is emitted with the wrong or missing response data.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant Agent as AI Agent (LangChain)
    participant Tool as Tool (Workflow / Code / HTTP)
    participant Ctx as Node Execution Context
    participant AIUtils as @n8n/ai-utilities
    participant Stream as Log Streaming / Observability

    Note over Agent,Stream: AI Tool Execution Flow (Manual Logging Path)

    Agent->>Tool: call(query)
    
    Tool->>Tool: Execute internal logic (JS Code, Sub-workflow, or HTTP Request)
    
    alt Success Branch
        Tool->>Ctx: addOutputData(NodeConnectionTypes.AiTool, index, response)
        
        Note over Tool,AIUtils: NEW: Manual emission for tools bypassing logWrapper
        Tool->>AIUtils: NEW: logAiEvent(ctx, 'ai-tool-called', { query, response })
        
        AIUtils-->>Stream: Push log entry to external listeners
        
        Tool-->>Agent: return response
    else Error Branch
        Tool->>Ctx: addOutputData(NodeConnectionTypes.AiTool, index, executionError)
        Note right of Tool: Log event is NOT emitted on failure in this flow
        Tool-->>Agent: return response
    end

    Note over Tool,Ctx: NOTE: If manualLogging is false (Engine-called),<br/>standard logWrapper proxy handles the event emission instead.
Loading

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

expect(mockLogAiEvent).toHaveBeenCalledWith(
expect.anything(),
'ai-tool-called',
expect.objectContaining({ query: 'test query' }),
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 17, 2026

Choose a reason for hiding this comment

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

P3: The positive-path telemetry test should also assert the logged response payload; currently it only checks the query, so it would miss regressions where ai-tool-called is emitted with the wrong or missing response data.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/@n8n/nodes-langchain/nodes/tools/ToolWorkflow/v2/ToolWorkflowV2.test.ts, line 1017:

<comment>The positive-path telemetry test should also assert the logged `response` payload; currently it only checks the query, so it would miss regressions where `ai-tool-called` is emitted with the wrong or missing response data.</comment>

<file context>
@@ -971,4 +978,71 @@ describe('WorkflowTool::WorkflowToolService', () => {
+			expect(mockLogAiEvent).toHaveBeenCalledWith(
+				expect.anything(),
+				'ai-tool-called',
+				expect.objectContaining({ query: 'test query' }),
+			);
+		});
</file context>
Suggested change
expect.objectContaining({ query: 'test query' }),
expect.objectContaining({
query: 'test query',
response: JSON.stringify(TEST_RESPONSE, null, 2),
}),
Fix with Cubic

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AI tool call events not emitted for ToolWorkflow, ToolHttpRequest, and ToolCode — log streaming blind spot

2 participants