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.
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
| Method | Purpose |
|---|---|
| fetchAIHistory({ senderId }) | List AI conversation history for a user |
| deleteAIHistoryMessage({ senderId, messageId }) | Delete one stored message |
Typical Uses
| Use case | Pattern |
|---|---|
| Support inbox UI | Call fetchAIHistory when a ticket opens |
| GDPR / privacy | Call deleteAIHistoryMessage on a valid user request |
| Debug | Compare stored history with sessionId sessions |
| Audit | Cross-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
| Event | When |
|---|---|
| Session start | Before the AI request is sent |
| Session complete | After the HTTP response returns |
| Token usage | Extracted from the response when available |
| Model | From 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
| Feature | logs: true | saveHistory on sendAI |
|---|---|---|
| Purpose | Operations dashboard and token audit | User-facing conversation storage |
| API | Automatic on sendAI | Read with fetchAIHistory |
| Audience | Developers and support leads | End-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."},
)