Skip to content

Commit 01883f2

Browse files
authored
[feat] [sdk] @cozeloop/langchain@0.0.3 LangGraph span type and peer with langchain v1 (#22)
* feat(cozeloop-langchain): add graph span type for LangGraph Node * feat(cozeloop-langchain): peer with langchain v1 * feat(cozeloop-langchain): bump to 0.0.3
1 parent 1c48d1f commit 01883f2

8 files changed

Lines changed: 84 additions & 54 deletions

File tree

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
# 🕗 Change Log - @cozeloop/langchain
22

3+
## 0.0.3
4+
5+
* [feat]: LangGraph Node type
6+
* [feat]: peer with langchain v1
7+
38
## 0.0.2
4-
fix: DEFAULT_SCHEDULE_DELAY to 1_000 ms
9+
10+
* [fix]: DEFAULT_SCHEDULE_DELAY to 1_000 ms
511

612
## 0.0.1
13+
714
🌱 Initial version

packages/cozeloop-langchain/README.md

Lines changed: 49 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,119 +3,120 @@
33
[![npm version](https://img.shields.io/npm/v/%40cozeloop%2Flangchain)](https://www.npmjs.com/package/@cozeloop/langchain)
44
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
55

6-
Integrate Langchain with Cozeloop via `@cozeloop/langchain`, supports:
7-
* `CozeloopCallbackHandler`: report trace to Cozeloop
6+
Official LangChain integration for [CozeLoop](https://loop.coze.cn) - seamlessly report traces from your LangChain and LangGraph applications.
87

9-
## Quick Start
8+
## Features
109

11-
### 1. Installation
10+
- **CozeloopCallbackHandler**: Automatically capture and report traces to CozeLoop
11+
- Support for both LangChain and LangGraph
12+
- W3C trace context propagation for distributed tracing
13+
14+
## Installation
1215

1316
```sh
1417
npm install @cozeloop/langchain
1518
# or
1619
pnpm install @cozeloop/langchain
1720
```
1821

19-
### 2. Basic Usage
20-
21-
1. Environment variables
22-
23-
The following variables are optional, and will be used if values provided.
22+
## Configuration
2423

25-
|Variable|Comment|Example|
26-
|----|----|------|
27-
|COZELOOP_WORKSPACE_ID|Cozeloop workspace id, used to identify the workspace to which resource such as trace belongs|'7487806534651887643'|
28-
|COZELOOP_API_TOKEN|Cozeloop api token, see [authentication-for-sdk](https://loop.coze.cn/open/docs/cozeloop/authentication-for-sdk) |'pat_xxxx'|
29-
|COZELOOP_OTLP_ENDPOINT|Trace endpoint|'https://api.coze.cn/v1/loop/opentelemetry/v1/trace'|
24+
### Environment Variables
3025

26+
The following environment variables can be used to configure the integration:
3127

32-
2. `CozeloopCallbackHandler`
28+
| Variable | Description | Example |
29+
|----------|-------------|---------|
30+
| `COZELOOP_WORKSPACE_ID` | Workspace ID for resource association | `'7487806534651887643'` |
31+
| `COZELOOP_API_TOKEN` | API token for authentication. See [Authentication Guide](https://loop.coze.cn/open/docs/cozeloop/authentication-for-sdk) | `'pat_xxxx'` |
32+
| `COZELOOP_OTLP_ENDPOINT` | Trace reporting endpoint | `'https://api.coze.cn/v1/loop/opentelemetry/v1/traces'` |
3333

34-
Callbacks can be used with LangChain and LangGraph.
34+
## Usage
3535

36-
Since the traces exporting is asynchronous, it can be interrupted by the termination of Node.js process.
36+
### CozeloopCallbackHandler
3737

38-
(1) When you run a file in command line, call `await callback.flush();` to ensure all traces exported.
38+
The callback handler integrates with LangChain and LangGraph to automatically capture traces.
3939

40-
(2) If you are running a server-side application, there is no need to flush, but it's recommended to call `await callback.shutdown();` to clean resource.
40+
> **Note**: Since trace exporting is asynchronous, proper cleanup is required:
41+
>
42+
> - **CLI scripts**: Call `await callback.flush()` before exit to ensure all traces are exported.
43+
> - **Server applications**: Call `await callback.shutdown()` during graceful shutdown to release resources.
4144
42-
* Initialize
45+
#### Initialization
4346

4447
```typescript
4548
import { CozeloopCallbackHandler } from '@cozeloop/langchain';
4649

47-
// initialize callback
4850
const callback = new CozeloopCallbackHandler({
49-
// Common callback params
51+
// Span exporter configuration
52+
spanExporter: {
53+
workspaceId: 'xxx',
54+
token: 'pat_xxx',
55+
traceEndpoint: 'https://api.coze.cn/v1/loop/opentelemetry/v1/traces',
56+
},
57+
// Optional: Filter specific trace types
5058
// ignoreAgent: false,
5159
// ignoreChain: false,
5260
// ignoreCustomEvent: false,
5361
// ignoreLLM: false,
5462
// ignoreRetriever: false,
5563
// ignorePrompt: false,
56-
/** Span exporter */
57-
spanExporter: {
58-
workspaceId: 'xxx',
59-
token: 'pat_xxx',
60-
traceEndpoint: 'https://api.coze.cn/v1/loop/opentelemetry/v1/traces',
61-
},
62-
/** Propagate with upstream services */
64+
65+
// Optional: Propagate trace context from upstream services
6366
// propagationHeaders: {
64-
// tracestate: '',
6567
// traceparent: '00-b3691bfe8af1415029177821d4114cef-ddd0307891d51ce3-01',
68+
// tracestate: '',
6669
// },
6770
});
6871

69-
// use to propagate with downstream services
70-
// callback.w3cPropagationHeaders
72+
// Access W3C propagation headers for downstream services
73+
// const headers = callback.w3cPropagationHeaders;
7174
```
7275

73-
* With LangChain
76+
#### With LangChain
77+
7478
```typescript
7579
import { CozeloopCallbackHandler } from '@cozeloop/langchain';
7680
import { ChatPromptTemplate } from '@langchain/core/prompts';
7781

78-
// Chain
82+
const callback = new CozeloopCallbackHandler({ /* options */ });
83+
7984
const prompt = ChatPromptTemplate.fromTemplate('What is 1 + {number}?');
8085
const model = new CustomLLM({});
8186
const chain = prompt.pipe(model);
82-
const callback = new CozeloopCallbackHandler({ /** options */});
8387

8488
const resp = await chain.invoke(
8589
{ number: 1 },
8690
{
8791
runName: 'SuperChain',
88-
callbacks: [callback], // set callback
92+
callbacks: [callback],
8993
},
9094
);
9195

92-
// call `flush` to ensure trace exported in script run
96+
// Ensure traces are exported before script exits
9397
await callback.flush();
9498
```
9599

96-
* With LangGraph
100+
#### With LangGraph
101+
97102
```typescript
98103
import { CozeloopCallbackHandler } from '@cozeloop/langchain';
99-
100104
import { createReactAgent } from '@langchain/langgraph/prebuilt';
101105

106+
const callback = new CozeloopCallbackHandler({ /* options */ });
107+
102108
const agent = createReactAgent({
103109
llm: model,
104110
tools: [tool1, tool2],
105111
});
106112

107-
const resp = await graphAgent.invoke(
113+
const resp = await agent.invoke(
108114
{
109-
messages: [
110-
{
111-
role: 'user',
112-
content: 'xxx',
113-
},
114-
],
115+
messages: [{ role: 'user', content: 'Hello!' }],
115116
},
116-
{ callbacks: [callback] }, // set callback
117+
{ callbacks: [callback] },
117118
);
118119

119-
// call `flush` to ensure trace exported in script run
120+
// Ensure traces are exported before script exits
120121
await callback.flush();
121122
```

packages/cozeloop-langchain/__tests__/callback/utils/chain.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import {
44
guessChainInput,
55
guessChainOutput,
6+
isLangGraphNode,
67
} from '@cozeloop/langchain/callbacks/utils';
78

89
describe('guessChainInput', () => {
@@ -65,3 +66,16 @@ describe('guessChainOutput', () => {
6566
expect(guessChainOutput(output)).toBe(output.returnValues.text);
6667
});
6768
});
69+
70+
describe('isLangGraphNode', () => {
71+
it('🧪 should return true for "LangGraph" name', () => {
72+
expect(isLangGraphNode('LangGraph')).toBe(true);
73+
});
74+
75+
it('🧪 should return false for other names', () => {
76+
expect(isLangGraphNode('SomeOtherNode')).toBe(false);
77+
expect(isLangGraphNode('langgraph')).toBe(false);
78+
expect(isLangGraphNode('LANGGRAPH')).toBe(false);
79+
expect(isLangGraphNode('')).toBe(false);
80+
});
81+
});

packages/cozeloop-langchain/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cozeloop/langchain",
3-
"version": "0.0.2",
3+
"version": "0.0.3",
44
"description": "Integration LangChain with CozeLoop | 扣子罗盘 LangChain 集成",
55
"keywords": [
66
"cozeloop",
@@ -70,7 +70,7 @@
7070
"vitest": "~2.1.4"
7171
},
7272
"peerDependencies": {
73-
"@langchain/core": "^0.3.61",
74-
"@langchain/langgraph": "^0.3.1"
73+
"@langchain/core": "^0.3.61 || ^1.0.0",
74+
"@langchain/langgraph": "^0.3.1 || ^1.0.0"
7575
}
7676
}

packages/cozeloop-langchain/src/callbacks/callback-handler.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
generateUUID,
2929
guessChainInput,
3030
guessChainOutput,
31+
isLangGraphNode,
3132
parseBaseMessages,
3233
parseLLMResult,
3334
stringifyVal,
@@ -334,7 +335,9 @@ export class CozeloopCallbackHandler
334335
const spanName = runName || 'ChainStart';
335336
this._startSpan(spanName, runId, parentRunId, span => {
336337
span.setAttributes({
337-
[CozeloopAttr.SPAN_TYPE]: CozeloopSpanType.CHAIN,
338+
[CozeloopAttr.SPAN_TYPE]: isLangGraphNode(spanName)
339+
? CozeloopSpanType.GRAPH
340+
: CozeloopSpanType.CHAIN,
338341
[CozeloopAttr.INPUT]: stringifyVal(guessChainInput(inputs)),
339342
});
340343
});

packages/cozeloop-langchain/src/callbacks/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export enum CozeloopSpanType {
3737
RETRIEVER = 'retriever',
3838
TOOL = 'tool',
3939
CHAIN = 'chain',
40+
GRAPH = 'graph',
4041
AGENT = 'agent',
4142
CUSTOM = 'custom',
4243
}

packages/cozeloop-langchain/src/callbacks/utils/chain.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,7 @@ export function guessChainOutput(outputs?: ChainValues) {
2727
outputs
2828
);
2929
}
30+
31+
export function isLangGraphNode(name: string) {
32+
return name === 'LangGraph';
33+
}

packages/cozeloop-langchain/src/callbacks/utils/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
22
// SPDX-License-Identifier: MIT
3-
export { guessChainInput, guessChainOutput } from './chain';
3+
export { guessChainInput, guessChainOutput, isLangGraphNode } from './chain';
44
export { generateUUID, stringifyVal } from './common';
55
export { parseBaseMessages, parseRawMessage } from './message';
66
export {

0 commit comments

Comments
 (0)