axonpush
TypeScript SDKIntegrations

Vercel AI SDK

axonPushMiddleware is a LanguageModelMiddleware for wrapLanguageModel, recording generateText and streamText calls with usage and finish reason.

axonPushMiddleware returns a LanguageModelMiddleware for the Vercel AI SDK. Wrap a model with it once and every call through that model is traced, the call sites themselves do not change.

Tested against ai@^4.

Install

npm install @axonpush/sdk ai

Wrap the model

import { wrapLanguageModel } from "ai";
import { openai } from "@ai-sdk/openai";
import { AxonPush, axonPushMiddleware } from "@axonpush/sdk";

const client = new AxonPush();

const model = wrapLanguageModel({
  model: openai("gpt-4o"),
  middleware: axonPushMiddleware({
    client,
    channelId: process.env.AXONPUSH_CHANNEL_ID!,
    agentId: "support-bot",
  }),
});

Then use the wrapped model everywhere:

import { generateText, streamText } from "ai";

const { text } = await generateText({ model, prompt: "Explain quantum computing." });
const stream = streamText({ model, prompt: "Explain quantum computing." });

agentId defaults to "vercel-ai".

What gets emitted

The middleware implements both wrapGenerate and wrapStream.

Identifieraxonpush eventTypePayload
llm.startagent.startmodel, prompt_tokens (non-streaming) or streaming: true
llm.tokenagent.llm.tokentoken, one per text-delta chunk
llm.endagent.endmodel, usage, finish_reason

On the streaming path the middleware pipes the model’s stream through a TransformStream, emitting a token event per delta and reading usage and finishReason off the terminal finish chunk. Every chunk is passed through untouched, so your consumer sees exactly what it would without the middleware.

prompt_tokens on a non-streaming llm.start is the length of the prompt array, not a token count, it is captured before the call, when no token count exists yet. The real counts arrive on llm.end in usage.

Every event carries metadata.framework: "vercel-ai".