@telygent/ai-sdk
v0.1.32
Published
Telygent conversational database AI SDK
Downloads
920
Readme
Telygent AI SDK
Client-side SDK to connect your app to Telygent AI. The SDK stores conversation history in your Redis, executes database tools locally, and sends tool results to Telygent for AI reasoning.
Install
npm install @telygent/ai-sdkRequired dependencies
npm install ioredis mongodbUsage
import { TelygentClient, createRedisHistoryStore, createMongoAdapter, type ModelRegistry } from "@telygent/ai-sdk";
import { MongoClient } from "mongodb";
// createRedisHistoryStore reuses a shared client per URL.
const historyStore = createRedisHistoryStore({
url: process.env.REDIS_URL as string,
ttlSeconds: 3600,
});
const mongoClient = new MongoClient(process.env.MONGO_URI as string);
await mongoClient.connect();
const mongoDb = mongoClient.db(process.env.MONGO_DB_NAME as string);
const registry = {
Statute: {
collectionName: "canadian_statutes",
allowedFields: ["title", "shortTitle", "year", "jurisdiction", "topics", "createdAt"],
links: {
list: "/laws/statutes",
detail: "/laws/statutes/{_id}",
allowedQueryParams: ["year", "jurisdiction", "topics", "createdAt"],
queryParamMap: {
year: "year",
jurisdiction: "jurisdiction",
topics: "topic",
createdAt: { gte: "fromDate", lte: "toDate" },
},
allowedQueryValues: {
jurisdiction: ["federal", "provincial"],
},
},
fieldTypes: {
_id: "objectId",
createdAt: "date",
},
requiredFilters: [
{ field: "jurisdiction", contextKey: "jurisdiction", type: "string" }
],
instructions:
"Use jurisdiction filters (federal or provincial) and default to the most recent 5 years when dates are missing.",
},
CaseLaw: {
collectionName: "canadian_cases",
allowedFields: ["title", "citation", "court", "decisionDate", "topics", "summary"],
links: {
list: "/laws/cases",
detail: "/laws/cases/{_id}",
allowedQueryParams: ["court", "decisionDate", "topics"],
queryParamMap: {
court: "court",
decisionDate: { gte: "fromDate", lte: "toDate" },
topics: "topic",
},
},
fieldTypes: {
_id: "objectId",
decisionDate: "date",
},
customServices: [
{
name: "case_search",
description: "Search Canadian case law by title, citation, or topic.",
inputSchema: {
properties: {
query: { type: "string", optional: false, description: "Title, citation, or keyword." },
court: { type: "string", optional: true, description: "e.g., SCC, FCA, ONSC." },
year: { type: "number", optional: true, description: "Decision year filter." },
limit: { type: "number", optional: true, description: "Maximum results to return." }
}
}
},
{
name: "case_summary",
description: "Fetch a short summary for a single case by citation.",
inputSchema: {
properties: {
citation: { type: "string", optional: false, description: "Case citation, e.g. 2018 SCC 10." }
}
}
}
]
},
} satisfies ModelRegistry;
// Multiple custom services:
// - Define each service in `customServices` with a unique name.
// - The AI will call `custom_query` with `service: "<name>"` to select the handler.
// If you don't have Redis yet, omit `historyStore` and the SDK will use empty history.
const dbAdapter = createMongoAdapter({
db: mongoDb,
registry,
});
const client = new TelygentClient({
apiKey: process.env.TELYGENT_API_KEY as string,
aiName: "Atlas",
registry,
historyStore,
dbAdapter,
customServices: {
CaseLaw: {
case_search: async (input) => caseService.search(input),
case_summary: async (input) => caseService.summary(input),
},
},
log: false,
});
const response = await client.query({
question: "Show me federal statutes on privacy passed after 2018",
conversationId: "conv_123",
userContext: {
userId: "user_1",
jurisdiction: "federal",
},
messageContext: "Viewing document id: 3283823883",
});
console.log(response.content);
const messages = await client.getConversationMessages("conv_123");
console.log(messages);Reload conversation history
import { TelygentClient, createRedisHistoryStore, type ModelRegistry } from "@telygent/ai-sdk";
const historyStore = createRedisHistoryStore({
url: process.env.REDIS_URL as string,
});
// Requires Redis. If you don't pass a history store, this returns an empty list.
const client = new TelygentClient({
apiKey: process.env.TELYGENT_API_KEY as string,
aiName: "Atlas",
historyStore,
});
const messages = await client.getConversationMessages("conv_123");
console.log(messages);Redis
Use a single shared Redis client for history. Creating a new client per request can exhaust the Redis
maxclients limit and cause errors. The SDK provides createRedisHistoryStore to reuse a shared
client per URL, or you can pass your own client if you already manage one.
import Redis from "ioredis";
import { createRedisHistoryStore } from "@telygent/ai-sdk";
const redisClient = new Redis(process.env.REDIS_URL as string);
const historyStore = createRedisHistoryStore({ client: redisClient });Notes
- Conversation history lives in your Redis and is sent to Telygent each request.
- Database queries are executed locally through the adapter you provide.
- Registry is static and versioned by hash after initial sync.
- Use
requiredFiltersto inject fixed constraints into queries. - Custom services are optional and let the AI call your own per-model lookup handlers.
- Use
getConversationMessagesto reload message history from Redis. messageContextcan be passed per request to enrich AI reasoning context; it is sent to AI for that turn but not stored as conversation history.messageContextis currently limited to 600 characters; longer values are truncated before sending to AI.
Streaming (SSE)
Use in an Express route to stream events to the browser:
app.post("/stream", async (req, res) => {
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Connection", "keep-alive");
await client.queryStream(req.body, (event) => {
res.write(`data: ${JSON.stringify(event)}\n\n`);
if (event.phase === "final" || event.phase === "error") {
res.end();
}
});
});Use streaming when you want step-by-step updates (planning, tool execution, response). The stream emits
JSON events with a phase field:
thinking: progress updatesfinal: final response payloaderror: terminal error
const response = await client.queryStream(
{
question: "Show me recent transactions",
conversationId: "conv_123",
userContext: { userId: "user_1" },
messageContext: "Viewing transaction detail (transactionId: txn_123)",
},
(event) => {
if (event.phase === "thinking") {
console.log("step:", event.content);
return;
}
if (event.phase === "final") {
console.log("final:", event.content);
}
}
);
console.log("answer:", response.content);Notes:
- Streaming does not replace the existing
query()method. Use either one. - Only
phase: "final"messages are stored in Redis history.
Express middleware
import express from "express";
import { attachAiClient, createRedisHistoryStore, createMongoAdapter } from "@telygent/ai-sdk";
const app = express();
app.use(express.json());
const historyStore = createRedisHistoryStore({
url: process.env.REDIS_URL as string,
});
app.use(
attachAiClient({
apiKey: process.env.TELYGENT_API_KEY as string,
registry,
historyStore,
dbAdapter: createMongoAdapter({ db: mongoDb, registry }),
})
);
app.post("/ask", async (req, res) => {
const { question, conversationId, userContext } = req.body;
const response = await req.aiClient!.query({ question, conversationId, userContext });
res.json(response);
});Mongo History Store
If you want users to resume conversations from your application database, use MongoDB as the history store.
import { createMongoHistoryStore } from "@telygent/ai-sdk";
const historyStore = createMongoHistoryStore({
db: mongoDb,
collectionName: "telygent_conversations", // optional
});Recommended Mongo index:
db.telygent_conversations.createIndex({ conversationId: 1, timestamp: 1 });You can use either Redis or Mongo for historyStore.
