SDK Reference
TypeScript SDK Reference
Constructor and configuration, event and lifecycle methods, decorators, tracing, governance, forensic, and verification methods, plus framework integrations for the Blocklog TypeScript client.
Constructor
new BlocklogClient()
The main entry point and orchestration layer. Coordinates configuration, tracing, the event pipeline, queues, and transport — while keeping minimal business logic of its own.
new BlocklogClient(
config: BlocklogConfig,
dependencies?: ClientDependencies
)Parameters
config· BlocklogConfigConfiguration object. See BlocklogConfig below.
dependencies· ClientDependencies, optionalDependency injection overrides — transport, retry, buffer, processor, memoryQueue, persistentQueue, deadLetterQueue. Mainly used for testing.
Key client properties
decisions: DecisionsClientCreate, get, list, search, update, and verify decision records.
traces: TracesClientRetrieve traces and trace timelines.
approvals: ApprovalClientHuman-in-the-loop approval workflows. Aliased as client.hitl.
incidents: IncidentsClientCreate, update, assign, resolve, and close incidents.
compliance: ComplianceClientGenerate audits, dashboards, and exportable evidence.
replay: ReplayClientReconstruct, verify, replay, and compare traces. Aliased as client.forensics.
traceManager: typeof TraceManagerStatic span-management class — see TraceManager below.
Example
const client = new BlocklogClient({
apiKey: 'your-api-key',
endpoint: 'base_url',
batchSize: 100,
flushInterval: 5000
});Type
BlocklogConfig
The configuration object passed to the BlocklogClient constructor. Resolved into a ResolvedConfig internally, with environment-variable fallbacks and defaults applied.
interface BlocklogConfig {
apiKey: string;
endpoint?: string;
batchSize?: number;
flushInterval?: number;
timeout?: number;
retryCount?: number;
enableSigning?: boolean;
signingKey?: string;
signingAlg?: 'hmac-sha256' | 'ed25519';
enableCompression?: boolean;
debug?: boolean;
}Fields
apiKey· stringRequired. Your Blocklog API key.
endpoint· string, optionalOverride the default API base URL.
batchSize· number, optionalEvents per batch flush. Default is 100.
flushInterval· number, optionalMilliseconds between automatic flushes.
timeout· number, optionalPer-request timeout in milliseconds.
retryCount· number, optionalAutomatic retry attempts on failure.
enableSigning· boolean, optionalTurn on tamper-evident event signing.
signingKey· string, optionalKey used for signing, when enableSigning is true.
signingAlg· 'hmac-sha256' | 'ed25519', optionalSigning algorithm. Defaults to hmac-sha256.
enableCompression· boolean, optionalCompress event payloads before sending.
debug· boolean, optionalLog every outbound request to stderr.
Example
const client = new BlocklogClient({
apiKey: process.env.BLOCKLOG_API_KEY!,
enableSigning: true,
signingAlg: 'hmac-sha256',
debug: process.env.NODE_ENV !== 'production'
});Event Methods
client.event() / client.enqueue()
Send a single event immediately with event(), or buffer it for batched delivery with enqueue(). Both take the same arguments — enqueue() simply resolves to null while the event sits in the buffer.
event(eventType: string, payload: any, options?: EventOptions): Promise<IngestResponse>
enqueue(eventType: string, payload: any, options?: EventOptions): Promise<IngestResponse | null>Parameters
eventType· stringEvent type identifier, e.g. "AGENT_RUN" or "TOOL_CALL".
payload· anyEvent payload data. Must be serializable.
options· EventOptions, optionalmetadata, trace_id, span_id, and timestamp overrides.
Example
await client.event('AGENT_RUN', {
agent_id: 'my-agent',
input: 'test input',
output: 'test output'
});
await client.enqueue('TOOL_CALL', {
tool_name: 'calculator',
input: '2 + 2',
output: '4'
});Middleware Method
client.addHook()
Register a middleware hook that can transform, enrich, validate, or filter every outbound event. Hooks run in the order they were added and may be async.
addHook(hook: MiddlewareHook): BlocklogClient
type MiddlewareHook = (event: EventEnvelope) => EventEnvelope | Promise<EventEnvelope> | nullParameters
hook· MiddlewareHookReceives an EventEnvelope and returns a (possibly modified) envelope, or null to drop the event entirely.
Example
client.addHook((event) => {
event.metadata = { ...event.metadata, enriched: true };
return event;
});- —Returning null from a hook skips the event entirely — useful for filtering debug events in production.
- —addHook() returns the client itself, so calls can be chained.
Lifecycle
client.flush() / shutdown() / health()
Manage the client's buffered events and background resources.
flush(): Promise<IngestResponse>
shutdown(): Promise<void>
health(): Promise<HealthStatus>What each call does
flush()Flushes the pipeline, buffer, and queues, then awaits transport completion.
shutdown()Flushes everything, persists the queue, stops timers, and closes transports to prevent event loss.
health()Returns { healthy, queueDepth, pendingEvents, transportReady } for monitoring.
Example
await client.flush();
const health = await client.health();
console.log(health);
// { healthy: true, queueDepth: 0, pendingEvents: 0, transportReady: true }
await client.shutdown();Decorator
@traceAgent
Trace an AI agent method automatically, emitting AGENT_START, AGENT_COMPLETE, and AGENT_ERROR events with input/output, duration, and trace context.
function traceAgent(options: AgentOptions | string)Parameters
options· AgentOptions | stringAn agent name string, or an options object: { name, version, tags, metadata }.
Example
class WeatherAgent {
@traceAgent('weather-agent')
async getWeather(location: string): Promise<string> {
const response = await fetch(`https://api.weather.com/${location}`);
return (await response.json()).weather;
}
}- —Trace context (trace ID, span ID, parent span ID) propagates automatically to nested @traceAgent calls.
- —On error, AGENT_ERROR is emitted with the error details before it propagates to the caller.
Method
executeAgent()
Trace an agent execution without a decorator — useful for functional code or one-off calls.
function executeAgent<T>(
agentId: string,
fn: () => Promise<T>,
options?: AgentOptions
): Promise<T>Parameters
agentId· stringAgent identifier.
fn· () => Promise<T>Function to execute and trace.
options· AgentOptions, optionalversion, tags, metadata.
Example
const result = await executeAgent(
'my-agent',
async () => 'agent result',
{ version: '1.0', tags: ['test'], metadata: { custom: 'value' } }
);Tracing
TraceManager
Static class managing span lifecycle and context propagation across async operations, via Async Local Storage.
class TraceManager {
static startSpan(name: string, options?: SpanOptions): Span
static endSpan(span: Span | string, status?: string): void
static currentSpan(): Span | undefined
static parentSpan(): Span | undefined
static runWithSpan<T>(span: Span, fn: () => Promise<T>): Promise<T>
}Static methods
startSpan(name, options?)Creates and starts a new span, storing it in Async Local Storage.
endSpan(span, status?)Finalizes a span, optionally recording a status such as "success" or "error".
currentSpan()Returns the active span for the current async context, if any.
parentSpan()Returns the parent of the active span, if any.
runWithSpan(span, fn)Runs fn() with span set as the active context for any nested operations.
Example
const span = TraceManager.startSpan('my-operation');
const result = await TraceManager.runWithSpan(span, async () => {
return 'result';
});
TraceManager.endSpan(span, 'success');- —Spans propagate automatically across await boundaries — no manual threading of IDs required.
- —Always end a span, ideally in a finally block, so it isn't left open if the wrapped code throws.
Governance Method
client.approvals.create()
Request human review for a decision. Part of the ApprovalClient, which also exposes approve(), reject(), status(), and list(). Aliased as client.hitl.
client.approvals.create(data: Record<string, any>): Promise<any>
client.approvals.approve(id: string, reason?: string): Promise<any>
client.approvals.reject(id: string, reason?: string): Promise<any>
client.approvals.status(id: string): Promise<any>
client.approvals.list(params?: Record<string, any>): Promise<any>Parameters
decisionId· stringID of the decision this approval request relates to.
reason· stringWhy human review is needed.
metadata· Record<string, any>, optionalExtra context, e.g. required_approver, expires_at, approval_level.
Example
const approval = await client.approvals.create({
decisionId: 'decision-123',
reason: 'High value trade requires approval'
});
await client.approvals.approve(approval.id, 'Approved based on risk analysis');
const status = await client.approvals.status(approval.id);- —Approval requests resolve to a status of "pending", "approved", or "rejected".
Forensic Method
client.replay.reconstruct()
Reconstruct a trace for debugging and analysis. Part of the ReplayClient, which also exposes verify(), replay(), get(), list(), and compare(). Aliased as client.forensics.
client.replay.reconstruct(traceId: string, options?: Record<string, any>): Promise<any>
client.replay.verify(id: string): Promise<any>
client.replay.replay(id: string, options?: Record<string, any>): Promise<any>
client.replay.compare(idA: string, idB: string): Promise<any>Parameters
traceId· stringTrace to reconstruct.
options· Record<string, any>, optionalinclude_tool_calls, include_decisions, include_timeline, and similar flags.
Example
const reconstruction = await client.replay.reconstruct('trace-123', {
include_tool_calls: true,
include_decisions: true
});
const result = await client.replay.replay(reconstruction.replay_id, {
speed: 2,
stop_on_error: false
});- —compare(idA, idB) returns { identical, differences, similarity_score } for A/B debugging two executions.
Verification Method
client.decisions.verify()
Confirm a decision record's integrity and that it hasn't been tampered with since creation.
client.decisions.verify(id: string): Promise<any>Parameters
id· stringDecision ID to verify.
Example
const verification = await client.decisions.verify('decision-123');
if (verification.valid) {
console.log('Decision is valid');
} else {
console.log('Decision verification failed:', verification.reason);
}Framework instrumentation
Integrations
Native instrumentation for LangChain, LangGraph, and OpenAI Agents. Each integration wires into the framework’s callback or hook system to trace chains, nodes, tools, and LLM calls automatically, with manual hooks available for anything outside the automatic path.
Common behaviour across all integrations
- —All instrument*() functions read configuration from the global client — call setGlobalClient() before instrumenting.
- —Trace context (trace ID, span ID, parent span ID) is preserved across async operations via Async Local Storage, the same mechanism TraceManager itself uses.
- —Errors are always traced — automatic instrumentation captures exceptions before they propagate, and manual hooks expose explicit onError / handle*Error methods for the same purpose.
- —Each integration also accepts a custom callback handler class for frameworks that support pluggable callbacks, letting you forward lifecycle events to the tracer or hooks object yourself.
Integration
LangChain
Wraps LangChain's callback system to trace chains, tools, LLM calls, and agents.
Setup
import { BlocklogClient, setGlobalClient, instrumentLangChain } from '@blocklog/sdk';
const client = new BlocklogClient({ apiKey: 'your-api-key' });
setGlobalClient(client);
const tracer = instrumentLangChain();Automatic tracing
import { AgentExecutor, createOpenAIFunctionsAgent } from 'langchain/agents';
const agent = await createOpenAIFunctionsAgent(llm, tools, prompt);
const executor = new AgentExecutor({ agent, tools, verbose: true });
// Execution is automatically traced
const result = await executor.invoke({ input: 'What is the weather?' });Manual tracing hooks
For cases the automatic instrumentation doesn’t cover, call the corresponding hook directly.
| Method | Use it to… |
|---|---|
handleChainStart(chain, inputs, runId) | Mark a chain's start. chain is { name, metadata? }. |
handleChainEnd(outputs, runId) | Mark a chain's successful completion. |
handleToolStart(tool, input, runId) | Mark a tool call's start. |
handleToolEnd(output, runId) | Mark a tool call's completion. |
handleLLMStart(llm, prompts, runId) | Mark an LLM call's start. |
handleLLMEnd(output, runId) | Mark an LLM call's completion. |
- —For deeper control, subclass BaseCallbackHandler and forward each callback to the matching tracer.handle*() method.
- —Set the global client with setGlobalClient() before calling instrumentLangChain() — the tracer reads from the global client.
Integration
LangGraph
Extends the same hook pattern to LangGraph's node, edge, and graph lifecycle.
Setup
import { BlocklogClient, setGlobalClient, instrumentLangGraph } from '@blocklog/sdk';
const client = new BlocklogClient({ apiKey: 'your-api-key' });
setGlobalClient(client);
const hooks = instrumentLangGraph();Automatic tracing
const compiledGraph = graph.compile();
// Node, edge, and graph execution are automatically traced
const result = await compiledGraph.invoke({ input: 'test input' });Manual tracing hooks
For cases the automatic instrumentation doesn’t cover, call the corresponding hook directly.
| Method | Use it to… |
|---|---|
onGraphStart({ graph_id, metadata? }) | Mark the start of a graph run. |
onGraphEnd({ graph_id }) | Mark the end of a graph run. |
onNodeStart(nodeName, state, runId) | Mark a node's start, including the state it received. |
onNodeEnd(nodeName, state, runId) | Mark a node's completion, including the state it produced. |
onEdge(from, to, condition, runId) | Mark an edge transition, including whether it matched a condition. |
- —Conditional edges added via addConditionalEdges() are traced the same way as static edges.
- —State objects passed to onNodeStart / onNodeEnd are recorded as-is, so keep them serializable.
Integration
OpenAI Agents
Traces OpenAI chat completion calls, tool and function calls, and the messages exchanged during an agent run.
Setup
import { BlocklogClient, setGlobalClient, instrumentOpenAIAgents } from '@blocklog/sdk';
const client = new BlocklogClient({ apiKey: 'your-api-key' });
setGlobalClient(client);
const hooks = instrumentOpenAIAgents();Automatic tracing
import { OpenAI } from 'openai';
const openai = new OpenAI({ apiKey: 'your-openai-key' });
// Chat completions, tool calls, and messages are automatically traced
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Hello' }]
});Manual tracing hooks
For cases the automatic instrumentation doesn’t cover, call the corresponding hook directly.
| Method | Use it to… |
|---|---|
onAgentRunStart(agentId, input) | Mark the start of an agent run. |
onAgentRunEnd(agentId, output) | Mark an agent run's successful completion. |
onAgentRunError(agentId, error) | Mark an agent run's failure. |
onToolCall(toolName, args) | Record a tool call's name and arguments. |
onFunctionCall(name, args) | Record a legacy function-calling invocation. |
onMessage(role, content) | Record a message exchanged during the run — user, assistant, or system. |
- —Call onAgentRunError() inside a catch block and re-throw, so failures are traced without being swallowed.
- —Metadata such as user_id, session_id, or environment can be passed alongside input on onAgentRunStart().