@librechat/agents 3.7.9 → 3.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/graphs/Graph.cjs +11 -1
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +36 -3
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/langfuse.cjs +6 -2
- package/dist/cjs/langfuse.cjs.map +1 -1
- package/dist/cjs/run.cjs +5 -1
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +12 -2
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/search/metrics.cjs +234 -0
- package/dist/cjs/tools/search/metrics.cjs.map +1 -0
- package/dist/cjs/tools/search/rerankers.cjs +80 -68
- package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +95 -45
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +77 -49
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +11 -1
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +36 -3
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/langfuse.mjs +6 -2
- package/dist/esm/langfuse.mjs.map +1 -1
- package/dist/esm/run.mjs +5 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +12 -2
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/search/metrics.mjs +234 -0
- package/dist/esm/tools/search/metrics.mjs.map +1 -0
- package/dist/esm/tools/search/rerankers.mjs +80 -68
- package/dist/esm/tools/search/rerankers.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +96 -46
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +77 -49
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/types/langfuse.d.ts +5 -1
- package/dist/types/tools/ToolNode.d.ts +4 -1
- package/dist/types/tools/search/metrics.d.ts +15 -0
- package/dist/types/tools/search/rerankers.d.ts +30 -5
- package/dist/types/tools/search/tool.d.ts +7 -1
- package/dist/types/tools/search/types.d.ts +88 -4
- package/dist/types/tools/search/utils.d.ts +2 -10
- package/dist/types/types/tools.d.ts +5 -0
- package/package.json +1 -1
- package/src/graphs/Graph.ts +10 -0
- package/src/graphs/MultiAgentGraph.ts +71 -2
- package/src/langfuse.ts +12 -0
- package/src/run.ts +4 -0
- package/src/tools/ToolNode.ts +19 -0
- package/src/tools/search/metrics.ts +400 -0
- package/src/tools/search/rerankers.ts +160 -97
- package/src/tools/search/search.ts +139 -56
- package/src/tools/search/tool.ts +126 -62
- package/src/tools/search/types.ts +104 -4
- package/src/tools/search/utils.ts +2 -10
- package/src/types/tools.ts +5 -0
|
@@ -24,7 +24,7 @@ export declare function resolveSearchOutcome(data: t.SearchResultData, query: st
|
|
|
24
24
|
* Executes parallel searches and merges the results,
|
|
25
25
|
* deduplicating top stories by link
|
|
26
26
|
*/
|
|
27
|
-
export declare function executeParallelSearches({ searchAPI, query, date, country, safeSearch, images, videos, news, logger, }: {
|
|
27
|
+
export declare function executeParallelSearches({ searchAPI, query, date, country, safeSearch, images, videos, news, logger, provider, metrics, }: {
|
|
28
28
|
searchAPI: ReturnType<typeof createSearchAPI>;
|
|
29
29
|
query: string;
|
|
30
30
|
date?: DATE_RANGE;
|
|
@@ -34,5 +34,11 @@ export declare function executeParallelSearches({ searchAPI, query, date, countr
|
|
|
34
34
|
videos: boolean;
|
|
35
35
|
news: boolean;
|
|
36
36
|
logger: t.Logger;
|
|
37
|
+
/** Labels the provider in the run summary. Optional so the pre-existing
|
|
38
|
+
* call contract still holds for callers outside this package. */
|
|
39
|
+
provider?: string;
|
|
40
|
+
/** Collector owned by the caller. Without one, this call opens and flushes
|
|
41
|
+
* its own, so a direct caller still gets the single summary line. */
|
|
42
|
+
metrics?: t.SearchMetrics;
|
|
37
43
|
}): Promise<t.SearchResult>;
|
|
38
44
|
export declare const createSearchTool: (config?: t.SearchToolConfig) => DynamicStructuredTool;
|
|
@@ -291,7 +291,9 @@ export interface JinaRerankerResult {
|
|
|
291
291
|
}
|
|
292
292
|
export interface JinaRerankerResponse {
|
|
293
293
|
model: string;
|
|
294
|
-
|
|
294
|
+
/** Telemetry only, and absent from some Jina-compatible endpoints — never
|
|
295
|
+
* dereference it on a path that would discard a usable ranking. */
|
|
296
|
+
usage?: {
|
|
295
297
|
total_tokens: number;
|
|
296
298
|
};
|
|
297
299
|
results: JinaRerankerResult[];
|
|
@@ -303,12 +305,13 @@ export interface CohereRerankerResult {
|
|
|
303
305
|
export interface CohereRerankerResponse {
|
|
304
306
|
results: CohereRerankerResult[];
|
|
305
307
|
id: string;
|
|
306
|
-
|
|
307
|
-
|
|
308
|
+
/** Telemetry only; see {@link JinaRerankerResponse.usage}. */
|
|
309
|
+
meta?: {
|
|
310
|
+
api_version?: {
|
|
308
311
|
version: string;
|
|
309
312
|
is_experimental: boolean;
|
|
310
313
|
};
|
|
311
|
-
billed_units
|
|
314
|
+
billed_units?: {
|
|
312
315
|
search_units: number;
|
|
313
316
|
};
|
|
314
317
|
};
|
|
@@ -343,6 +346,81 @@ export interface RagApiRerankResponse {
|
|
|
343
346
|
}
|
|
344
347
|
export type SafeSearchLevel = 0 | 1 | 2;
|
|
345
348
|
export type Logger = WinstonLogger;
|
|
349
|
+
/** Compact, redacted view of a thrown error, safe to hand to a logger. */
|
|
350
|
+
export interface SafeErrorLog {
|
|
351
|
+
message: string;
|
|
352
|
+
name?: string;
|
|
353
|
+
code?: string;
|
|
354
|
+
status?: number;
|
|
355
|
+
method?: string;
|
|
356
|
+
url?: string;
|
|
357
|
+
responseDataSummary?: string;
|
|
358
|
+
value?: string;
|
|
359
|
+
}
|
|
360
|
+
/** Why a rerank returned the candidates' original order instead of a ranking. */
|
|
361
|
+
export type RerankFallback = 'no_api_key' | 'no_base_url' | 'no_token_supplier' | 'bad_response' | 'invalid_results' | 'chunk_error' | 'placeholder' | 'error';
|
|
362
|
+
/** One provider query. `results` is the row count that query contributed. */
|
|
363
|
+
export interface SearchObservation {
|
|
364
|
+
provider: string;
|
|
365
|
+
type: string;
|
|
366
|
+
results: number;
|
|
367
|
+
durationMs: number;
|
|
368
|
+
error?: string;
|
|
369
|
+
/** The query rejected rather than reporting failure in its response. Those
|
|
370
|
+
* were logged at error level before they were aggregated, so the summary
|
|
371
|
+
* has to carry the distinction to keep that severity. */
|
|
372
|
+
thrown?: boolean;
|
|
373
|
+
}
|
|
374
|
+
/** One scraped link. A failure carries `error`; a success carries the sizes
|
|
375
|
+
* the scrape produced, so the summary can report both without a second pass. */
|
|
376
|
+
export interface ScrapeObservation {
|
|
377
|
+
url: string;
|
|
378
|
+
chars?: number;
|
|
379
|
+
highlights?: number;
|
|
380
|
+
error?: string;
|
|
381
|
+
}
|
|
382
|
+
/** One reranker round trip. A search reranks once per scraped source, so
|
|
383
|
+
* these fold into a single summary rather than logging per source. */
|
|
384
|
+
export interface RerankObservation {
|
|
385
|
+
provider: string;
|
|
386
|
+
chunks: number;
|
|
387
|
+
results: number;
|
|
388
|
+
durationMs: number;
|
|
389
|
+
model?: string;
|
|
390
|
+
/** Provider-reported usage: Jina tokens, Cohere billed search units. */
|
|
391
|
+
units?: number;
|
|
392
|
+
/** Chunks a provider candidate cap dropped before submission. */
|
|
393
|
+
dropped?: number;
|
|
394
|
+
/** Set only when a provider cap reduced the requested result count, so a
|
|
395
|
+
* search returning fewer highlights than configured says why. */
|
|
396
|
+
topK?: number;
|
|
397
|
+
topKLimit?: number;
|
|
398
|
+
reason?: RerankFallback;
|
|
399
|
+
error?: SafeErrorLog;
|
|
400
|
+
}
|
|
401
|
+
/** Per-rerank state threaded from the start of a call to whichever exit it
|
|
402
|
+
* takes, so every path records exactly one observation. */
|
|
403
|
+
export interface RerankRun {
|
|
404
|
+
metrics: SearchMetrics;
|
|
405
|
+
documents: string[];
|
|
406
|
+
topK: number;
|
|
407
|
+
startedAt: number;
|
|
408
|
+
model?: string;
|
|
409
|
+
units?: number;
|
|
410
|
+
dropped?: number;
|
|
411
|
+
topKLimit?: number;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Fold-as-you-go counters for one `web_search` call. Recording is O(1) and
|
|
415
|
+
* allocation-free past a bounded reason map; {@link SearchMetrics.flush}
|
|
416
|
+
* emits at most one line per phase that actually ran.
|
|
417
|
+
*/
|
|
418
|
+
export interface SearchMetrics {
|
|
419
|
+
recordSearch(observation: SearchObservation): void;
|
|
420
|
+
recordScrape(observation: ScrapeObservation): void;
|
|
421
|
+
recordRerank(observation: RerankObservation): void;
|
|
422
|
+
flush(): void;
|
|
423
|
+
}
|
|
346
424
|
export interface SearchToolConfig extends SearchConfig, ProcessSourcesConfig, FirecrawlConfig {
|
|
347
425
|
tavilyScraperOptions?: TavilyScraperConfig;
|
|
348
426
|
crwScraperOptions?: CrwScraperConfig;
|
|
@@ -572,6 +650,9 @@ export interface FirecrawlScraperConfig extends BaseSearchProviderConfig {
|
|
|
572
650
|
onlyMainContent?: boolean;
|
|
573
651
|
changeTrackingOptions?: object;
|
|
574
652
|
}
|
|
653
|
+
/** Result kind a parallel sub-search covers; `web` is the untyped main
|
|
654
|
+
* search, which every provider serves without a `type` parameter. */
|
|
655
|
+
export type SubSearchType = 'web' | 'images' | 'videos' | 'news';
|
|
575
656
|
export type GetSourcesParams = {
|
|
576
657
|
query: string;
|
|
577
658
|
date?: DATE_RANGE;
|
|
@@ -870,6 +951,9 @@ export type ProcessSourcesFields = {
|
|
|
870
951
|
news: boolean;
|
|
871
952
|
proMode: boolean;
|
|
872
953
|
onGetHighlights: SearchToolConfig['onGetHighlights'];
|
|
954
|
+
/** Collector owned by the caller; when omitted, one is created and flushed
|
|
955
|
+
* for this call so a direct `processSources` still summarizes itself. */
|
|
956
|
+
metrics?: SearchMetrics;
|
|
873
957
|
};
|
|
874
958
|
export interface SearchToolSchema {
|
|
875
959
|
type: 'object';
|
|
@@ -1,14 +1,6 @@
|
|
|
1
|
+
import type { SafeErrorLog } from './types';
|
|
1
2
|
import type * as t from './types';
|
|
2
|
-
export
|
|
3
|
-
message: string;
|
|
4
|
-
name?: string;
|
|
5
|
-
code?: string;
|
|
6
|
-
status?: number;
|
|
7
|
-
method?: string;
|
|
8
|
-
url?: string;
|
|
9
|
-
responseDataSummary?: string;
|
|
10
|
-
value?: string;
|
|
11
|
-
}
|
|
3
|
+
export type { SafeErrorLog } from './types';
|
|
12
4
|
/**
|
|
13
5
|
* Creates a default logger that maps to console methods
|
|
14
6
|
* Uses a singleton pattern to avoid creating multiple instances
|
|
@@ -131,6 +131,11 @@ export type ToolNodeOptions = {
|
|
|
131
131
|
/** ID of the agent that owns this tool node, surfaced to hooks as `executingAgentId`
|
|
132
132
|
* so a batch can be attributed to a specific agent even where `agentId` is undefined. */
|
|
133
133
|
executingAgentId?: string;
|
|
134
|
+
/** Name of the agent that owns this tool node, used for active Langfuse attribution. */
|
|
135
|
+
executingAgentName?: string;
|
|
136
|
+
/** Root graph-agent identity retained alongside the currently executing tool owner. */
|
|
137
|
+
rootAgentId?: string;
|
|
138
|
+
rootAgentName?: string;
|
|
134
139
|
/** Tool names that must be executed directly (via runTool) even in event-driven mode (e.g., graph-managed handoff tools) */
|
|
135
140
|
directToolNames?: Set<string>;
|
|
136
141
|
/**
|
package/package.json
CHANGED
package/src/graphs/Graph.ts
CHANGED
|
@@ -2620,6 +2620,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
2620
2620
|
// run_id); `executingAgentId` always identifies the owning agent.
|
|
2621
2621
|
agentId: this.subagentScope ? agentContext?.agentId : undefined,
|
|
2622
2622
|
executingAgentId: agentContext?.agentId,
|
|
2623
|
+
executingAgentName: agentContext?.name,
|
|
2624
|
+
rootAgentId: this.defaultAgentId,
|
|
2625
|
+
rootAgentName: this.agentContexts.get(this.defaultAgentId)?.name,
|
|
2623
2626
|
toolCallStepIds: this.toolCallStepIds,
|
|
2624
2627
|
toolRegistry: agentContext?.toolRegistry,
|
|
2625
2628
|
getDiscoveredToolNames: (): readonly string[] =>
|
|
@@ -2697,6 +2700,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
2697
2700
|
// hooks can attribute the batch even at the top level.
|
|
2698
2701
|
agentId: this.subagentScope ? agentContext?.agentId : undefined,
|
|
2699
2702
|
executingAgentId: agentContext?.agentId,
|
|
2703
|
+
executingAgentName: agentContext?.name,
|
|
2704
|
+
rootAgentId: this.defaultAgentId,
|
|
2705
|
+
rootAgentName: this.agentContexts.get(this.defaultAgentId)?.name,
|
|
2700
2706
|
toolCallStepIds: this.toolCallStepIds,
|
|
2701
2707
|
errorHandler: (data, metadata): Promise<boolean> =>
|
|
2702
2708
|
StandardGraph.handleToolCallErrorStatic(this, data, metadata),
|
|
@@ -3815,6 +3821,10 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
3815
3821
|
parentMessageId: config.configurable?.requestBody?.parentMessageId,
|
|
3816
3822
|
agentId,
|
|
3817
3823
|
agentName: agentContext.name,
|
|
3824
|
+
rootAgentId: this.defaultAgentId,
|
|
3825
|
+
rootAgentName: this.agentContexts.get(this.defaultAgentId)?.name,
|
|
3826
|
+
activeAgentId: agentId,
|
|
3827
|
+
activeAgentName: agentContext.name,
|
|
3818
3828
|
});
|
|
3819
3829
|
let langfuseHandler: CallbackEntry | undefined;
|
|
3820
3830
|
let invokeConfig = {
|
|
@@ -101,6 +101,14 @@ function isTransferToolName(name: unknown): boolean {
|
|
|
101
101
|
);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
function graphToolName(tool: unknown): string | undefined {
|
|
105
|
+
if (tool == null || typeof tool !== 'object' || !('name' in tool)) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
const { name } = tool;
|
|
109
|
+
return typeof name === 'string' ? name : undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
104
112
|
/**
|
|
105
113
|
* Drop transfer `tool_use` content blocks from an AI message's array content.
|
|
106
114
|
* Companion to the reception's tool-call filtering: array-content providers
|
|
@@ -287,6 +295,21 @@ function withHandoffGroupMetadata(
|
|
|
287
295
|
};
|
|
288
296
|
}
|
|
289
297
|
|
|
298
|
+
function withActiveAgentMetadata(
|
|
299
|
+
config: LangGraphRunnableConfig | undefined,
|
|
300
|
+
agentId: string,
|
|
301
|
+
agentName: string | undefined
|
|
302
|
+
): LangGraphRunnableConfig {
|
|
303
|
+
return {
|
|
304
|
+
...config,
|
|
305
|
+
metadata: {
|
|
306
|
+
...config?.metadata,
|
|
307
|
+
activeAgentId: agentId,
|
|
308
|
+
...(agentName == null ? {} : { activeAgentName: agentName }),
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
290
313
|
/**
|
|
291
314
|
* MultiAgentGraph extends StandardGraph to support dynamic multi-agent workflows
|
|
292
315
|
* with handoffs, fan-in/fan-out, and other composable patterns.
|
|
@@ -594,6 +617,24 @@ export class MultiAgentGraph extends StandardGraph {
|
|
|
594
617
|
private createHandoffTools(): void {
|
|
595
618
|
// Group handoff edges by source agent(s)
|
|
596
619
|
const handoffsByAgent = new Map<string, t.GraphEdge[]>();
|
|
620
|
+
const tokenAccountingRefresh = new Set<string>();
|
|
621
|
+
|
|
622
|
+
/** Transfer tool names are SDK-reserved. Remove externally supplied or
|
|
623
|
+
* stale transfer tools before deriving the source agent's allowed set
|
|
624
|
+
* from the graph edges below. */
|
|
625
|
+
for (const agentContext of this.agentContexts.values()) {
|
|
626
|
+
const originalTools = agentContext.graphTools;
|
|
627
|
+
const retainedTools = agentContext.graphTools?.filter(
|
|
628
|
+
(graphTool) => !isTransferToolName(graphToolName(graphTool))
|
|
629
|
+
);
|
|
630
|
+
if (retainedTools?.length !== originalTools?.length) {
|
|
631
|
+
tokenAccountingRefresh.add(agentContext.agentId);
|
|
632
|
+
}
|
|
633
|
+
agentContext.graphTools =
|
|
634
|
+
retainedTools != null && retainedTools.length > 0
|
|
635
|
+
? retainedTools
|
|
636
|
+
: undefined;
|
|
637
|
+
}
|
|
597
638
|
|
|
598
639
|
// Only process handoff edges for tool creation
|
|
599
640
|
for (const edge of this.handoffEdges) {
|
|
@@ -643,6 +684,29 @@ export class MultiAgentGraph extends StandardGraph {
|
|
|
643
684
|
for (const handoffTool of handoffTools) {
|
|
644
685
|
agentContext.graphTools.push(handoffTool);
|
|
645
686
|
}
|
|
687
|
+
if (handoffTools.length > 0) {
|
|
688
|
+
tokenAccountingRefresh.add(agentId);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
for (const agentId of tokenAccountingRefresh) {
|
|
693
|
+
const agentContext = this.agentContexts.get(agentId);
|
|
694
|
+
if (agentContext?.tokenCounter == null) {
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
const { tokenCounter, baseIndexTokenCountMap } = agentContext;
|
|
698
|
+
agentContext.tokenCalculationPromise = agentContext
|
|
699
|
+
.calculateInstructionTokens(tokenCounter)
|
|
700
|
+
.then(() => {
|
|
701
|
+
agentContext.updateTokenMapWithInstructions(baseIndexTokenCountMap);
|
|
702
|
+
})
|
|
703
|
+
.catch((err) => {
|
|
704
|
+
// eslint-disable-next-line no-console
|
|
705
|
+
console.error(
|
|
706
|
+
'Error recalculating instruction tokens after handoff tool updates:',
|
|
707
|
+
err
|
|
708
|
+
);
|
|
709
|
+
});
|
|
646
710
|
}
|
|
647
711
|
}
|
|
648
712
|
|
|
@@ -1239,10 +1303,16 @@ export class MultiAgentGraph extends StandardGraph {
|
|
|
1239
1303
|
): Promise<t.MultiAgentGraphState | Command> => {
|
|
1240
1304
|
let result: t.MultiAgentGraphState;
|
|
1241
1305
|
let inputMessages = state.messages;
|
|
1242
|
-
const
|
|
1306
|
+
const agentContext = this.agentContexts.get(agentId);
|
|
1307
|
+
const recursionLimitedConfig =
|
|
1243
1308
|
this.memberRecursionLimit == null
|
|
1244
1309
|
? config
|
|
1245
1310
|
: { ...config, recursionLimit: this.memberRecursionLimit };
|
|
1311
|
+
const memberConfig = withActiveAgentMetadata(
|
|
1312
|
+
recursionLimitedConfig,
|
|
1313
|
+
agentId,
|
|
1314
|
+
agentContext?.name
|
|
1315
|
+
);
|
|
1246
1316
|
|
|
1247
1317
|
/**
|
|
1248
1318
|
* Check if this agent is receiving a handoff.
|
|
@@ -1254,7 +1324,6 @@ export class MultiAgentGraph extends StandardGraph {
|
|
|
1254
1324
|
state.messages,
|
|
1255
1325
|
agentId
|
|
1256
1326
|
);
|
|
1257
|
-
const agentContext = this.agentContexts.get(agentId);
|
|
1258
1327
|
|
|
1259
1328
|
if (
|
|
1260
1329
|
handoffContext?.sourceAgentName != null &&
|
package/src/langfuse.ts
CHANGED
|
@@ -783,17 +783,29 @@ export function createLangfuseTraceMetadata({
|
|
|
783
783
|
parentMessageId,
|
|
784
784
|
agentId,
|
|
785
785
|
agentName,
|
|
786
|
+
rootAgentId,
|
|
787
|
+
rootAgentName,
|
|
788
|
+
activeAgentId,
|
|
789
|
+
activeAgentName,
|
|
786
790
|
}: {
|
|
787
791
|
messageId?: unknown;
|
|
788
792
|
parentMessageId?: unknown;
|
|
789
793
|
agentId?: unknown;
|
|
790
794
|
agentName?: unknown;
|
|
795
|
+
rootAgentId?: unknown;
|
|
796
|
+
rootAgentName?: unknown;
|
|
797
|
+
activeAgentId?: unknown;
|
|
798
|
+
activeAgentName?: unknown;
|
|
791
799
|
}): LangfuseTraceMetadata {
|
|
792
800
|
return createTraceMetadata({
|
|
793
801
|
messageId,
|
|
794
802
|
parentMessageId,
|
|
795
803
|
agentId,
|
|
796
804
|
agentName,
|
|
805
|
+
rootAgentId,
|
|
806
|
+
rootAgentName,
|
|
807
|
+
activeAgentId,
|
|
808
|
+
activeAgentName,
|
|
797
809
|
});
|
|
798
810
|
}
|
|
799
811
|
|
package/src/run.ts
CHANGED
|
@@ -1311,6 +1311,10 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1311
1311
|
parentMessageId: config.configurable?.requestBody?.parentMessageId,
|
|
1312
1312
|
agentId: graph.defaultAgentId,
|
|
1313
1313
|
agentName: primaryContext?.name,
|
|
1314
|
+
rootAgentId: graph.defaultAgentId,
|
|
1315
|
+
rootAgentName: primaryContext?.name,
|
|
1316
|
+
activeAgentId: graph.defaultAgentId,
|
|
1317
|
+
activeAgentName: primaryContext?.name,
|
|
1314
1318
|
});
|
|
1315
1319
|
const traceName = config.runName ?? getLangfuseTraceName(traceMetadata);
|
|
1316
1320
|
const streamLangfuseConfig = this.getStreamLangfuseConfig(graph);
|
package/src/tools/ToolNode.ts
CHANGED
|
@@ -738,6 +738,9 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
738
738
|
* even where `agentId` (the subagent-scope marker) is undefined.
|
|
739
739
|
*/
|
|
740
740
|
private executingAgentId?: string;
|
|
741
|
+
private executingAgentName?: string;
|
|
742
|
+
private rootAgentId?: string;
|
|
743
|
+
private rootAgentName?: string;
|
|
741
744
|
/** Tool names that bypass event dispatch and execute directly (e.g., graph-managed handoff tools) */
|
|
742
745
|
private directToolNames?: Set<string>;
|
|
743
746
|
/**
|
|
@@ -823,6 +826,9 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
823
826
|
eagerEventToolSuppressions,
|
|
824
827
|
agentId,
|
|
825
828
|
executingAgentId,
|
|
829
|
+
executingAgentName,
|
|
830
|
+
rootAgentId,
|
|
831
|
+
rootAgentName,
|
|
826
832
|
directToolNames,
|
|
827
833
|
interruptingToolNames,
|
|
828
834
|
codeSessionToolNames,
|
|
@@ -902,6 +908,9 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
902
908
|
// Default to agentId so callers constructing ToolNode directly (who pass the
|
|
903
909
|
// existing agentId option) still get attribution without knowing the new option.
|
|
904
910
|
this.executingAgentId = executingAgentId ?? agentId;
|
|
911
|
+
this.executingAgentName = executingAgentName;
|
|
912
|
+
this.rootAgentId = rootAgentId;
|
|
913
|
+
this.rootAgentName = rootAgentName;
|
|
905
914
|
this.directToolNames = directToolNames;
|
|
906
915
|
this.interruptingToolNames =
|
|
907
916
|
interruptingToolNames != null && interruptingToolNames.size > 0
|
|
@@ -963,6 +972,16 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
963
972
|
metadata: {
|
|
964
973
|
...options?.metadata,
|
|
965
974
|
agentId: this.executingAgentId,
|
|
975
|
+
activeAgentId: this.executingAgentId,
|
|
976
|
+
...(this.executingAgentName == null
|
|
977
|
+
? {}
|
|
978
|
+
: { activeAgentName: this.executingAgentName }),
|
|
979
|
+
...(this.rootAgentId == null
|
|
980
|
+
? {}
|
|
981
|
+
: { rootAgentId: this.rootAgentId }),
|
|
982
|
+
...(this.rootAgentName == null
|
|
983
|
+
? {}
|
|
984
|
+
: { rootAgentName: this.rootAgentName }),
|
|
966
985
|
},
|
|
967
986
|
};
|
|
968
987
|
return withLangfuseRuntimeScope(
|