Tutorial 18 of 18

How to Enable AI History and Session Logging

Store user-facing AI history, delete individual turns, and enable operational session telemetry in the DNotifier dashboard.

18 min read

This tutorial covers two ways DNotifier records your AI activity: AI history, which stores conversation turns for your product, and session logging, which sends AI session telemetry to the DNotifier dashboard for operations.

Part 1: Enable AI History

When sendAI runs with saveHistory: true, the default, turns are stored server-side. Use fetchAIHistory to list them and deleteAIHistoryMessage to remove individual entries.

Methods

MethodPurpose
fetchAIHistory({ senderId })List AI conversation history for a user
deleteAIHistoryMessage({ senderId, messageId })Delete one stored message

Typical Uses

Use casePattern
Support inbox UICall fetchAIHistory when a ticket opens
GDPR / privacyCall deleteAIHistoryMessage on a valid user request
DebugCompare stored history with sessionId sessions
AuditCross-check with the session logging dashboard

The saveHistory Flag

// Stored (default)
await notifier.sendAI({
  senderId,
  message,
  saveHistory: true,
});

// Ephemeral — routing, classification, workflow internals
await notifier.sendAI({
  senderId,
  message,
  saveHistory: false,
});

Part 2: Enable Session Logging

Set logs: true when constructing DNotifier to send AI session telemetry to the DNotifier dashboard, including session start, completion, model, and token usage when available.

What Gets Logged

EventWhen
Session startBefore the AI request is sent
Session completeAfter the HTTP response returns
Token usageExtracted from the response when available
ModelFrom the sendAI or agent override, otherwise the project default

View recorded sessions under Logs in the DNotifier dashboard.

Enable Logging

Pass logs: true at construction time, rather than on each sendAI call:

const notifier = new DNotifier({
  appId: process.env.DNOTIFIER_APP_ID,
  secret: process.env.DNOTIFIER_SECRET,
  transport: "http",
  userId: "user-123",
  logs: true,
  onConnected: () => {},
  onMessage: () => {},
  onDisconnected: () => {},
});

Logging vs. AI History

Featurelogs: truesaveHistory on sendAI
PurposeOperations dashboard and token auditUser-facing conversation storage
APIAutomatic on sendAIRead with fetchAIHistory
AudienceDevelopers and support leadsEnd-user chat UI

AI History — JavaScript / TypeScript

Fetch and delete stored AI conversation turns over HTTP.

Fetch History

import { DNotifier } from "@dnotifier-realtime/dnotifier";

const USER_ID = "user-123";

const notifier = new DNotifier({
  appId: process.env.DNOTIFIER_APP_ID,
  secret: process.env.DNOTIFIER_SECRET,
  transport: "http",
  userId: USER_ID,
  onConnected: () => {},
  onMessage: () => {},
  onDisconnected: () => {},
});

await notifier.connect();

await notifier.sendAI({
  senderId: USER_ID,
  message: { text: "What is your return policy?" },
  saveHistory: true,
});

const history = await notifier.fetchAIHistory({
  senderId: USER_ID,
});
console.log(history);

Delete a Message

const history = await notifier.fetchAIHistory({
  senderId: USER_ID,
});

const messageId =
  history?.data?.messages?.[0]?.id ??
  "message-id-to-delete";

await notifier.deleteAIHistoryMessage({
  senderId: USER_ID,
  messageId,
});

API Route Pattern

app.get("/api/users/:userId/ai-history", async (req, res) => {
  const history = await notifier.fetchAIHistory({
    senderId: req.params.userId,
  });
  res.json(history);
});

app.delete(
  "/api/users/:userId/ai-history/:messageId",
  async (req, res) => {
    await notifier.deleteAIHistoryMessage({
      senderId: req.params.userId,
      messageId: req.params.messageId,
    });
    res.status(204).end();
  },
);

Skip History for Internal Calls

await notifier.sendAI({
  senderId: USER_ID,
  message: { text: "Classify: urgent or normal" },
  saveHistory: false,
});

AI History — Dart / Flutter

Fetch and delete stored AI conversation turns over HTTP.

Fetch History

import 'package:dnotifier/dnotifier.dart';

const userId = 'user-123';

Future<void> main() async {
  final notifier = DNotifier(
    appId: 'your-app-id',
    secret: 'your-app-secret',
    transport: 'http',
    userId: userId,
    onConnected: () {},
    onMessage: (_) {},
  );

  await notifier.connect();

  await notifier.sendAI(
    senderId: userId,
    message: {'text': 'What is your return policy?'},
    saveHistory: true,
  );

  final history = await notifier.fetchAIHistory(
    senderId: userId,
  );
  print(history);
}

Delete a Message

final history = await notifier.fetchAIHistory(
  senderId: userId,
);

String? messageId;
if (history is Map && history['data'] is Map) {
  final messages = history['data']['messages'];
  if (messages is List && messages.isNotEmpty) {
    final first = messages.first;
    if (first is Map) {
      messageId = first['id']?.toString();
    }
  }
}

if (messageId != null) {
  await notifier.deleteAIHistoryMessage(
    senderId: userId,
    messageId: messageId,
  );
}

Flutter List UI Sketch

Future<List<Map<String, dynamic>>> loadAiHistory(
  DNotifier notifier,
) async {
  final raw = await notifier.fetchAIHistory(
    senderId: userId,
  );
  if (raw is Map && raw['data'] is Map) {
    final messages = raw['data']['messages'];
    if (messages is List) {
      return messages.cast<Map<String, dynamic>>();
    }
  }
  return [];
}

Skip History for Internal Calls

await notifier.sendAI(
  senderId: userId,
  message: {'text': 'Classify: urgent or normal'},
  saveHistory: false,
);

AI History — Python

Fetch and delete stored AI conversation turns over HTTP.

Fetch History

import asyncio
from dnotifier import DNotifier

USER_ID = "user-123"

async def main():
    notifier = DNotifier(
        app_id="your-app-id",
        secret="your-app-secret",
        transport="http",
        user_id=USER_ID,
    )

    await notifier.connect()

    await notifier.send_ai(
        sender_id=USER_ID,
        message={"text": "What is your return policy?"},
        save_history=True,
    )

    history = await notifier.fetch_ai_history(
        sender_id=USER_ID
    )
    print(history)

asyncio.run(main())

Delete a Message

history = await notifier.fetch_ai_history(
    sender_id=USER_ID
)

message_id = None
if (
    isinstance(history, dict)
    and isinstance(history.get("data"), dict)
):
    messages = history["data"].get("messages")
    if isinstance(messages, list) and messages:
        first = messages[0]
        if isinstance(first, dict):
            message_id = first.get("id")

if message_id:
    await notifier.delete_ai_history_message(
        sender_id=USER_ID,
        message_id=str(message_id),
    )

Load History for UI

async def load_ai_history(
    notifier: DNotifier,
) -> list[dict]:
    raw = await notifier.fetch_ai_history(
        sender_id=USER_ID
    )
    if (
        isinstance(raw, dict)
        and isinstance(raw.get("data"), dict)
    ):
        messages = raw["data"].get("messages")
        if isinstance(messages, list):
            return messages
    return []

Skip History for Internal Calls

await notifier.send_ai(
    sender_id=USER_ID,
    message={"text": "Classify: urgent or normal"},
    save_history=False,
)

Session Logging — JavaScript / TypeScript

Enable dashboard AI telemetry with logs: true on the DNotifier constructor.

Complete Example

import { DNotifier } from "@dnotifier-realtime/dnotifier";

const USER_ID = "user-123";

const notifier = new DNotifier({
  appId: process.env.DNOTIFIER_APP_ID,
  secret: process.env.DNOTIFIER_SECRET,
  transport: "http",
  userId: USER_ID,
  logs: true,
  onConnected: () => console.log("Ready — logging enabled"),
  onMessage: () => {},
  onDisconnected: () => {},
});

await notifier.connect();

const response = await notifier.sendAI({
  senderId: USER_ID,
  message: {
    messages: [
      {
        role: "system",
        content: "You are a concise assistant.",
      },
      {
        role: "user",
        content: "Explain session logging in one paragraph.",
      },
    ],
  },
});

console.log(response?.data?.content ?? response);
// Check app.dnotifier.com → Logs for this session.

Production API Service

function createAiNotifier(serviceUserId) {
  return new DNotifier({
    appId: process.env.DNOTIFIER_APP_ID,
    secret: process.env.DNOTIFIER_SECRET,
    transport: "http",
    userId: serviceUserId,
    logs: process.env.NODE_ENV === "production",
    onConnected: () => {},
    onMessage: () => {},
    onDisconnected: () => {},
  });
}

With Session Continuation

const first = await notifier.sendAI({
  senderId: USER_ID,
  message: { text: "Start logged session." },
});

const sessionId =
  first?.metadata?.packet?.id ??
  first?.metadata?.id;

await notifier.sendAI({
  senderId: USER_ID,
  sessionId,
  message: { text: "Follow-up — also logged." },
});

Disable Logging Locally

const notifier = new DNotifier({
  // ...
  logs: process.env.DNOTIFIER_LOGS === "true",
});

Session Logging — Dart / Flutter

Enable dashboard AI telemetry with logs: true on the DNotifier constructor.

Complete Example

import 'package:dnotifier/dnotifier.dart';

const userId = 'user-123';

Future<void> main() async {
  final notifier = DNotifier(
    appId: 'your-app-id',
    secret: 'your-app-secret',
    transport: 'http',
    userId: userId,
    logs: true,
    onConnected: () => print('Ready — logging enabled'),
    onMessage: (_) {},
  );

  await notifier.connect();

  await notifier.sendAI(
    senderId: userId,
    message: {
      'messages': [
        {
          'role': 'system',
          'content': 'You are a concise assistant.',
        },
        {
          'role': 'user',
          'content': 'Explain session logging in one paragraph.',
        },
      ],
    },
  );
  // Check app.dnotifier.com → Logs.
}

Conditional Logging

import 'dart:io';

final enableLogs =
    Platform.environment['DNOTIFIER_LOGS'] == 'true';

final notifier = DNotifier(
  appId: Platform.environment['DNOTIFIER_APP_ID']!,
  secret: Platform.environment['DNOTIFIER_SECRET']!,
  transport: 'http',
  userId: userId,
  logs: enableLogs,
  onConnected: () {},
  onMessage: (_) {},
);

With Session Continuation

final first = await notifier.sendAI(
  senderId: userId,
  message: {'text': 'Start logged session.'},
);

final sessionId = sessionIdFromResponse(first);

await notifier.sendAI(
  senderId: userId,
  sessionId: sessionId,
  message: {'text': 'Follow-up — also logged.'},
);

Session Logging — Python

Enable dashboard AI telemetry with logs=True on the DNotifier constructor.

Complete Example

import asyncio
from dnotifier import DNotifier

USER_ID = "user-123"

async def main():
    notifier = DNotifier(
        app_id="your-app-id",
        secret="your-app-secret",
        transport="http",
        user_id=USER_ID,
        logs=True,
        on_connected=lambda: print(
            "Ready — logging enabled"
        ),
    )

    await notifier.connect()

    await notifier.send_ai(
        sender_id=USER_ID,
        message={
            "messages": [
                {
                    "role": "system",
                    "content": "You are a concise assistant.",
                },
                {
                    "role": "user",
                    "content": (
                        "Explain session logging "
                        "in one paragraph."
                    ),
                },
            ],
        },
    )
    # Check app.dnotifier.com → Logs.

asyncio.run(main())

Conditional Logging

import os

enable_logs = os.environ.get("DNOTIFIER_LOGS") == "true"

notifier = DNotifier(
    app_id=os.environ["DNOTIFIER_APP_ID"],
    secret=os.environ["DNOTIFIER_SECRET"],
    transport="http",
    user_id=USER_ID,
    logs=enable_logs,
)

With Session Continuation

first = await notifier.send_ai(
    sender_id=USER_ID,
    message={"text": "Start logged session."},
)

session_id = session_id_from_response(first)

await notifier.send_ai(
    sender_id=USER_ID,
    session_id=session_id,
    message={"text": "Follow-up — also logged."},
)