feat(ai-builder): Add n8n and workflow SDK versions to LangSmith trace metadata (no-changelog) (#30202)

This commit is contained in:
Albert Alises 2026-05-11 11:36:53 +02:00 committed by GitHub
parent 94d91e13bf
commit 40ffbfa5ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 62 additions and 1 deletions

View File

@ -62,6 +62,14 @@ export async function createDetachedSubAgentTracing(
typeof context.tracing.actorRun.metadata?.agent_id === 'string' typeof context.tracing.actorRun.metadata?.agent_id === 'string'
? context.tracing.actorRun.metadata.agent_id ? context.tracing.actorRun.metadata.agent_id
: context.orchestratorAgentId; : context.orchestratorAgentId;
const n8nVersion =
typeof context.tracing.actorRun.metadata?.n8n_version === 'string'
? context.tracing.actorRun.metadata.n8n_version
: undefined;
const workflowSdkVersion =
typeof context.tracing.actorRun.metadata?.workflow_sdk_version === 'string'
? context.tracing.actorRun.metadata.workflow_sdk_version
: undefined;
const tracing = await createDetachedSubAgentTraceContext({ const tracing = await createDetachedSubAgentTraceContext({
projectName: context.tracing.projectName, projectName: context.tracing.projectName,
threadId: context.threadId, threadId: context.threadId,
@ -73,6 +81,8 @@ export async function createDetachedSubAgentTracing(
modelId: context.modelId, modelId: context.modelId,
input: options.inputs, input: options.inputs,
metadata: options.metadata, metadata: options.metadata,
n8nVersion,
workflowSdkVersion,
agentId: options.agentId, agentId: options.agentId,
role: options.role, role: options.role,
kind: options.kind, kind: options.kind,

View File

@ -502,6 +502,44 @@ describe('createInstanceAiTraceContext', () => {
expect(JSON.stringify(inputs)).not.toContain('custom.endpoint'); expect(JSON.stringify(inputs)).not.toContain('custom.endpoint');
}); });
it('includes n8n and workflow SDK versions in trace metadata when provided', async () => {
const tracing = await createInstanceAiTraceContext({
threadId: 'thread-1',
messageId: 'message-1',
runId: 'run-1',
userId: 'user-1',
n8nVersion: '1.123.4',
workflowSdkVersion: '0.13.0',
input: { message: 'What workflows do I have?' },
});
expect(tracing?.messageRun.metadata).toEqual(
expect.objectContaining({
n8n_version: '1.123.4',
workflow_sdk_version: '0.13.0',
}),
);
expect(tracing?.orchestratorRun.metadata).toEqual(
expect.objectContaining({
n8n_version: '1.123.4',
workflow_sdk_version: '0.13.0',
}),
);
});
it('omits version metadata when not provided', async () => {
const tracing = await createInstanceAiTraceContext({
threadId: 'thread-1',
messageId: 'message-1',
runId: 'run-1',
userId: 'user-1',
input: { message: 'What workflows do I have?' },
});
expect(tracing?.messageRun.metadata).not.toHaveProperty('n8n_version');
expect(tracing?.messageRun.metadata).not.toHaveProperty('workflow_sdk_version');
});
it('redacts model secrets from trace metadata', async () => { it('redacts model secrets from trace metadata', async () => {
const tracing = await createInstanceAiTraceContext({ const tracing = await createInstanceAiTraceContext({
threadId: 'thread-1', threadId: 'thread-1',

View File

@ -104,6 +104,8 @@ interface CreateInstanceAiTraceContextOptions {
modelId?: unknown; modelId?: unknown;
input: unknown; input: unknown;
metadata?: Record<string, unknown>; metadata?: Record<string, unknown>;
n8nVersion?: string;
workflowSdkVersion?: string;
/** When set, traces are routed through the AI service proxy instead of directly to LangSmith. */ /** When set, traces are routed through the AI service proxy instead of directly to LangSmith. */
proxyConfig?: ServiceProxyConfig; proxyConfig?: ServiceProxyConfig;
} }
@ -1312,6 +1314,10 @@ function buildBaseMetadata(options: CreateInstanceAiTraceContextOptions): Record
...(options.modelId !== undefined ...(options.modelId !== undefined
? { model_id: serializeModelIdForTrace(options.modelId) } ? { model_id: serializeModelIdForTrace(options.modelId) }
: {}), : {}),
...(options.n8nVersion !== undefined ? { n8n_version: options.n8nVersion } : {}),
...(options.workflowSdkVersion !== undefined
? { workflow_sdk_version: options.workflowSdkVersion }
: {}),
...options.metadata, ...options.metadata,
}; };
} }

View File

@ -24,12 +24,17 @@ export const EDITOR_UI_DIST_DIR = join(dirname(require.resolve('n8n-editor-ui'))
const packageJsonPath = join(CLI_DIR, 'package.json'); const packageJsonPath = join(CLI_DIR, 'package.json');
const aiAssistantPackageJsonPath = join(AI_ASSISTANT_SDK_DIR, 'package.json'); const aiAssistantPackageJsonPath = join(AI_ASSISTANT_SDK_DIR, 'package.json');
const workflowSdkPackageJsonPath = require.resolve('@n8n/workflow-sdk/package.json');
const n8nPackageJson = jsonParse<n8n.PackageJson>(readFileSync(packageJsonPath, 'utf8')); const n8nPackageJson = jsonParse<n8n.PackageJson>(readFileSync(packageJsonPath, 'utf8'));
const aiAssistantPackageJson = jsonParse<n8n.PackageJson>( const aiAssistantPackageJson = jsonParse<n8n.PackageJson>(
readFileSync(aiAssistantPackageJsonPath, 'utf8'), readFileSync(aiAssistantPackageJsonPath, 'utf8'),
); );
const workflowSdkPackageJson = jsonParse<n8n.PackageJson>(
readFileSync(workflowSdkPackageJsonPath, 'utf8'),
);
export const N8N_VERSION = n8nPackageJson.version; export const N8N_VERSION = n8nPackageJson.version;
export const AI_ASSISTANT_SDK_VERSION = aiAssistantPackageJson.version; export const AI_ASSISTANT_SDK_VERSION = aiAssistantPackageJson.version;
export const WORKFLOW_SDK_VERSION = workflowSdkPackageJson.version;
export const N8N_RELEASE_DATE = statSync(packageJsonPath).mtime; export const N8N_RELEASE_DATE = statSync(packageJsonPath).mtime;
export const STARTING_NODES = [ export const STARTING_NODES = [

View File

@ -90,7 +90,7 @@ import { OperationalError, UnexpectedError, UserError } from 'n8n-workflow';
import type * as Undici from 'undici'; import type * as Undici from 'undici';
import { v5 as uuidv5 } from 'uuid'; import { v5 as uuidv5 } from 'uuid';
import { N8N_VERSION } from '@/constants'; import { N8N_VERSION, WORKFLOW_SDK_VERSION } from '@/constants';
import { EventService } from '@/events/event.service'; import { EventService } from '@/events/event.service';
import { SourceControlPreferencesService } from '@/modules/source-control.ee/source-control-preferences.service.ee'; import { SourceControlPreferencesService } from '@/modules/source-control.ee/source-control-preferences.service.ee';
import { AiService } from '@/services/ai.service'; import { AiService } from '@/services/ai.service';
@ -2785,6 +2785,8 @@ export class InstanceAiService {
userId: user.id, userId: user.id,
modelId, modelId,
input: traceInput, input: traceInput,
n8nVersion: N8N_VERSION,
workflowSdkVersion: WORKFLOW_SDK_VERSION,
proxyConfig: orchestrationContext.tracingProxyConfig, proxyConfig: orchestrationContext.tracingProxyConfig,
}); });