AutoGen Tutorial (TypeScript): adding cost tracking for advanced developers

By Cyprian AaronsUpdated 2026-04-21
autogenadding-cost-tracking-for-advanced-developerstypescript

This tutorial shows you how to wire cost tracking into an AutoGen TypeScript agent workflow so every model call is metered, logged, and easy to attribute per conversation or task. You need this when you’re running multi-agent systems in production and want visibility into spend before it turns into a finance problem.

What You'll Need

  • Node.js 18+ and npm
  • A TypeScript project with ts-node or a build step already set up
  • @autogenai/autogen installed
  • openai installed
  • An OpenAI API key in OPENAI_API_KEY
  • Basic familiarity with AutoGen agents, model clients, and async/await
  • A place to persist metrics:
    • console logs for local dev
    • JSONL file, Redis, Postgres, or Datadog for production

Step-by-Step

  1. Start by installing the packages and setting up a clean TypeScript project. I’m using the official OpenAI client directly because it gives you a reliable source of token usage data that you can attach to each AutoGen turn.
npm init -y
npm install @autogenai/autogen openai
npm install -D typescript ts-node @types/node
npx tsc --init
  1. Create a small cost tracker that converts token usage into dollars. Keep this separate from your agent code so you can reuse it across teams, workflows, and environments.
// cost-tracker.ts
export type Usage = {
  prompt_tokens?: number;
  completion_tokens?: number;
  total_tokens?: number;
};

const PRICING = {
  "gpt-4o-mini": { input: 0.15 / 1_000_000, output: 0.6 / 1_000_000 },
};

export function estimateCost(model: keyof typeof PRICING, usage: Usage) {
  const inputTokens = usage.prompt_tokens ?? 0;
  const outputTokens = usage.completion_tokens ?? 0;
  const price = PRICING[model];
  const cost = inputTokens * price.input + outputTokens * price.output;

  return {
    inputTokens,
    outputTokens,
    totalTokens: usage.total_tokens ?? inputTokens + outputTokens,
    costUsd: Number(cost.toFixed(8)),
  };
}
  1. Build your AutoGen model client and wrap each response with tracking. The important part is that you read usage from the OpenAI response and record it immediately after the call.
// index.ts
import OpenAI from "openai";
import { estimateCost } from "./cost-tracker";

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function main() {
  const model = "gpt-4o-mini" as const;

  const response = await client.chat.completions.create({
    model,
    messages: [
      { role: "system", content: "You are a concise banking assistant." },
      { role: "user", content: "Summarize the risks in one sentence." },
    ],
  });

  const usage = response.usage ?? {};
  const metrics = estimateCost(model, usage);

  console.log({
    requestId: response.id,
    model,
    ...metrics,
    text: response.choices[0]?.message?.content ?? "",
  });
}

main().catch(console.error);
  1. If you’re using an AutoGen agent loop, attach the same tracker around each turn instead of only at the end of the workflow. That gives you per-turn attribution, which matters when one agent is cheap and another is expensive.
import OpenAI from "openai";
import { estimateCost } from "./cost-tracker";

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function trackedTurn(model: "gpt-4o-mini", userText: string) {
  const result = await client.chat.completions.create({
    model,
    messages: [{ role: "user", content: userText }],
  });

  const metrics = estimateCost(model, result.usage ?? {});
  return {
    content: result.choices[0]?.message?.content ?? "",
    metrics,
  };
}

(async () => {
  const turn1 = await trackedTurn("gpt-4o-mini", "Draft a claims email.");
  console.log("turn1", turn1.metrics);

  const turn2 = await trackedTurn("gpt-4o-mini", "Make it shorter.");
  console.log("turn2", turn2.metrics);
})();
  1. For production, aggregate metrics by session so you can answer questions like “what did this case cost?” and “which workflow is burning tokens?” Persist raw events first; rollups can happen later in SQL or your observability stack.
type CostEvent = {
  sessionId: string;
  requestId?: string;
  model: string;
  inputTokens: number;
  outputTokens: number;
  totalTokens: number;
  costUsd: number;
};

const sessionTotals = new Map<string, number>();

function recordCost(event: CostEvent) {
  const current = sessionTotals.get(event.sessionId) ?? 0;
  sessionTotals.set(event.sessionId, current + event.costUsd);

  console.log(JSON.stringify({
    type: "llm_cost",
    ...event,
    sessionTotalUsd: Number(sessionTotals.get(event.sessionId)?.toFixed(8)),
    ts: new Date().toISOString(),
  }));
}

Testing It

Run the script with OPENAI_API_KEY set and confirm you get both text output and numeric usage data in the console. If usage comes back empty, check that you’re calling a model endpoint that returns token accounting and that your request actually completes successfully.

For a real test, run two or three turns in one session and verify totals increase monotonically. Then compare your logged token counts against the provider dashboard to make sure your pricing assumptions are aligned with the actual model you selected.

If you move this into a multi-agent flow, tag every event with sessionId, agentName, and workflowName. That gives you enough structure to build per-agent budgets and alert when a single case exceeds threshold.

Next Steps

  • Add budget guards that stop execution when a session crosses a dollar limit.
  • Export these events to Postgres or ClickHouse for reporting by team, tenant, or workflow.
  • Wrap this into an AutoGen middleware layer so every agent call is tracked automatically instead of manually instrumented.

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides