AutoGen Tutorial (TypeScript): adding observability for beginners

By Cyprian AaronsUpdated 2026-04-21
autogenadding-observability-for-beginnerstypescript

This tutorial shows you how to add basic observability to an AutoGen TypeScript agent so you can inspect prompts, responses, tool calls, and execution flow. You need this when an agent starts behaving unpredictably and you want hard evidence instead of guessing.

What You'll Need

  • Node.js 18+ installed
  • A TypeScript project with ts-node or a build step already set up
  • AutoGen packages:
    • @autogen/agentchat
    • @autogen/core
  • An OpenAI API key exported as OPENAI_API_KEY
  • A terminal that can run your script and print logs
  • Basic familiarity with AutoGen agents and messages

Step-by-Step

  1. Start by installing the packages and setting up your environment variables. For observability, we’re going to use simple structured logging first, because that gives you immediate visibility without adding extra infrastructure.
npm install @autogen/agentchat @autogen/core dotenv
export OPENAI_API_KEY="your-key-here"
  1. Create a small helper that logs each important event in a consistent format. In production, this is where you would later swap console.log for a real logger like Pino or Winston.
// logger.ts
export function logEvent(event: string, data: unknown) {
  const payload = {
    ts: new Date().toISOString(),
    event,
    data,
  };

  console.log(JSON.stringify(payload));
}
  1. Now create an AutoGen agent and wrap its execution with logs before and after the call. The key idea is to log the input, the output, and any metadata you care about so you can trace one request end-to-end.
// index.ts
import "dotenv/config";
import { AssistantAgent } from "@autogen/agentchat";
import { OpenAIChatCompletionClient } from "@autogen/core";
import { logEvent } from "./logger.js";

async function main() {
  const modelClient = new OpenAIChatCompletionClient({
    model: "gpt-4o-mini",
    apiKey: process.env.OPENAI_API_KEY,
  });

  const agent = new AssistantAgent({
    name: "support_agent",
    modelClient,
    systemMessage: "You are a concise support assistant.",
  });

  const task = "Explain what observability means in one sentence.";
  logEvent("agent.request.start", { agent: "support_agent", task });

  const result = await agent.run(task);

  logEvent("agent.request.end", {
    agent: "support_agent",
    output: result.messages.at(-1),
  });

  console.log(result.messages.at(-1));
}

main().catch((error) => {
  logEvent("agent.request.error", {
    message: error instanceof Error ? error.message : String(error),
  });
  process.exit(1);
});
  1. Add tool-level observability if your agent uses functions. This is where most debugging pain comes from, because tool inputs and outputs are often what explain bad agent behavior.
// tools.ts
import { FunctionTool } from "@autogen/core";
import { logEvent } from "./logger.js";

export const getPolicyStatus = FunctionTool.from(
  async (policyId: string) => {
    logEvent("tool.getPolicyStatus.start", { policyId });

    const result = {
      policyId,
      status: "active",
      renewalDate: "2026-01-15",
    };

    logEvent("tool.getPolicyStatus.end", result);
    return JSON.stringify(result);
  },
  {
    name: "getPolicyStatus",
    description: "Fetch the current status of an insurance policy.",
    parameters: {
      type: "object",
      properties: {
        policyId: { type: "string" },
      },
      required: ["policyId"],
      additionalProperties: false,
    },
  }
);
  1. Plug the tool into the agent and run a request that forces a tool call. You should now see request logs plus tool start/end logs, which gives you enough signal to debug most beginner-level issues.
// index.ts
import "dotenv/config";
import { AssistantAgent } from "@autogen/agentchat";
import { OpenAIChatCompletionClient } from "@autogen/core";
import { getPolicyStatus } from "./tools.js";
import { logEvent } from "./logger.js";

async function main() {
  const modelClient = new OpenAIChatCompletionClient({
    model: "gpt-4o-mini",
    apiKey: process.env.OPENAI_API_KEY,
  });

  const agent = new AssistantAgent({
    name: "support_agent",
    modelClient,
    systemMessage:
      "You are a support assistant. Use tools when asked about policies.",
    tools: [getPolicyStatus],
  });

  const task = "Check policy ABC123 and tell me its status.";
  logEvent("agent.request.start", { task });

  const result = await agent.run(task);

  logEvent("agent.request.end", {
    finalMessage: result.messages.at(-1),
    messageCount: result.messages.length,
  });
}

main().catch((error) => {
  logEvent("agent.request.error", {
    message: error instanceof Error ? error.message : String(error),
  });
});
  1. If you want better observability than raw logs, add correlation IDs so every line for one request can be grouped together. This matters once multiple users or background jobs are running at the same time.
// request-context.ts
import crypto from "node:crypto";

export function createRequestId() {
  return crypto.randomUUID();
}

export function withRequestId<T>(requestId: string, fn: () => Promise<T>) {
  console.log(JSON.stringify({ ts: new Date().toISOString(), requestId, event: "request.begin" }));
  return fn()
    .then((result) => {
      console.log(JSON.stringify({ ts: new Date().toISOString(), requestId, event: "request.success" }));
      return result;
    })
    .catch((error) => {
      console.log(
        JSON.stringify({
          ts: new Date().toISOString(),
          requestId,
          event: "request.failure",
          error: error instanceof Error ? error.message : String(error),
        })
      );
      throw error;
    });
}

Testing It

Run the script with npx ts-node index.ts or your normal TypeScript runner. You should see JSON logs for the request start, any tool calls, and the final response.

If the API key is missing or invalid, you should get a structured agent.request.error line instead of a silent failure. If your tool is called, confirm that both tool.getPolicyStatus.start and tool.getPolicyStatus.end appear in order.

For a real sanity check, run two requests back to back and verify each one produces its own traceable sequence of events. That tells you your logging is useful enough to debug concurrent traffic later.

Next Steps

  • Add a real logger like Pino with JSON output and log levels
  • Send traces to OpenTelemetry so you can correlate agent runs across services
  • Capture token usage and latency per run so you can track cost and performance

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