@stigg/agent-sdk-js adds gating, metering and budgets to the LLM calls your agents make. See AI agents for setup, and the source on GitHub.
npm also lists versions 1.0.0, 1.0.1, 1.1.0 and 2.0.0. Those are pre-release builds published before the package was re-versioned, and they aren’t supported. Install 0.1.0 or later.
2026-10-26
LangChain and LangGraph
- Added:
StiggLangChainCallbackHandler, from the new@stigg/agent-sdk-js/langchainentry point. Pass it in a run’scallbacksto govern a LangChaincreateAgentgraph or a hand-built LangGraphStateGraph. Each model call and governed tool call is checked before it runs and billed after it succeeds, as the agent that made it.@langchain/core1.x is an optional peer dependency. - Added:
stigg.middleware({ stiggContext, tools, hooks, agents }), the framework-neutral logic behind the handler, for wiring other orchestrators. - Added: the run’s customer comes from
metadata.stiggCustomerId, or from a defaultcustomerIdinstiggContext. A run with neither is refused before its first step. SetstiggCustomerIdon your server, because it wins over the default. - Added: per-tool governance in
tools, keyed by tool name, with'*'for every tool not named:- An entitlement: checked, then billed one unit per call.
{ entitlement, usage }: checked, then billed by a usage mapper over the call’s input and output.{ usage }: billed, never checked.false: left ungoverned.
- Added:
agents, which gives each agent in the graph its ownstiggContextand tools, laid over the shared ones. Point an agent’sagentIdat an entity registered withstigg.register(), and its steps are checked and billed against that entity’s budget.
- Added: OpenTelemetry spans (
stigg.checkandstigg.ingest, with GenAI attribute names) from the middleware and the LangChain handler, so tracing tools such as Langfuse and LangSmith see Stigg’s decisions, including refusals.@opentelemetry/apiis an optional peer dependency, and without it no spans are emitted. Wrapped clients emit no spans. - Changed:
isAccessDeniedfinds anAccessDeniedErroranywhere in an error’s cause chain or inside anAggregateError. - Added:
HookContextcarries the agent and tool a hook fired for.
2026-10-21
- Added:
defaultPlanIdinstiggContext. A customer Stigg doesn’t know yet is created on that plan before their first check or report. An existing customer is left untouched.- Provisioning runs once per customer per process.
- If Stigg is unreachable, the failure goes to
onErrorand provisioning is retried on the next call. A check for a customer that couldn’t be provisioned followscheckErrorAction. - If Stigg refuses, for example because the plan doesn’t exist, the refusal is reported once and not retried.
2026-10-19
- Fixed: the npm package links to the public stigg-agent-sdk-ts repository. It previously linked to a private one.
- Fixed: the examples and
.env.templateuseSTIGG_SERVER_API_KEY, the variable the SDK reads. They previously usedSTIGG_API_KEY, which the SDK ignores. The examples still accept the old name.
2026-10-19
- Fixed: a stream split with
tee()is metered. Previously onlyfor awaitwas metered, so a teed Anthropic or OpenAI-compatible stream moved no budget. - ⚠️ Changed:
wrapthrows whenstiggContextsets anidempotencyKey. One key shared by every call deduplicated them all down to the first, so later calls moved no budget. SetidempotencyKeyper call instead. - ⚠️ Changed: a call throws when its
customerIdis empty or blank. It previously billed the client’s default customer. A call with nocustomerIdstill uses the default. - Fixed:
apiKeyis no longer enumerable onstigg.config, so logging or serializing the client no longer prints the key.
2026-10-19
- Updated
@stigg/node-server-sdkto 6.2.0. No change to the Agent SDK API.
2026-10-14
Databricks
- Added:
databricksRecipe, matched automatically on a Databricks workspace’s/serving-endpointsor/ai-gateway/mlflow/v1URL. It covers both anOpenAIclient pointed at the workspace and Databricks’ own@databricks/sdk-modelservingqueryclient, and emitsdatabricks.chat.completions.create,databricks.responses.createanddatabricks.query. - Added: the model that answered is recorded as a dimension. On Databricks the
modelyou send is a serving endpoint name, so the response is the only place the real model appears. - Added:
databricksExternalRecipefor serving endpoints configured as external models, where the upstream provider charges you instead of Databricks. It emitsdatabricks-external.*events. It’s opt-in, because the two routes look identical from the client:stigg.wrap(client, { recipe: databricksExternalRecipe() }). - Neither recipe reports a
costmetric, because Databricks doesn’t state a price on any response. A workspace on a custom domain needs its base URL passed in:databricksRecipe({ baseUrl }).
- Added:
cloudflareRecipe, matched automatically for both Workers AI (api.cloudflare.com/client/v4/accounts/<id>/ai/v1) and AI Gateway (gateway.ai.cloudflare.com). It covers anOpenAIclient and thecloudflarepackage’s ownai.run, and emitscloudflare.chat.completions.create,cloudflare.responses.create,cloudflare.messages.createandcloudflare.ai.run. - Reports token counts only. Cloudflare doesn’t state a price or Neuron count on any response, so there’s no
costmetric. - On AI Gateway, the model that served and the
cf_aig_log_idare recorded as dimensions, and a cache hit isn’t metered because no one was charged for it. - Known limitation: a streamed
ai.runcall is gated but not metered, because Cloudflare returns raw SSE bytes for it.
2026-10-13
Initial release.Core
- Added:
StiggAgentSDK. Pass an API key, or one options object for the base URL, ingest mode and hooks. - Added:
stigg.wrap(client, { stiggContext }), which returns a copy of a vendor client whose calls are checked and metered. The context names the customer, the agent the call is attributed to, and an optionalentitlement. Naming an entitlement turns on gating. Without one, calls are metered but never refused. Any call can override the context in its own parameters, so one wrapped client can serve every customer. - Added:
stigg.register()andstigg.deregister()to create an agent entity with a budget and a parent. Both are optional. Without them, checks and usage apply to the customer. - Added: a refused call throws
AccessDeniedError. Pass it tostigg.denial(err)to get the decision, including which entity blocked the call and how to fix it. - Added:
ingest: 'async' | 'sync'. Usage is reported as raw events by default. A metric named after a credit currency draws the credit balance directly. Metering failures go to theonErrorhook and never break the call. - Added:
unitsPerTokensandweightedMetricsfor pricing token counts in code. Stigg recommends reporting raw token counts and converting them in Stigg instead.
- Added: Anthropic, OpenAI (Chat Completions and Responses), Google Gemini (models and chats), Groq, Mistral, Ollama and TypeSafe.
- Added: any other OpenAI-compatible endpoint, metered under
openai.*events.
- Added: OpenRouter, through an
OpenAIclient or OpenRouter’s own@openrouter/sdk. Reportscostand the model that served. - Added: LiteLLM. Reports
costfrom the response header and the model that served. - Added: Amazon Bedrock. Reports tokens only, because Bedrock doesn’t state a price.
- Added: a gateway you operate yourself. The wrapped client sends attribution as
x-stigg-*headers, and your gateway reports usage withstigg.ingestFromHeaders(...). This path meters but can’t refuse calls.