@tralo/node
v0.1.3
Published
AI agent monitoring SDK — zero-config observability
Readme
@tralo/node
AI agent monitoring SDK for Tralo. The SDK captures events and raw provider responses; the Tralo server validates, deduplicates, extracts tokens, and interprets provider formats.
Installation
npm install @tralo/node
npm install @tralo/node openai # with OpenAIQuickstart (autopatch)
import { Tralo, patchOpenAI } from '@tralo/node'
import OpenAI from 'openai'
const monitor = new Tralo({
apiKey: 'trl_live_YOUR_KEY',
agentId: 'my-agent'
})
const openai = new OpenAI()
patchOpenAI(openai, monitor)
// Your existing provider call is unchanged.
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'Hello' }]
})Autopatch sends raw provider responses to /v1/ingest. The server-side format registry extracts tokens, so provider format updates do not require an SDK release.
Context manager pattern
import { Tralo } from '@tralo/node'
const monitor = new Tralo({
apiKey: 'trl_live_YOUR_KEY',
agentId: 'support-agent'
})
await monitor.run(async (run) => {
await run.step({
stepName: 'classify',
model: 'gpt-4o',
tokensIn: 150,
tokensOut: 80,
latencyMs: 850,
input: { prompt: 'Classify this ticket' },
output: { label: 'billing' }
})
})monitor.run() sends run_start automatically. It sends run_end with success on clean exit and failure if your callback throws. The original error is re-thrown.
Decorator pattern
import { Tralo, track } from '@tralo/node'
const monitor = new Tralo({
apiKey: 'trl_live_YOUR_KEY',
agentId: 'support-agent'
})
class SupportAgent {
@track(monitor, { stepName: 'classify' })
async classifyTicket(text: string): Promise<string> {
return callLLM(text)
}
}Functional wrapper for non-class code:
const classifyTicket = monitor.wrap(
async (text: string) => callLLM(text),
{ stepName: 'classify' }
)Manual pattern
const run = monitor.startRun()
try {
await run.step({
stepName: 'classify',
model: 'gpt-4o',
tokensIn: 150,
tokensOut: 80
})
await run.end({ status: 'success' })
} catch (err) {
await run.end({ status: 'failure', errorMsg: String(err) })
throw err
}Provider wrappers
import {
patchAnthropic,
patchAuto,
patchGroq,
patchOpenAI,
unpatchOpenAI
} from '@tralo/node'
patchOpenAI(openaiClient, monitor)
patchAnthropic(anthropicClient, monitor)
patchGroq(groqClient, monitor)
patchAuto(customClient, monitor)
unpatchOpenAI()Patches are idempotent and reversible. Monitoring failures never break provider calls. Streaming calls post to /v1/events/stream-end, where the server reconstructs approximate output tokens from chunks.
Reliability
Every event gets an X-Idempotency-Key header so retries cannot create duplicate database rows. If the API is unavailable, events are written to ~/.tralo/failed_events.ndjson and retried on the next SDK initialization. API keys are never exposed in debug output.
Serverless
Use wrapHandler in AWS Lambda-style handlers:
import { Tralo, wrapHandler } from '@tralo/node'
const monitor = new Tralo({ apiKey: 'trl_live_YOUR_KEY', agentId: 'lambda-agent' })
export const handler = wrapHandler(monitor, async (event) => {
return runAgent(event)
})monitor.flush() is called before the handler returns. In Edge runtimes, file fallback is disabled because the filesystem is unavailable.
Configuration
const monitor = new Tralo({
apiKey: 'trl_live_YOUR_KEY',
agentId: 'my-agent',
baseUrl: 'https://api.tralo.dev',
debug: false
})Use baseUrl: 'http://localhost:8000' for a local Tralo API.
