@cloudbase/agent-observability
v0.0.18
Published
OpenInference-compatible observability for AG-Kit
Readme
TypeScript Observability
OpenTelemetry-based observability for the TypeScript SDK with OpenInference semantic conventions.
Installation
Standalone Usage
# Core package
npm install @cloudbase/agent-observability
# With LangChain integration
npm install @cloudbase/agent-observability @langchain/coreWith AG-Kit Server (Optional)
When using @cloudbase/agent-server or @cloudbase/agent-adapter-langgraph, observability is an optional peer dependency. You need to explicitly install it if you want tracing capabilities:
# Using with @cloudbase/agent-server
npm install @cloudbase/agent-server @cloudbase/agent-observability
# Using with @cloudbase/agent-adapter-langgraph
npm install @cloudbase/agent-adapter-langgraph @cloudbase/agent-observabilityWithout installing @cloudbase/agent-observability, the packages will work normally but no traces will be generated.
Architecture Overview
This package provides a callback-based observability system that integrates with LangChain/LangGraph through the standard BaseCallbackHandler mechanism.
Core Components
┌─────────────────────────────────────────────────────────────────┐
│ Application │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Server Layer │ │
│ │ Creates AG-UI.Server span, extracts SpanContext, │ │
│ │ propagates via forwardedProps │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Adapter Layer (LangGraph) │ │
│ │ Restores SpanContext, sets external parent context │ │
│ │ in CallbackHandler │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ LangGraph Workflow (streamEvents) │ │
│ │ Events flow through patched astream_events │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ CallbackHandler (BaseCallbackHandler) │ │
│ │ on_chain_start, on_llm_start, on_tool_start, etc. │ │
│ │ Creates spans with correct parent-child relationships │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ OpenTelemetry │ │
│ │ SpanContext propagation, OTLP exporters │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘Callback Mechanism
The observability system uses LangChain's standard BaseCallbackHandler to automatically capture tracing events:
Callback Registration
import { CallbackHandler } from '@cloudbase/agent-observability/langchain'; const handler = new CallbackHandler({ adapterName: 'LangGraph' });Span Hierarchy Construction
- Server span created at request entry
- SpanContext serialized and passed through
forwardedProps - Adapter layer restores context and sets external parent
- CallbackHandler creates child spans with correct parent relationships
Event Handling
on_chain_start: Creates CHAIN spans (Adapter.LangGraph, nodes)on_llm_start: Creates LLM spans (ChatOpenAI, etc.)on_tool_start: Creates TOOL spans (calculator, etc.)on_chain_end/on_llm_end/on_tool_end: End spans with duration
Quick Start
Basic Span Creation
import { startObservation } from '@cloudbase/agent-observability';
// Create a span
const span = startObservation(
'my-operation',
{ 'http.method': 'GET' },
{ asType: 'span' }
);
// Update and end
span.update({ 'http.status_code': 200 });
span.end();LangChain Integration
import { CallbackHandler } from '@cloudbase/agent-observability/langchain';
import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
const handler = CallbackHandler.create({
adapterName: 'LangGraph'
});
// Use with LangChain
const chain = new LLMChain({ llm, prompt, callbacks: [handler] });
await chain.invoke({ input: 'Hello' });LangGraph Integration
import { CallbackHandler } from '@cloudbase/agent-observability/langchain';
import { StateGraph } from '@langgraph/langgraph';
const workflow = new StateGraph(StateSchema)
.addNode('node_a', nodeA)
.addNode('node_b', nodeB)
.compile();
// The callback is automatically injected through the agent wrapper
const agent = new LangGraphAgent({ graph: workflow });Span Hierarchy Example
When using LangGraph with the server:
AG-UI.Server (Request entry point)
└─ Adapter.LangGraph (Agent adapter layer)
├─ node_a (LangGraph node)
│ └─ ChatOpenAI (LLM call)
├─ node_b (LangGraph node)
│ ├─ ChatOpenAI (LLM call)
│ └─ calculator (Tool call)
└─ synthesizer (LangGraph node)
└─ ChatOpenAI (LLM call)Internal spans: LangGraph also emits internal spans like __start__ and ChannelWrite<...> which are tagged with metadata.tags: ["langsmith:hidden"]. These can be filtered in visualization tools if desired.
OpenInference Semantic Conventions
This package follows OpenInference standards:
| Span Kind | Attribute | Description |
|-----------|-----------|-------------|
| SPAN | openinference.span.kind: SPAN | General operations |
| CHAIN | openinference.span.kind: CHAIN | Chain/workflow spans |
| LLM | openinference.span.kind: LLM | LLM calls |
| TOOL | openinference.span.kind: TOOL | Tool/function calls |
| AGENT | openinference.span.kind: AGENT | Agent workflows |
Key Attributes
input.value/output.value: Message contentllm.model_name: Model identifierllm.token_count.prompt/llm.token_count.completion: Token usagetool.name: Tool function name
Exporters
Console (Local Debug)
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));OTLP (Langfuse, etc.)
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
const exporter = new OTLPTraceExporter({
url: 'http://localhost:3000/api/public/otel/v1/traces',
headers: {
'Authorization': `Basic ${credentials}`
}
});API Reference
Core Functions
startObservation(name, attributes, options): Create a new spangetActiveTraceId(): Get current trace IDgetActiveSpanId(): Get current span ID
CallbackHandler
interface CallbackHandlerOptions {
adapterName: string; // e.g., 'LangGraph', 'LangChain'
traceMetadata?: Record<string, string>;
observationCallbacks?: (obs: any) => void;
}Span Types
ObservationLLM: LLM generation spansObservationTool: Tool invocation spansObservationChain: Chain/workflow spansObservationAgent: Agent spans
Dependencies
Peer Dependencies
@langchain/core: For LangChain callback integration
Dev Dependencies
@opentelemetry/sdk-trace-base: For testing exporters@opentelemetry/exporter-trace-otlp-http: For OTLP export
