diff --git a/packages/@n8n/instance-ai/src/index.ts b/packages/@n8n/instance-ai/src/index.ts index 2ca217d35af..044de67ca88 100644 --- a/packages/@n8n/instance-ai/src/index.ts +++ b/packages/@n8n/instance-ai/src/index.ts @@ -17,6 +17,7 @@ export type { DomainAccessTracker } from './domain-access'; export { createInstanceAiTraceContext, continueInstanceAiTraceContext, + releaseTraceClient, withCurrentTraceSpan, } from './tracing/langsmith-tracing'; export { createInstanceAgent } from './agent/instance-agent'; diff --git a/packages/@n8n/instance-ai/src/tracing/langsmith-tracing.ts b/packages/@n8n/instance-ai/src/tracing/langsmith-tracing.ts index 87c6c86f1c2..eec8befccc9 100644 --- a/packages/@n8n/instance-ai/src/tracing/langsmith-tracing.ts +++ b/packages/@n8n/instance-ai/src/tracing/langsmith-tracing.ts @@ -423,6 +423,15 @@ function mergeRunTreeInputs( }; } +/** + * Unconditionally remove the cached LangSmith Client for a trace. + * Call after run finalization (success or failure) so the Client and + * its RunTree hierarchy can be garbage-collected. + */ +export function releaseTraceClient(traceId: string): void { + traceClients.delete(traceId); +} + export function getTraceParentRun(): RunTree | undefined { const overrideRun = traceParentOverrideStorage.getStore()?.current; if (overrideRun) { diff --git a/packages/cli/src/modules/instance-ai/instance-ai.service.ts b/packages/cli/src/modules/instance-ai/instance-ai.service.ts index 55ce4f03d83..f58e7d0a5f1 100644 --- a/packages/cli/src/modules/instance-ai/instance-ai.service.ts +++ b/packages/cli/src/modules/instance-ai/instance-ai.service.ts @@ -34,6 +34,7 @@ import { PlannedTaskCoordinator, PlannedTaskStorage, applyPlannedTaskPermissions, + releaseTraceClient, resumeAgentRun, RunStateRegistry, startBuildWorkflowAgentTask, @@ -544,6 +545,8 @@ export class InstanceAiService { threadId: tracing.rootRun.metadata?.thread_id, error: getErrorMessage(error), }); + } finally { + releaseTraceClient(tracing.rootRun.traceId); } } @@ -574,6 +577,7 @@ export class InstanceAiService { private deleteTraceContextsForThread(threadId: string): void { for (const [runId, entry] of this.traceContextsByRunId) { if (entry.threadId === threadId) { + releaseTraceClient(entry.tracing.rootRun.traceId); this.traceContextsByRunId.delete(runId); } } @@ -609,6 +613,8 @@ export class InstanceAiService { traceRunId: traceContext.rootRun.id, error: getErrorMessage(error), }); + } finally { + releaseTraceClient(traceContext.rootRun.traceId); } }