Skip to content

Observability — metrics & Prometheus

You can’t run an agent in production you can’t see. toolnexus instruments the loop once and gives you two outputs from it — both opt-in, both zero-cost when unused.

Pass a sink and it receives a readable, semantic record at each significant point: one llm event per model call, one tool event per tool call, and one terminal run event per run/ask. Forward it to statsd, structured logs, or OpenTelemetry — the library holds no opinion.

const client = createClient({
baseUrl, style: "openai", model,
onMetric: (ev) => {
if (ev.event === "run") console.log(`run: ${ev.turns} turns, ${ev.totalTokens} tokens, ${ev.ms}ms`)
},
})

The three event shapes: { event: "llm", model, status, ms, promptTokens, completionTokens }, { event: "tool", tool, source, isError, ms, pending? }, and { event: "run", model, turns, toolCalls, totalTokens, ms, error? } — names idiomatic per port (snake_case in Python).

The same events feed a tiny in-memory registry that renders the Prometheus text exposition format — no third-party dependency. Mount it at GET /metrics:

// in your HTTP handler:
res.setHeader("Content-Type", "text/plain")
res.end(client.metrics()) // client.Metrics() in Go / Java / C#

It exposes toolnexus_llm_requests_total, toolnexus_llm_tokens_total, toolnexus_tool_calls_total, plus the toolnexus_llm_request_duration_seconds and toolnexus_tool_duration_seconds histograms.

A suspension is never counted as a tool error: its tool event carries isError: false and a pending: true marker, so error-rate metrics and circuit-breakers don’t trip on a human wait (see Suspension).