SDK
LangChain
The stillrunning-langchain package is a LangChain BaseCallbackHandler. Attach it via callbacks and StillRunning gets a ping once per top-level run (chain or agent) with its duration, tokens, cost, model, and tool-call count, and alerts you the moment one fails, runs too long, or costs too much.
Install
npm install stillrunning-langchainLangChain (@langchain/core) is your own dependency. This package plugs into it as a callback handler.
30-second quickstart
1. Create a workflow at stillrunning.ai/app/new and copy its token. 2. Set STILLRUNNING_TOKEN. 3. Pass the handler in callbacks:
import { stillrunning } from 'stillrunning-langchain'
const sr = stillrunning() // reads STILLRUNNING_TOKEN
await chain.invoke({ topic: 'otters' }, { callbacks: [sr.handler] })sr.handleris a ready-to-use callback handler. One instance is safe to reuse across many concurrent invocations, state is keyed by each run tree's root.
What it captures
The handler watches the whole run tree (chain → LLM/chat-model → tools) and pings on the top-level run's completion. Token usage is summed across every LLM call and read from whichever shape your provider emits (tokenUsage, usage, or per-message usage_metadata); cost is estimated from the model + tokens since LangChain reports no dollar cost. Tool calls are counted from handleToolStart.
A run that errors at the top level pings fail with the error message, and still reports the tokens it burned before failing.
Grouping multi-step runs
Wrap several invocations in withTrace so they share one traceId and stitch into a single outcome chain:
import { stillrunning, withTrace } from 'stillrunning-langchain'
const sr = stillrunning()
await withTrace(async () => {
await planner.invoke(input, { callbacks: [sr.handler] })
await executor.invoke(input, { callbacks: [sr.handler] })
})Configuration
stillrunning({
token, // ping token; defaults to process.env.STILLRUNNING_TOKEN
baseUrl, // defaults to https://stillrunning.ai
computeCost, // ({ model, inputTokens, outputTokens }) => number — override cost estimation
awaitPing, // default true; false = fire-and-forget (lowest latency)
pingTimeoutMs, // default 3000
onError, // (err) => void — observe ping delivery failures
fetch, // custom fetch (testing / non-global-fetch runtimes)
})Monitoring never throws into your code: a failed ping routes to onError and is otherwise swallowed, bounded by pingTimeoutMs. Your chains run exactly as before.
Requirements
Node 18+. @langchain/core ≥ 0.2 as a peer dependency. Ships ESM + CJS with TypeScript types.
You're set
Open your dashboard to watch chain and agent runs land with duration, cost, tool counts, and anomaly alerts.
Open dashboard