@anvia/logger

Structured logging adapters for Anvia agent events.

@anvia/logger provides console and Pino-based loggers, plus a logger observer that writes agent lifecycle events (runs, generations, tool calls) to your application logs.

Install

pnpm add @anvia/logger

Pino is included as a dependency. No additional installs needed.

Quick Start

import { AgentBuilder } from "@anvia/core";
import { OpenAIClient } from "@anvia/openai";
import { createLoggerObserver, createPinoLogger } from "@anvia/logger";

const logger = createPinoLogger({ name: "my-app", level: "info" });

const client = new OpenAIClient({ apiKey });
const agent = new AgentBuilder("support", client.completionModel())
  .instructions("Answer support questions.")
  .observe(createLoggerObserver(logger))
  .build();

const response = await agent.prompt("How do I reset my password?").send();

Every agent run now produces structured log lines for run start/end, model generations, tool calls, and errors.

Loggers

createPinoLogger

Production logger backed by Pino. Outputs structured JSON.

import { createPinoLogger } from "@anvia/logger";

const logger = createPinoLogger({
  name: "my-app",
  level: "info",
  bindings: { env: "production" },
  pinoOptions: { /* pass-through to Pino */ },
  destination: /* custom Pino destination stream */,
});
OptionDefaultPurpose
name--Logger name field in every log line
levelauto"trace" through "silent". Defaults to ANVIA_LOG_LEVEL, LOG_LEVEL, or "info"
bindings{}Default structured fields on every log line
pinoOptions{}Raw Pino options pass-through
destinationstdoutCustom Pino destination stream

createConsoleLogger

Lightweight JSON logger for development. No Pino dependency at runtime.

import { createConsoleLogger } from "@anvia/logger";

const logger = createConsoleLogger({
  name: "my-app",
  level: "debug",
  writer: (line) => console.log(line),  // custom output
  timestamp: () => new Date(),           // custom timestamps
});

Logger Interface

Both loggers implement the same Logger interface:

interface Logger {
  trace(message: string, context?: Record<string, unknown>): void;
  debug(message: string, context?: Record<string, unknown>): void;
  info(message: string, context?: Record<string, unknown>): void;
  warn(message: string, context?: Record<string, unknown>): void;
  error(message: string, context?: Record<string, unknown>): void;
  fatal(message: string, context?: Record<string, unknown>): void;
  child(bindings: Record<string, unknown>): Logger;
}

Use .child(...) to add scoped fields (e.g., request ID, user ID) to a subset of logs.

Logger Observer

createLoggerObserver adapts any Logger into an agent observer:

import { createLoggerObserver } from "@anvia/logger";

const observer = createLoggerObserver(logger, {
  includeOutput: false,      // log final agent output (default: false)
  includeRequest: false,     // log full model requests (default: false)
  includeResponse: false,    // log full model responses (default: false)
  includeToolResult: false,  // log tool results (default: false)
});

By default, the observer omits potentially sensitive payloads (final output, full model requests/responses, tool results). Enable these flags when your data policy allows logging those details.

Attach the observer to multiple agents:

const agent1 = new AgentBuilder("support", model).observe(observer).build();
const agent2 = new AgentBuilder("sales", model).observe(observer).build();

Log Levels

LevelUse for
traceExtremely verbose internal details
debugDevelopment diagnostics
infoNormal operational events (default)
warnUnexpected but recoverable situations
errorFailures that need attention
fatalProcess-ending failures
silentDisable logging

When to Use Which Logger

ScenarioLogger
Production with log aggregationcreatePinoLogger
Local developmentcreateConsoleLogger
TestingcreateConsoleLogger with custom writer
Custom logging systemImplement the Logger interface directly