mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-30 16:26:59 +02:00
fix(instance-ai): compact trace tool metadata
This commit is contained in:
parent
ca986ba28d
commit
f2feb27180
|
|
@ -738,6 +738,7 @@ describe('createInstanceAiTraceContext', () => {
|
|||
expect(redacted.attributes['llm.tool_manifest_ref']).toBe(
|
||||
redacted.attributes['llm.tool_schema_hash'],
|
||||
);
|
||||
expect(redacted.attributes['llm.available_tools']).toBeUndefined();
|
||||
expect(jsonParse(redacted.attributes['tools'] as string)).toEqual(prompt.tools);
|
||||
expect(jsonParse(redacted.attributes['invocation_params.tools'] as string)).toEqual(
|
||||
prompt.tools,
|
||||
|
|
@ -1084,7 +1085,7 @@ describe('createInstanceAiTraceContext', () => {
|
|||
expect(telemetry.runtimeRootSpanEnabled).toBe(false);
|
||||
});
|
||||
|
||||
it('attaches root agent config without duplicating it into llm steps', async () => {
|
||||
it('attaches compact root agent config without duplicating tool schemas into agent spans', async () => {
|
||||
const tracing = await createDetachedSubAgentTraceContext({
|
||||
threadId: 'thread-1',
|
||||
conversationId: 'thread-1',
|
||||
|
|
@ -1131,21 +1132,22 @@ describe('createInstanceAiTraceContext', () => {
|
|||
);
|
||||
|
||||
const actorInputs = tracing?.actorRun.inputs as Record<string, unknown>;
|
||||
const loadedTools = actorInputs.loaded_tools as Array<Record<string, unknown>>;
|
||||
const loadedToolManifest = jsonParse<Array<Record<string, unknown>>>(
|
||||
actorInputs.loaded_tool_manifest as string,
|
||||
);
|
||||
const systemPrompt = actorInputs.system_prompt as Record<string, unknown>;
|
||||
|
||||
expect(actorInputs.task).toBe('Build a workflow');
|
||||
expect(actorInputs.model).toBe('anthropic/claude-sonnet-4-6');
|
||||
expect(actorInputs.loaded_tool_count).toBe(2);
|
||||
expect(actorInputs.loaded_tool_names).toEqual(['build-workflow', 'submit-workflow']);
|
||||
expect(actorInputs.assigned_tool_count).toBe(2);
|
||||
expect(actorInputs.assigned_tool_names).toEqual(['build-workflow', 'submit-workflow']);
|
||||
expect(actorInputs.assigned_tool_schema_hash).toEqual(expect.any(String));
|
||||
expect(actorInputs.runtime_tool_count).toBe(1);
|
||||
expect(actorInputs.runtime_tool_names).toEqual(['workspace_read_file']);
|
||||
expect(actorInputs.loaded_tool_schema_hash).toEqual(expect.any(String));
|
||||
expect(actorInputs.runtime_tool_schema_hash).toEqual(expect.any(String));
|
||||
expect(actorInputs.loaded_tool_count).toBeUndefined();
|
||||
expect(actorInputs.loaded_tool_names).toBeUndefined();
|
||||
expect(actorInputs.loaded_tool_schema_hash).toBeUndefined();
|
||||
expect(actorInputs.loaded_tool_manifest).toBeUndefined();
|
||||
expect(actorInputs.loaded_tools).toBeUndefined();
|
||||
expect(actorInputs.loaded_tool_catalog).toBeUndefined();
|
||||
const actorSpan = agentsMock
|
||||
.getSpans()
|
||||
.find((span) => span.id === tracing?.actorRun.otelSpanId);
|
||||
|
|
@ -1154,41 +1156,8 @@ describe('createInstanceAiTraceContext', () => {
|
|||
);
|
||||
expect(spanInputs.assigned_tool_names).toEqual(['build-workflow', 'submit-workflow']);
|
||||
expect(spanInputs.runtime_tool_names).toEqual(['workspace_read_file']);
|
||||
expect(loadedTools).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
name: 'build-workflow',
|
||||
kind: 'local',
|
||||
source: 'domain',
|
||||
category: 'workflow',
|
||||
side_effect: 'write',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
name: 'submit-workflow',
|
||||
kind: 'local',
|
||||
source: 'workspace',
|
||||
category: 'workflow',
|
||||
side_effect: 'write',
|
||||
}),
|
||||
]),
|
||||
);
|
||||
const buildWorkflowManifest = loadedToolManifest.find((tool) => tool.name === 'build-workflow');
|
||||
expect(buildWorkflowManifest).toEqual(
|
||||
expect.objectContaining({
|
||||
name: 'build-workflow',
|
||||
source: 'domain',
|
||||
category: 'workflow',
|
||||
side_effect: 'write',
|
||||
approval: {
|
||||
default_approval: false,
|
||||
suspend: false,
|
||||
resume: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
expect(buildWorkflowManifest?.input_schema).toEqual(
|
||||
expect.objectContaining({ type: 'object' }),
|
||||
);
|
||||
expect(spanInputs.loaded_tool_manifest).toBeUndefined();
|
||||
expect(spanInputs.loaded_tools).toBeUndefined();
|
||||
expect(systemPrompt.part_01).toEqual(expect.any(String));
|
||||
expect(systemPrompt.part_02).toEqual(expect.any(String));
|
||||
});
|
||||
|
|
@ -1229,7 +1198,8 @@ describe('createInstanceAiTraceContext', () => {
|
|||
const actorInputs = tracing?.actorRun.inputs as Record<string, unknown>;
|
||||
expect(actorInputs.model).toBe('anthropic/claude-sonnet-4-6');
|
||||
expect(actorInputs.system_prompt).toBe('system prompt');
|
||||
expect(actorInputs.loaded_tool_count).toBe(1);
|
||||
expect(actorInputs.assigned_tool_count).toBe(1);
|
||||
expect(actorInputs.assigned_tool_names).toEqual(['build-workflow']);
|
||||
});
|
||||
|
||||
it('redacts model secrets from agent trace inputs', () => {
|
||||
|
|
|
|||
|
|
@ -972,7 +972,6 @@ function enrichLangSmithToolAttributes(attributes: Record<string, unknown>): unk
|
|||
|
||||
attributes['llm.available_tool_count'] = normalizedTools.length;
|
||||
attributes['llm.available_tool_names'] = toolNames;
|
||||
attributes['llm.available_tools'] = serializedTools;
|
||||
attributes['llm.tool_manifest_ref'] = schemaHash;
|
||||
attributes['llm.tool_schema_hash'] = schemaHash;
|
||||
attributes.tools = serializedTools;
|
||||
|
|
@ -1420,41 +1419,21 @@ function summarizeToolSet(
|
|||
const summaries = Object.entries(tools).map(([name, tool]) =>
|
||||
summarizeToolForManifest(name, tool),
|
||||
);
|
||||
const catalogText = summaries
|
||||
.map((tool) => {
|
||||
const name = typeof tool.name === 'string' ? tool.name : 'unknown';
|
||||
return typeof tool.description === 'string' ? `${name}: ${tool.description}` : name;
|
||||
})
|
||||
.join('\n');
|
||||
const manifestHash = stableHash(summaries);
|
||||
const toolNames = summaries
|
||||
.map((tool) => (typeof tool.name === 'string' ? tool.name : undefined))
|
||||
.filter((name): name is string => name !== undefined);
|
||||
const aliases: Record<string, unknown> = {};
|
||||
if (fieldPrefix === 'loaded') {
|
||||
aliases.assigned_tool_count = summaries.length;
|
||||
aliases.assigned_tool_names = toolNames;
|
||||
return {
|
||||
assigned_tool_count: summaries.length,
|
||||
assigned_tool_names: toolNames,
|
||||
assigned_tool_schema_hash: manifestHash,
|
||||
};
|
||||
}
|
||||
if (fieldPrefix === 'runtime') {
|
||||
aliases.runtime_tool_count = summaries.length;
|
||||
aliases.runtime_tool_names = toolNames;
|
||||
}
|
||||
|
||||
return {
|
||||
...aliases,
|
||||
[`${fieldPrefix}_tool_count`]: summaries.length,
|
||||
[`${fieldPrefix}_tool_names`]: toolNames,
|
||||
[`${fieldPrefix}_tool_manifest`]: serializeTraceText(JSON.stringify(summaries)),
|
||||
[`${fieldPrefix}_tool_schema_hash`]: manifestHash,
|
||||
[`${fieldPrefix}_tools`]: summaries.map((tool) => ({
|
||||
name: tool.name,
|
||||
description: tool.description,
|
||||
kind: tool.kind,
|
||||
source: tool.source,
|
||||
category: tool.category,
|
||||
side_effect: tool.side_effect,
|
||||
})),
|
||||
[`${fieldPrefix}_tool_catalog`]: serializeTraceText(catalogText),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user