Skip to content

Commit be5c3bc

Browse files
committed
refactor LangGraph LlmAgent event, remove old base
1 parent 7ff953d commit be5c3bc

File tree

7 files changed

+30
-175
lines changed

7 files changed

+30
-175
lines changed

lib/llm-events/error-message.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ module.exports = class LlmErrorMessage {
4343
this.agent_id = aiAgent?.id
4444

4545
if (embedding?.vendor === 'gemini' || summary?.vendor === 'gemini') {
46-
this._handleGemini(cause)
46+
this.#handleGemini(cause)
4747
}
4848
}
4949

@@ -57,7 +57,7 @@ module.exports = class LlmErrorMessage {
5757
* the relevant fields from cause.message to get `status` and `error`.
5858
* @param {object} cause error object
5959
*/
60-
_handleGemini(cause) {
60+
#handleGemini(cause) {
6161
if (cause?.message) {
6262
try {
6363
const jsonStartIndex = cause.message.indexOf('{')

lib/llm-events/event.js

Lines changed: 0 additions & 130 deletions
This file was deleted.

lib/llm-events/langgraph/agent.js

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,23 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
const BaseLlmEvent = require('../event')
7-
const { makeId } = require('../../util/hashes')
6+
const LlmEvent = require('../event-base')
87

98
/**
10-
* @typedef {object} LangGraphAgentEventParams
11-
* @property {Agent} agent The New Relic agent instance.
12-
* @property {string} name The name of the LangGraph agent, defaults to 'agent'.
13-
* @property {object} segment The associated NR segment.
14-
* @property {object} transaction The associated NR transaction.
15-
* @property {boolean} error A boolean flag to indicate if an error occurred.
9+
* Encapsulates a `@langchain/langgraph` LlmAgent event.
1610
*/
17-
18-
module.exports = class LangGraphAgentEvent extends BaseLlmEvent {
19-
id = makeId(36)
20-
span_id
21-
trace_id
22-
ingest_source = 'Node'
23-
vendor = 'langgraph'
24-
11+
module.exports = class LangGraphLlmAgent extends LlmEvent {
2512
/**
26-
* @param {LangGraphAgentEventParams} params should contain all necessary and optional LangGraph data
13+
*
14+
* @param {object} params constructor parameters
15+
* @param {Agent} params.agent New Relic agent instance
16+
* @param {object} params.segment Current segment
17+
* @param {object} params.transaction Current and active transaction
18+
* @param {string} params.aiAgentName Name of the AI agent which can typically be captured through framework context
19+
* @param {boolean} [params.error] Set to `true` if an error occurred during creation call, omitted if no error occurred
2720
*/
28-
constructor(params) {
29-
super(params)
30-
const { agent, segment, transaction, error = false, name = 'agent' } = params
31-
32-
this.name = name
33-
this.span_id = segment.id
34-
this.trace_id = transaction.traceId
35-
this.error = error
36-
37-
// Setting `metadata` as the NR agent instance will allow `BaseLlmEvent`
38-
// to extract the relevant `llm.<user_defined_metadata>`.
39-
this.metadata = agent
21+
constructor({ agent, segment, transaction, aiAgentName, error }) {
22+
super({ agent, segment, transaction, vendor: 'langgraph', error })
23+
this.name = aiAgentName ?? 'agent'
4024
}
4125
}

lib/subscribers/langgraph/graph-stream.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
const AiMonitoringSubscriber = require('../ai-monitoring/base')
77
const LlmErrorMessage = require('#agentlib/llm-events/error-message.js')
8-
const LangGraphAgentEvent = require('#agentlib/llm-events/langgraph/agent.js')
8+
const LlmAgent = require('#agentlib/llm-events/langgraph/agent.js')
99
const { AI: { LANGGRAPH, STREAMING_DISABLED } } = require('#agentlib/metrics/names.js')
1010

1111
class LangGraphStreamSubscriber extends AiMonitoringSubscriber {
@@ -104,9 +104,9 @@ class LangGraphStreamSubscriber extends AiMonitoringSubscriber {
104104
recordAiAgentEvent({ aiAgentName, transaction, segment, error }) {
105105
const { agent } = this
106106
segment.end()
107-
const agentEvent = new LangGraphAgentEvent({
107+
const agentEvent = new LlmAgent({
108108
agent,
109-
name: aiAgentName,
109+
aiAgentName,
110110
transaction,
111111
segment,
112112
error: !!error

test/unit/llm-events/langgraph/agent.test.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
const test = require('node:test')
99
const assert = require('node:assert')
10-
const LangGraphAgentEvent = require('../../../../lib/llm-events/langgraph/agent')
10+
const LlmAgent = require('#agentlib/llm-events/langgraph/agent.js')
1111

1212
test.beforeEach((ctx) => {
1313
ctx.nr = {}
@@ -43,29 +43,28 @@ test.beforeEach((ctx) => {
4343
id: 'segment-1'
4444
}
4545

46-
ctx.nr.name = 'test-agent'
46+
ctx.nr.aiAgentName = 'test-agent'
4747
})
4848

4949
test('constructs default instance', async (t) => {
50-
const event = new LangGraphAgentEvent(t.nr)
50+
const event = new LlmAgent(t.nr)
5151
assert.equal(event.name, 'test-agent')
52-
assert.match(event.id, /[a-z0-9-]{36}/)
52+
assert.match(event.id, /[a-z0-9-]{32}/)
5353
assert.equal(event.span_id, 'segment-1')
5454
assert.equal(event.trace_id, 'trace-1')
5555
assert.equal(event['llm.foo'], 'bar')
5656
assert.equal(event.ingest_source, 'Node')
5757
assert.equal(event.vendor, 'langgraph')
58-
assert.equal(event.error, false)
5958
})
6059

6160
test('constructs instance with error', async (t) => {
6261
t.nr.error = true
63-
const event = new LangGraphAgentEvent(t.nr)
62+
const event = new LlmAgent(t.nr)
6463
assert.equal(event.error, true)
6564
})
6665

6766
test('uses default name when not provided', async (t) => {
68-
delete t.nr.name
69-
const event = new LangGraphAgentEvent(t.nr)
67+
delete t.nr.aiAgentName
68+
const event = new LlmAgent(t.nr)
7069
assert.equal(event.name, 'agent')
7170
})

test/versioned/langgraph/graph-invoke.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ test('should create LlmAgent event for CompiledStateGraph.invoke', async (t) =>
115115
const [segment] = tx.trace.getChildren(tx.trace.root.id)
116116

117117
match(agentEvent, {
118-
id: /[a-f0-9]{36}/,
118+
id: /[a-f0-9]{32}/,
119119
name: 'LangGraphReactAgent',
120120
span_id: segment.id,
121121
trace_id: tx.traceId,

test/versioned/langgraph/graph-stream.test.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ test('should create LlmAgent event for CompiledStateGraph.stream', async (t) =>
162162
const [segment] = tx.trace.getChildren(tx.trace.root.id)
163163

164164
match(agentEvent, {
165-
id: /[a-f0-9]{36}/,
165+
id: /[a-f0-9]{32}/,
166166
name: 'LangGraphReactAgent',
167167
span_id: segment.id,
168168
trace_id: tx.traceId,
@@ -239,7 +239,7 @@ test('should have LlmChatCompletion events from LangChain and OpenAI instrumenta
239239
})
240240
})
241241

242-
test('should have LlmTool events from LangChain instrumentation', async (t) => {
242+
test('should have LlmTool event from LangChain instrumentation', async (t) => {
243243
const { agent, langgraphAgentWithTools } = t.nr
244244

245245
await helper.runInTransaction(agent, async (tx) => {
@@ -260,6 +260,8 @@ test('should have LlmTool events from LangChain instrumentation', async (t) => {
260260
assert.equal(toolEvent.name, 'calculator', 'tool name should be calculator')
261261
assert.equal(toolEvent.vendor, 'langchain', 'vendor should be langchain')
262262
assert.equal(toolEvent.output, '4', 'tool output should be 4')
263+
assert.equal(toolEvent.run_id, 'call_calc123')
264+
assert.equal(toolEvent.agent_name, 'LangGraphReactAgent')
263265

264266
// Should have 2 LlmChatCompletionMessages with role='tool'
265267
const chatEvents = events.filter((e) => e[0].type === 'LlmChatCompletionMessage' && e[1].role === 'tool')

0 commit comments

Comments
 (0)