Blyp Docs

Better Agent

Use @blyp/core/ai/better-agent when your app uses Better Agent and you want Blyp to emit one normalized run-level ai_trace record per Better Agent run.

This integration has two surfaces:

Better Agent runs can span multiple model calls and tool steps. Blyp aggregates those steps into one final trace for the run. It does not emit one trace per model step.

Install

Install Blyp and Better Agent in the app that runs the traced Better Agent runtime:

bun add @blyp/core @better-agent/core

Better Agent support lives in the @blyp/core/ai/better-agent entrypoint.

@better-agent/core is an optional peer dependency of @blyp/core, but it is required when you use this integration.

Quick start

Register the Blyp plugin in the Better Agent app plugins array:

import { betterAgent } from "@better-agent/core";
import { blypPlugin } from "@blyp/core/ai/better-agent";

declare const supportAgent: unknown;

export const app = betterAgent({
  agents: [supportAgent],
  plugins: [
    blypPlugin({
      operation: "support_chat",
      metadata: {
        service: "api",
        team: "support",
      },
      capture: {
        input: true,
        output: true,
        toolInputs: true,
        toolOutputs: true,
      },
    }),
  ],
});

With that plugin installed, Better Agent run events and model responses are aggregated into one Blyp ai_trace with provider, model, operation, timing, usage, and optional captured content.

Public API

@blyp/core/ai/better-agent exports:

import {
  blypPlugin,
  createBetterAgentTracker,
  type BlypBetterAgentOptions,
  type BlypBetterAgentRunResolver,
  type BlypBetterAgentTracker,
} from "@blyp/core/ai/better-agent";

blypPlugin(options?)

import type { Plugin } from "@better-agent/core";
import type { BlypBetterAgentOptions } from "@blyp/core/ai/better-agent";

declare function blypPlugin(options?: BlypBetterAgentOptions): Plugin;

Use this when you can register a Better Agent plugin at the app level. This is the preferred path because the Better Agent runtime will call both onEvent and onAfterModelCall for you.

createBetterAgentTracker(options?)

import type { BlypBetterAgentOptions, BlypBetterAgentTracker } from "@blyp/core/ai/better-agent";

declare function createBetterAgentTracker(
  options?: BlypBetterAgentOptions
): BlypBetterAgentTracker;

Use this when plugin registration is not possible and you need to forward Better Agent events and model responses manually.

BlypBetterAgentTracker

import type { Event } from "@better-agent/core/events";
import type { GenerativeModelResponse } from "@better-agent/core/providers";

type BlypBetterAgentTracker = {
  onEvent(event: Event): Promise<void>;
  onAfterModelCall(
    response: GenerativeModelResponse,
    info?: { stepIndex?: number }
  ): Promise<void>;
};

One tracker instance handles one Better Agent run.

BlypBetterAgentOptions

BlypBetterAgentOptions builds on Blyp’s shared AI tracing options. It inherits capture, exclude, limits, and hooks from Blyp’s provider-level tracing config, then adds Better Agent-specific run resolution.

Conceptually:

type BlypBetterAgentOptions =
  Omit<BlypProviderOptions, "provider" | "operation" | "metadata"> & {
    provider?: string;
    operation?: string;
    metadata?: Record<string, unknown>;
    resolveRun?: BlypBetterAgentRunResolver;
  };

BlypBetterAgentRunResolver

type BlypBetterAgentRunResolver = (ctx: {
  runId: string;
  agentName: string;
  conversationId?: string;
}) =>
  | {
      provider?: string;
      model?: string;
      operation?: string;
      method?: string;
      metadata?: Record<string, unknown>;
      streamed?: boolean;
    }
  | Promise<
      | {
          provider?: string;
          model?: string;
          operation?: string;
          method?: string;
          metadata?: Record<string, unknown>;
          streamed?: boolean;
        }
      | undefined
    >
  | undefined;

The resolver runs once at RUN_STARTED time and lets you override provider/model/operation metadata for that run.

Option reference

Better Agent-specific top-level options

model and method are not top-level BlypBetterAgentOptions fields. If you need to override them, do it in resolveRun().

resolveRun() input

resolveRun() receives:

It can return overrides for:

Resolver metadata is merged on top of top-level metadata. Blyp then appends built-in run metadata such as agentName, runId, conversationId, and final stepCount.

Inherited Blyp AI tracing options

The Better Agent integration inherits these Blyp AI tracing options:

capture

Supported capture flags:

streamEvents and streamChunks are normalized together by Blyp’s shared AI tracing config. Enabling either enables the same ai.chunk event capture path.

exclude

Supported exclude flags:

exclude.providerOptions is inherited from shared Blyp AI tracing, but it has no practical effect for Better Agent traces because this integration does not serialize providerOptions.

limits

Supported limits:

hooks

Supported hooks:

These are Blyp tracing hooks, not Better Agent runtime hooks. For example, hooks.onEvent receives normalized Blyp trace events such as ai.start, ai.chunk, and ai.finish.

Behavior and trace model

The Better Agent integration emits one normalized Blyp ai_trace per Better Agent run.

Key behavior:

Conceptually, the final record looks like:

Defaults

Default behavior is intentionally conservative:

Resolver example

Use resolveRun() when you want Better Agent run traces to carry richer provider/model identity than the Better Agent plugin hook context exposes directly:

import { blypPlugin } from "@blyp/core/ai/better-agent";

const plugin = blypPlugin({
  resolveRun({ agentName, runId, conversationId }) {
    if (agentName === "support-agent") {
      return {
        provider: "openai",
        model: "gpt-5",
        operation: "support_chat",
        metadata: {
          runId,
          conversationId,
          route: "support",
        },
      };
    }

    return {
      provider: "better-agent",
      model: agentName,
      operation: `better-agent:${agentName}`,
    };
  },
});

void plugin;

Why this matters:

Manual tracker

createBetterAgentTracker() is the fallback path when you cannot register blypPlugin() at the Better Agent app level.

Rules for manual use:

Example:

import type { RunFinishedEvent, RunStartedEvent } from "@better-agent/core/events";
import type { GenerativeModelResponse } from "@better-agent/core/providers";
import { createBetterAgentTracker } from "@blyp/core/ai/better-agent";

const tracker = createBetterAgentTracker({
  capture: {
    output: true,
    rawProviderPayload: true,
  },
});

const runStartedEvent: RunStartedEvent = {
  type: "RUN_STARTED",
  timestamp: Date.now(),
  runId: "run_1",
  agentName: "support-agent",
  conversationId: "conv_1",
  runInput: { input: "Where is my order?" },
};

const modelResponse: GenerativeModelResponse = {
  output: [
    {
      type: "message",
      role: "assistant",
      content: [{ type: "text", text: "I found your order." }],
    },
  ],
  finishReason: "stop",
  usage: {
    inputTokens: 10,
    outputTokens: 6,
    totalTokens: 16,
  },
  request: {
    body: { step: 0 },
  },
  response: {
    body: { id: "resp_1" },
  },
};

const runFinishedEvent: RunFinishedEvent = {
  type: "RUN_FINISHED",
  timestamp: Date.now(),
  runId: "run_1",
  agentName: "support-agent",
  conversationId: "conv_1",
  result: {
    response: modelResponse,
  },
};

await tracker.onEvent(runStartedEvent);
await tracker.onAfterModelCall(modelResponse, { stepIndex: 0 });
await tracker.onEvent(runFinishedEvent);

Important limitation:

Without onAfterModelCall(), the tracker can still emit a trace from runtime events and the terminal Better Agent response, but aggregated usage and raw provider payload capture will be incomplete. In that case Blyp falls back to final-response-only usage and payload fidelity.

Event mapping

This is how Better Agent runtime events map into Blyp tracing:

Privacy and capture

Better Agent tracing uses the same Blyp privacy model as the other AI integrations.

Important points:

For the shared privacy controls, see AI Privacy & Capture.

Limitations

Comparison to other Blyp AI integrations

The Better Agent integration sits at a different layer than Blyp’s other AI entrypoints:

That difference matters for trace shape. Better Agent emits one run-level summary trace for the whole agent run, not one provider-call trace per step.

Additional examples

Capture-heavy debugging

Use aggressive capture when you need to inspect the full run shape during debugging:

import { blypPlugin } from "@blyp/core/ai/better-agent";

const plugin = blypPlugin({
  operation: "support_debug",
  capture: {
    input: true,
    output: true,
    reasoning: true,
    toolInputs: true,
    toolOutputs: true,
    streamEvents: true,
    rawProviderPayload: true,
  },
  limits: {
    maxContentBytes: 32_768,
    maxEvents: 500,
    maxToolCalls: 100,
  },
});

void plugin;

Conservative production capture

Use a resolver and minimal capture when you want low-risk production tracing:

import { blypPlugin } from "@blyp/core/ai/better-agent";

const plugin = blypPlugin({
  resolveRun({ agentName }) {
    return {
      provider: "openai",
      model: agentName === "support-agent" ? "gpt-5" : agentName,
      operation: `agent:${agentName}`,
    };
  },
  capture: {
    input: false,
    output: false,
    toolInputs: false,
    toolOutputs: false,
    reasoning: false,
    rawProviderPayload: false,
  },
  exclude: {
    metadataPaths: ["tenant.secret"],
    toolNames: ["internalAdminTool"],
  },
});

void plugin;