stillrunning-langchain
v0.1.0
Published
One-line monitoring for LangChain. A BaseCallbackHandler that pings StillRunning on every chain/agent run with duration, tokens, cost, model, and tool-call count.
Downloads
173
Maintainers
Readme
stillrunning-langchain
One-line monitoring for LangChain. A BaseCallbackHandler that pings StillRunning once per top-level run (chain or agent) with its duration, tokens, cost, model, and tool-call count, and alerts you the moment a run fails, runs too long, or costs too much.
import { stillrunning } from 'stillrunning-langchain'
const sr = stillrunning() // reads STILLRUNNING_TOKEN
await chain.invoke({ topic: 'otters' }, { callbacks: [sr.handler] })Attach sr.handler via the callbacks option on any chain, agent, model, or .invoke / .stream call. One handler instance is safe to reuse across many concurrent invocations, state is keyed by each run tree's root.
Install
npm install stillrunning-langchainLangChain (@langchain/core) is your dependency; this package is a callback handler that plugs into it.
Setup
- Create a workflow at stillrunning.ai/app/new and copy its ping token.
- Set
STILLRUNNING_TOKEN(or passstillrunning({ token })). - Pass
sr.handlerincallbacks.
What it captures
The handler watches the whole run tree (chain → LLM/chat-model → tools) and pings on the top-level run's completion with:
| Field | Source |
| --- | --- |
| success / fail | root chain/LLM end vs error |
| duration | wall-clock from the root run's start to its end |
| tokens in / out | summed across every LLM call in the tree (tokenUsage, usage, or usage_metadata) |
| cost | estimated from model + tokens (LangChain reports no dollar cost) |
| model | the model id from the LLM/chat-model start |
| tool calls | counted from handleToolStart |
Token usage is read from whichever shape your provider emits, and cost is estimated from a built-in pricing table (override with computeCost). A failed run still reports the tokens it burned.
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.
License
MIT
