LangChain
The LangChain callback handler is the primary integration. One handler, zero changes to your chain, full coverage of retrievals and (optionally) generations.
Recommended over wrap() because callbacks fire correctly for ensemble retrievers, MultiVectorRetriever, ParentDocumentRetriever, MMR rerankers, cached retrievers, and LCEL-composed chains — all places where a naive wrap either misses traces or generates noise.
Install
npm install buzo-sdk @langchain/coreBasic usage
Attach the handler to any retriever invocation. The handler is safe to reuse across requests.
import { Buzo } from 'buzo-sdk'
import { createBuzoCallbackHandler } from 'buzo-sdk/langchain'
export const buzo = new Buzo({ apiKey: process.env.BUZO_API_KEY! })
const handler = await createBuzoCallbackHandler(buzo, {
collectionId: 'prod-support-kb',
agentId: 'support-v3',
})
const docs = await retriever.invoke('how do I reset my password?', {
callbacks: [handler],
})Full chain coverage (retrieval + generation)
Enable outputCapture on the Buzo client and the same handler also fires on the LLM step of the chain — Buzo correlates retrieval and generation server-side via LangChain runId.
import { Buzo } from 'buzo-sdk'
import { createBuzoCallbackHandler } from 'buzo-sdk/langchain'
import { ChatPromptTemplate } from '@langchain/core/prompts'
import { ChatOpenAI } from '@langchain/openai'
import { RunnablePassthrough } from '@langchain/core/runnables'
const buzo = new Buzo({
apiKey: process.env.BUZO_API_KEY!,
outputCapture: 'redacted',
outputRedactPatterns: [
{ pattern: /[\w.-]+@[\w.-]+\.\w+/g, replacement: '<EMAIL>' },
],
})
const handler = await createBuzoCallbackHandler(buzo, {
collectionId: 'prod-support-kb',
agentId: 'support-v3',
})
const prompt = ChatPromptTemplate.fromTemplate(`
Answer based on context:
{context}
Question: {question}`)
const chain = RunnablePassthrough
.assign({ context: async (i) => retriever.invoke(i.question) })
.pipe(prompt)
.pipe(new ChatOpenAI({ modelName: 'gpt-4o' }))
const answer = await chain.invoke(
{ question: 'how do I reset my password?' },
{ callbacks: [handler] },
)What gets captured
| Event | When it fires | Sent to |
|---|---|---|
handleRetrieverEnd | Every retriever invocation in the chain | POST /v1/retrieval-traces |
handleLLMEnd | Every LLM/ChatModel call — only when outputCapture !== 'off' | POST /v1/generation-traces |
handleRetrieverError / handleLLMError | Failure paths; trace recorded with error field, original error re-thrown | Same endpoints as above |
Multiple collections in one chain
If your chain uses retrievers against different Buzo collections — for example an ensemble retriever that combines a product KB with a support KB — pass mapRunToContext to derive the collectionId per invocation from LangChain run metadata.
const handler = await createBuzoCallbackHandler(buzo, {
collectionId: 'default-kb',
mapRunToContext: ({ tags }) => {
if (tags?.includes('product')) return { collectionId: 'product-kb' }
if (tags?.includes('support')) return { collectionId: 'support-kb' }
return undefined
},
})Compatibility
- LangChain.js
v0.1.x,v0.2.x,v0.3.x. @langchain/coreis declared as an optional peer dependency. The SDK imports it lazily — you can installbuzo-sdkin a project that does not use LangChain without cost.- Ensemble retrievers,
MultiVectorRetriever,ParentDocumentRetriever, cached retrievers, and MMR rerankers all emit the expectedhandleRetrieverEndcallbacks and are fully supported.
wrap() and wrapPineconeIndex() helpers, or call recordRetrieval directly.
Buzo