Graphlit TypeScript Client SDK

The official TypeScript/JavaScript SDK for the Graphlit Platform - build AI-powered applications with knowledge retrieval in minutes.
š What is Graphlit?
Graphlit is a cloud platform that handles the complex parts of building AI applications:
- Ingest any content - PDFs, websites, audio, video, and more
- Chat with your data - Using RAG (Retrieval-Augmented Generation)
- Extract insights - Summaries, entities, and metadata
- Build knowledge graphs - Automatically connect related information
What's New
OpenAI Responses API Support
- Automatic Responses API Routing - GPT-5.4 and eligible OpenAI models are automatically routed through the OpenAI Responses API for improved intelligence, fewer reasoning tokens, higher cache hit rates, and lower latency. Disable with
useResponsesApi: false in StreamAgentOptions.
- Reasoning Effort - Reasoning effort (e.g.
medium, high) is read from the specification's openAI.reasoningEffort field and passed through to the Responses API.
- GPT-5.4 Temperature Handling - Temperature is only sent when reasoning effort is
none (the GPT-5.4 default). Other reasoning levels don't support temperature per the OpenAI docs.
phase on Assistant Messages - Conversation history replayed to the Responses API includes phase: "commentary" on assistant messages that preceded tool calls, and phase: "final_answer" on terminal messages, per GPT-5.4 best practices.
- Tool Call ID Remapping - Tool call IDs are automatically remapped between
call_ (Chat Completions) and fc_ (Responses API) formats, enabling mid-conversation model switches without errors.
- First-Round Tool Engagement - When tools are provided, the SDK sends
tool_choice: "required" on the first API request to ensure the model engages with available tools, then reverts to auto for subsequent rounds. This addresses GPT-5.4's tendency to skip tool use under the default auto setting. This behavior is internal to the Responses API path and not exposed as a caller option.
Streaming Provider Resilience
- Automatic Retry for Provider Errors -
streamAgent and runAgent now retry transient LLM provider errors (HTTP 500, 503, 429, network failures) with exponential backoff (up to 3 retries)
ProviderError Class - Normalized, typed error class across all 10 streaming providers with provider, statusCode, retryable, and requestId fields
- Structured
recoverable Flag - Error events now accurately indicate whether an error is transient, enabling smarter application-level retry logic
- No More Duplicate Error Events - Fixed providers that were emitting both an error event and throwing, causing duplicate error handling
v1.6.0 - Agent Framework
- Agent Entity - First-class agent lifecycle management
runAgent() Method - Autonomous agent harness with built-in stuck detection and turn evaluation
- Skills API - Define and manage reusable agent skills
- Agent Scratchpad - Persistent scratchpad for agents and conversations
- Optimized Reasoning Streaming - More efficient streaming of reasoning/thinking updates
- Node.js 20+ Required - Minimum Node.js version bumped from 18 to 20
v1.5.0 - Streaming & Context Management šļø
- Context Management - Token windowing for
streamAgent and promptAgent to handle large conversations
- Artifact Collection - Collect and track artifacts generated during agent streaming
- Conversation Queueing - Queue multiple prompts in
streamAgent for sequential processing
- Thinking Storage - LLM thinking/reasoning responses now tracked and stored across turns
- Better Abort Handling - Improved cancellation cleanup in
streamAgent
- Partial Error Responses - Graceful degradation when API returns partial data with errors
- BREAKING: Renamed
distributeContents() to distribute()
v1.4.0 - Knowledge Graph & Platform Enhancements š
- Knowledge Graph Queries - New
queryGraph and queryFactsGraph methods for graph traversal
- Expanded Entity Queries - Richer entity detail retrieval with
lookupEntity and expanded query variants
- Conversation Clusters - Group and query related conversations
- Optional dotenv -
dotenv is no longer a required dependency
- Partial Error Handling - SDK now surfaces partial data instead of throwing on mixed responses
- JSDoc Documentation - Client methods now include inline documentation
v1.3.0 - Google SDK Migration š
- BREAKING CHANGE: Migrated from deprecated
@google/generative-ai to new @google/genai SDK
- Improved Thinking Support - Better detection of Google Gemini thinking/reasoning with proper
part.thought API
- Enhanced Streaming - More reliable streaming with the new Google SDK
- Migration Required - See Migration Guide below
v1.2.0 - Reasoning & Cancellation Support š§
- Reasoning/Thinking Detection - See how AI models think through problems (Bedrock Nova, Deepseek, Anthropic)
- Stream Cancellation - Stop long-running generations instantly with AbortSignal support
- Enhanced Streaming Events - New
reasoning_update events expose model thought processes
v1.1.0 - Streaming & Resilience
- Real-time streaming - Watch AI responses appear word-by-word across 9 different providers
- Tool calling - Let AI execute functions and retrieve data
- Extended provider support - Native streaming integration with OpenAI, Anthropic, Google, Groq, Cerebras, Cohere, Mistral, AWS Bedrock, and Deepseek
- Better performance - Optimized streaming with provider-specific SDKs
- Network resilience - Automatic retry logic for transient failures
š Table of Contents
Quick Start
Get started in 2 minutes:
npm install graphlit-client
export GRAPHLIT_ORGANIZATION_ID=your_org_id
export GRAPHLIT_ENVIRONMENT_ID=your_env_id
export GRAPHLIT_JWT_SECRET=your_secret
import { Graphlit, Types } from "graphlit-client";
const client = new Graphlit();
const spec = await client.createSpecification({
name: "Assistant",
type: Types.SpecificationTypes.Completion,
serviceType: Types.ModelServiceTypes.OpenAi,
openAI: {
model: Types.OpenAiModels.Gpt4O_128K,
},
});
await client.streamAgent(
"Tell me a joke",
(event) => {
if (event.type === "message_update") {
console.log(event.message.message);
}
},
undefined,
{ id: spec.createSpecification.id },
);
Installation
npm install graphlit-client
Want Real-time Streaming?
Install the LLM SDK for streaming responses:
npm install openai
npm install @anthropic-ai/sdk
npm install @google/genai
npm install groq-sdk
npm install openai
npm install cohere-ai
npm install @mistralai/mistralai
npm install @aws-sdk/client-bedrock-runtime
npm install openai
Setting Up
Create a .env file in your project:
GRAPHLIT_ORGANIZATION_ID=your_org_id
GRAPHLIT_ENVIRONMENT_ID=your_env_id
GRAPHLIT_JWT_SECRET=your_secret
# Optional: For streaming with specific providers
OPENAI_API_KEY=your_key
ANTHROPIC_API_KEY=your_key
GOOGLE_API_KEY=your_key
# Additional streaming providers
GROQ_API_KEY=your_key # For Groq models (Llama, Mixtral)
CEREBRAS_API_KEY=your_key # For Cerebras models
COHERE_API_KEY=your_key # For Cohere Command models
MISTRAL_API_KEY=your_key # For Mistral models
DEEPSEEK_API_KEY=your_key # For Deepseek models
# For AWS Bedrock streaming (requires AWS credentials)
AWS_REGION=us-east-2
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secret
Migrating from @google/generative-ai
ā ļø Breaking Change in v1.3.0
The deprecated @google/generative-ai SDK has been replaced with the new @google/genai SDK. This change provides better thinking/reasoning support and improved streaming reliability.
Migration Steps
- Update your dependencies:
npm uninstall @google/generative-ai
npm install @google/genai
- Update your client initialization:
import { GoogleGenerativeAI } from "@google/generative-ai";
const googleClient = new GoogleGenerativeAI(apiKey);
client.setGoogleClient(googleClient);
import { GoogleGenAI } from "@google/genai";
const googleClient = new GoogleGenAI({ apiKey });
client.setGoogleClient(googleClient);
- No other code changes required!
- The Graphlit SDK handles all the API differences internally
- Your existing specifications and conversations will continue to work
- Thinking/reasoning detection is now more reliable with proper
part.thought support
Why the Migration?
- The
@google/generative-ai SDK is deprecated by Google
- New SDK provides better support for Gemini 2.x features including thinking mode
- Improved streaming performance and reliability
- Proper detection of thought parts without markdown parsing hacks
Benefits
- Better Thinking Detection: Properly detects and separates thinking content using Google's official API
- Improved Performance: More efficient streaming with the new SDK architecture
- Future-Proof: Ensures compatibility with upcoming Gemini models and features
- Cleaner API: Simplified configuration and better TypeScript types
Reasoning Support (New!) š§
The SDK can detect and expose AI reasoning processes, showing you how models "think" through problems. This feature works with models that support reasoning output.
Quick Example
await client.streamAgent(
"What's 15% of 240? Think step by step.",
(event) => {
if (event.type === "reasoning_update") {
console.log("š¤ Model thinking:", event.content);
} else if (event.type === "message_update") {
console.log("š¬ Answer:", event.message.message);
}
},
undefined,
{ id: specificationId },
);
Supported Models
| AWS Bedrock | Nova Premier | thinking_tag | <thinking>Let me calculate...</thinking> |
| Deepseek | Chat, Reasoner | markdown | **Step 1:** First, I need to... |
| Anthropic | Claude (with special access) | thinking_tag | Internal thinking blocks |
Using Reasoning Detection
const spec = await client.createSpecification({
name: "Reasoning Assistant",
serviceType: Types.ModelServiceTypes.Bedrock,
bedrock: {
model: Types.BedrockModels.NovaPremier,
temperature: 0.7,
},
});
const reasoningSteps: string[] = [];
await client.streamAgent(
"Analyze the pros and cons of remote work. Think carefully.",
(event) => {
switch (event.type) {
case "reasoning_update":
reasoningSteps.push(event.content);
console.log(`š§ Thinking (${event.format}):`, event.content);
if (event.isComplete) {
console.log("ā
Reasoning complete!");
}
break;
case "message_update":
console.log("Answer:", event.message.message);
break;
}
},
undefined,
{ id: spec.createSpecification!.id },
);
Key Features
- Automatic Detection: Reasoning content is automatically detected and separated
- Format Preservation: Maintains original formatting (markdown, tags, etc.)
- Real-time Streaming: Reasoning streams as it's generated
- Clean Separation: Final answers don't include thinking content
Stream Cancellation (New!) š
Cancel long-running AI generations instantly using the standard Web API AbortController.
Quick Example
const controller = new AbortController();
document.getElementById("stop").onclick = () => controller.abort();
try {
await client.streamAgent(
"Write a 10,000 word essay about quantum computing...",
(event) => {
if (event.type === "message_update") {
console.log(event.message.message);
}
},
undefined,
{ id: specificationId },
undefined,
undefined,
{ abortSignal: controller.signal },
);
} catch (error) {
if (controller.signal.aborted) {
console.log("ā Generation stopped by user");
}
}
Advanced Cancellation
const controller = new AbortController();
setTimeout(() => controller.abort(), 30000);
const controller = new AbortController();
const streams = [
client.streamAgent("Query 1", handler1, undefined, spec1, null, null, {
abortSignal: controller.signal,
}),
client.streamAgent("Query 2", handler2, undefined, spec2, null, null, {
abortSignal: controller.signal,
}),
client.streamAgent("Query 3", handler3, undefined, spec3, null, null, {
abortSignal: controller.signal,
}),
];
controller.abort();
await Promise.allSettled(streams);
Features
- Instant Response: Cancellation happens immediately
- Provider Support: Works with all streaming providers
- Tool Interruption: Stops tool execution between rounds
- Clean Cleanup: Resources are properly released
Network Resilience
The SDK includes automatic retry logic for network errors and transient failures:
Default Retry Configuration
By default, the client will automatically retry on these status codes:
429 - Too Many Requests
500 - Internal Server Error
502 - Bad Gateway
503 - Service Unavailable
504 - Gateway Timeout
const client = new Graphlit();
Custom Retry Configuration
Configure retry behavior to match your needs:
const client = new Graphlit({
organizationId: "your_org_id",
environmentId: "your_env_id",
jwtSecret: "your_secret",
retryConfig: {
maxAttempts: 10,
initialDelay: 500,
maxDelay: 60000,
jitter: true,
retryableStatusCodes: [429, 500, 502, 503, 504],
onRetry: (attempt, error, operation) => {
console.log(`Retry attempt ${attempt} for ${operation.operationName}`);
console.log(`Error: ${error.message}`);
},
},
});
Update Retry Configuration at Runtime
Change retry behavior on the fly:
const client = new Graphlit();
client.setRetryConfig({
maxAttempts: 20,
initialDelay: 100,
retryableStatusCodes: [429, 500, 502, 503, 504, 521, 522, 524],
});
Disable Retries
For testing or specific scenarios:
const client = new Graphlit({
organizationId: "your_org_id",
environmentId: "your_env_id",
jwtSecret: "your_secret",
retryConfig: {
maxAttempts: 1,
},
});
Streaming Error Handling
When using streamAgent or runAgent, LLM provider calls (Anthropic, OpenAI, Google, etc.) can fail with transient errors such as HTTP 500, 503, rate limits, or network issues. The SDK handles these automatically and exposes structured error information to your application.
Automatic Retry for Provider Errors
The SDK automatically retries transient provider errors with exponential backoff:
- HTTP 5xx (Internal Server Error, Bad Gateway, Service Unavailable, Gateway Timeout)
- HTTP 429 (Rate Limit / Overloaded)
- Network errors (connection reset, timeout, DNS failures)
By default, each provider call is retried up to 3 times with exponential backoff (1s, 2s, 4s) plus jitter. If a retry succeeds, the stream continues transparently. If all retries are exhausted, the error is surfaced to your application.
Handling Errors in streamAgent
The error event includes a recoverable flag that tells you whether the failure is transient:
await client.streamAgent(prompt, (event) => {
if (event.type === "error") {
const { message, recoverable } = event.error;
if (recoverable) {
console.warn(`Transient error: ${message}. Consider retrying.`);
} else {
console.error(`Permanent error: ${message}`);
}
}
});
Using ProviderError for Advanced Handling
For more granular control, catch the thrown error and inspect ProviderError:
import { Graphlit, ProviderError } from "graphlit-client";
try {
await client.streamAgent(prompt, onEvent, conversationId, spec);
} catch (error) {
if (error instanceof ProviderError) {
console.log(error.provider);
console.log(error.statusCode);
console.log(error.retryable);
console.log(error.requestId);
}
}
Error Handling in promptAgent
The promptAgent method returns errors in the result object instead of throwing:
const result = await client.promptAgent(prompt, conversationId, spec);
if (result.error) {
if (result.error.recoverable) {
console.warn(`Transient: ${result.error.message}`);
} else {
console.error(`Error: ${result.error.message}`);
}
}
Streaming Provider Support
The Graphlit SDK supports real-time streaming responses from 9 different LLM providers. Each provider requires its specific SDK and API key:
Supported Providers
| OpenAI | GPT-5.4, GPT-4.1, GPT-4o, O1, O3, O4 | openai | OPENAI_API_KEY |
| Anthropic | Claude 3, Claude 3.5, Claude 3.7, Claude 4 | @anthropic-ai/sdk | ANTHROPIC_API_KEY |
| Google | Gemini 1.5, Gemini 2.0, Gemini 2.5 | @google/genai | GOOGLE_API_KEY |
| Groq | Llama 4, Llama 3.3, Mixtral, Deepseek R1 | groq-sdk | GROQ_API_KEY |
| Cerebras | Llama 3.3, Llama 3.1 | openai | CEREBRAS_API_KEY |
| Cohere | Command R+, Command R, Command R7B, Command A | cohere-ai | COHERE_API_KEY |
| Mistral | Mistral Large, Medium, Small, Nemo, Pixtral | @mistralai/mistralai | MISTRAL_API_KEY |
| AWS Bedrock | Nova Premier/Pro, Claude 3.7, Llama 4 | @aws-sdk/client-bedrock-runtime | AWS credentials |
| Deepseek | Deepseek Chat, Deepseek Reasoner | openai | DEEPSEEK_API_KEY |
Setting Up Streaming
Each provider requires both the SDK installation and proper client setup:
import { Graphlit } from "graphlit-client";
const client = new Graphlit();
if (process.env.OPENAI_API_KEY) {
const { OpenAI } = await import("openai");
client.setOpenAIClient(new OpenAI());
}
if (process.env.COHERE_API_KEY) {
const { CohereClientV2 } = await import("cohere-ai");
client.setCohereClient(
new CohereClientV2({ token: process.env.COHERE_API_KEY }),
);
}
if (process.env.GROQ_API_KEY) {
const { Groq } = await import("groq-sdk");
client.setGroqClient(new Groq({ apiKey: process.env.GROQ_API_KEY }));
}
const spec = await client.createSpecification({
name: "Multi-Provider Assistant",
type: Types.SpecificationTypes.Completion,
serviceType: Types.ModelServiceTypes.Cohere,
cohere: {
model: Types.CohereModels.CommandRPlus,
temperature: 0.7,
},
});
Provider-Specific Notes
- OpenAI GPT-5.4: Automatically uses the Responses API for chain-of-thought passback, 1M context, and improved tool calling. The SDK sends
tool_choice: "required" on the first round when tools are provided, then auto on subsequent rounds. Set useResponsesApi: false in options to force legacy Chat Completions.
- OpenAI-Compatible: Groq, Cerebras, Deepseek, and xAI use OpenAI-compatible APIs
- AWS Bedrock: Requires AWS credentials and uses the Converse API for streaming
- Cohere: Supports both chat and tool calling with Command models
- Google: Includes advanced multimodal capabilities with Gemini models
- Mistral: Supports both text and vision models (Pixtral)
Basic Examples
1. Chat with AI
Simple conversation with streaming responses:
import { Graphlit, Types } from "graphlit-client";
const client = new Graphlit();
const spec = await client.createSpecification({
name: "Assistant",
type: Types.SpecificationTypes.Completion,
serviceType: Types.ModelServiceTypes.OpenAi,
openAI: {
model: Types.OpenAiModels.Gpt4O_128K,
temperature: 0.7,
},
});
await client.streamAgent(
"What can you help me with?",
(event) => {
if (event.type === "message_update") {
process.stdout.write(event.message.message);
}
},
undefined,
{ id: spec.createSpecification.id },
);
2. Ingest and Query Documents
Upload a PDF and ask questions about it:
import { Graphlit, Types } from "graphlit-client";
const client = new Graphlit();
const spec = await client.createSpecification({
name: "Document Q&A",
type: Types.SpecificationTypes.Completion,
serviceType: Types.ModelServiceTypes.OpenAi,
openAI: {
model: Types.OpenAiModels.Gpt4O_128K,
},
});
const content = await client.ingestUri(
"https://arxiv.org/pdf/1706.03762.pdf",
"AI Research Paper",
undefined,
true,
);
console.log(`ā
Uploaded: ${content.ingestUri.id}`);
await new Promise((resolve) => setTimeout(resolve, 5000));
const conversation = await client.createConversation({
filter: { contents: [{ id: content.ingestUri.id }] },
});
await client.streamAgent(
"What are the key innovations in this paper?",
(event) => {
if (event.type === "message_update") {
console.log(event.message.message);
}
},
conversation.createConversation.id,
{ id: spec.createSpecification.id },
);
3. Web Scraping
Extract content from websites:
const webpage = await client.ingestUri(
"https://en.wikipedia.org/wiki/Artificial_intelligence",
"AI Wikipedia Page",
undefined,
true,
);
await new Promise((resolve) => setTimeout(resolve, 5000));
const conversation = await client.createConversation({
filter: { contents: [{ id: webpage.ingestUri.id }] },
});
const response = await client.promptAgent(
"Summarize the key points about AI from this Wikipedia page",
conversation.createConversation.id,
{ id: spec.createSpecification.id },
);
console.log(response.message);
4. Multiple Provider Streaming
Compare responses from different LLM providers:
import { Graphlit, Types } from "graphlit-client";
const client = new Graphlit();
if (process.env.OPENAI_API_KEY) {
const { OpenAI } = await import("openai");
client.setOpenAIClient(new OpenAI());
}
if (process.env.COHERE_API_KEY) {
const { CohereClientV2 } = await import("cohere-ai");
client.setCohereClient(
new CohereClientV2({ token: process.env.COHERE_API_KEY }),
);
}
if (process.env.GROQ_API_KEY) {
const { Groq } = await import("groq-sdk");
client.setGroqClient(new Groq({ apiKey: process.env.GROQ_API_KEY }));
}
const providers = [
{
name: "OpenAI GPT-4o",
serviceType: Types.ModelServiceTypes.OpenAi,
openAI: { model: Types.OpenAiModels.Gpt4O_128K },
},
{
name: "Cohere Command R+",
serviceType: Types.ModelServiceTypes.Cohere,
cohere: { model: Types.CohereModels.CommandRPlus },
},
{
name: "Groq Llama",
serviceType: Types.ModelServiceTypes.Groq,
groq: { model: Types.GroqModels.Llama_3_3_70B },
},
];
for (const provider of providers) {
console.log(`\nš¤ ${provider.name}:`);
const spec = await client.createSpecification({
...provider,
type: Types.SpecificationTypes.Completion,
});
await client.streamAgent(
"Explain quantum computing in simple terms",
(event) => {
if (event.type === "message_update") {
process.stdout.write(event.message.message);
}
},
undefined,
{ id: spec.createSpecification.id },
);
}
5. Reasoning + Cancellation Example
Combine reasoning detection with cancellable streams:
import { Graphlit, Types } from "graphlit-client";
const client = new Graphlit();
const controller = new AbortController();
const spec = await client.createSpecification({
name: "Reasoning Demo",
serviceType: Types.ModelServiceTypes.Bedrock,
bedrock: {
model: Types.BedrockModels.NovaPremier,
},
});
const stopButton = document.getElementById("stop-reasoning");
const reasoningDiv = document.getElementById("reasoning");
const answerDiv = document.getElementById("answer");
stopButton.onclick = () => {
controller.abort();
console.log("š Cancelled!");
};
try {
await client.streamAgent(
"Solve this puzzle: If it takes 5 machines 5 minutes to make 5 widgets, how long does it take 100 machines to make 100 widgets? Think through this step-by-step.",
(event) => {
switch (event.type) {
case "reasoning_update":
reasoningDiv.textContent = event.content;
if (event.isComplete) {
reasoningDiv.classList.add("complete");
}
break;
case "message_update":
answerDiv.textContent = event.message.message;
break;
case "conversation_completed":
stopButton.disabled = true;
console.log("ā
Complete!");
break;
}
},
undefined,
{ id: spec.createSpecification!.id },
undefined,
undefined,
{ abortSignal: controller.signal },
);
} catch (error) {
if (controller.signal.aborted) {
console.log("Reasoning cancelled by user");
}
}
6. Tool Calling
Let AI call functions to get real-time data:
import { Graphlit, Types } from "graphlit-client";
const client = new Graphlit();
const weatherTool: Types.ToolDefinitionInput = {
name: "get_weather",
description: "Get current weather for a city",
schema: JSON.stringify({
type: "object",
properties: {
city: { type: "string", description: "City name" },
},
required: ["city"],
}),
};
const toolHandlers = {
get_weather: async (args: { city: string }) => {
return {
city: args.city,
temperature: 72,
condition: "sunny",
};
},
};
const spec = await client.createSpecification({
name: "Weather Assistant",
type: Types.SpecificationTypes.Completion,
serviceType: Types.ModelServiceTypes.OpenAi,
openAI: {
model: Types.OpenAiModels.Gpt4O_128K,
},
});
await client.streamAgent(
"What's the weather in San Francisco?",
(event) => {
if (event.type === "tool_update" && event.status === "completed") {
console.log(`š§ Called ${event.toolCall.name}`);
} else if (event.type === "message_update") {
console.log(event.message.message);
}
},
undefined,
{ id: spec.createSpecification.id },
[weatherTool],
toolHandlers,
);
Common Use Cases
Build a Knowledge Base Assistant
Create an AI that answers questions from your documents:
import { Graphlit, Types } from "graphlit-client";
class KnowledgeAssistant {
private client: Graphlit;
private conversationId?: string;
private specificationId?: string;
private contentIds: string[] = [];
constructor() {
this.client = new Graphlit();
}
async initialize() {
const spec = await this.client.createSpecification({
name: "Knowledge Assistant",
type: Types.SpecificationTypes.Completion,
serviceType: Types.ModelServiceTypes.OpenAi,
openAI: {
model: Types.OpenAiModels.Gpt4O_128K,
temperature: 0.7,
},
});
this.specificationId = spec.createSpecification?.id;
}
async uploadDocuments(urls: string[]) {
console.log("š Uploading documents...");
for (const url of urls) {
const content = await this.client.ingestUri(
url,
url.split("/").pop() || "Document",
undefined,
true,
);
this.contentIds.push(content.ingestUri.id);
}
console.log("ā
Documents uploaded!");
await new Promise((resolve) => setTimeout(resolve, 5000));
}
async ask(question: string) {
if (!this.conversationId && this.contentIds.length > 0) {
const conversation = await this.client.createConversation({
filter: { contents: this.contentIds.map((id) => ({ id })) },
});
this.conversationId = conversation.createConversation?.id;
}
await this.client.streamAgent(
question,
(event) => {
if (event.type === "conversation_started" && !this.conversationId) {
this.conversationId = event.conversationId;
} else if (event.type === "message_update") {
process.stdout.write(event.message.message);
}
},
this.conversationId,
{ id: this.specificationId! },
);
}
}
const assistant = new KnowledgeAssistant();
await assistant.initialize();
await assistant.uploadDocuments([
"https://arxiv.org/pdf/2103.15348.pdf",
"https://arxiv.org/pdf/1706.03762.pdf",
]);
await assistant.ask("What are these papers about?");
await assistant.ask("How do they relate to each other?");
Extract specific information from uploaded content:
const document = await client.ingestUri(
"https://example.com/document.pdf",
"Document #12345",
undefined,
true,
);
await new Promise((resolve) => setTimeout(resolve, 5000));
const extraction = await client.extractContents(
"Extract the key information from this document",
undefined,
undefined,
{ contents: [{ id: document.ingestUri.id }] },
);
console.log("Extracted data:", extraction.extractContents);
Summarize Multiple Documents
Create summaries across multiple files:
const ids: string[] = [];
for (const url of documentUrls) {
const content = await client.ingestUri(
url,
url.split("/").pop() || "Document",
undefined,
true,
);
ids.push(content.ingestUri.id);
}
const summary = await client.summarizeContents(
[
{
type: Types.SummarizationTypes.Custom,
prompt: "Create an executive summary of these documents",
},
],
{ contents: ids.map((id) => ({ id })) },
);
console.log("Summary:", summary.summarizeContents);
Processing Options
const content = await client.ingestUri(
"https://example.com/large-document.pdf",
undefined,
undefined,
true,
);
console.log("ā
Content ready!");
const content = await client.ingestUri(
"https://example.com/very-large-video.mp4",
);
let isReady = false;
while (!isReady) {
const status = await client.isContentDone(content.ingestUri.id);
isReady = status.isContentDone?.result || false;
if (!isReady) {
console.log("ā³ Still processing...");
await new Promise((resolve) => setTimeout(resolve, 2000));
}
}
console.log("ā
Content ready!");
Advanced Agent Features
Using Content Filters
Control what content the agent can access during conversations:
const result = await client.promptAgent(
"What are the main points in these documents?",
undefined,
{ id: specificationId },
undefined,
undefined,
undefined,
undefined,
undefined,
{
contents: [{ id: "content-id-1" }, { id: "content-id-2" }],
},
);
await client.streamAgent(
"Explain the technical details",
(event) => {
if (event.type === "message_update") {
process.stdout.write(event.message.message);
}
},
undefined,
{ id: specificationId },
undefined,
undefined,
undefined,
undefined,
undefined,
{
collections: [{ id: "technical-docs-collection" }],
},
);
Using Augmented Filters
Force specific content into the LLM context without retrieval:
const fileContent = await client.getContent("file-content-id");
await client.streamAgent(
"What patterns do you see in this code?",
(event) => {
if (event.type === "message_update") {
process.stdout.write(event.message.message);
}
},
undefined,
{ id: specificationId },
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
{
contents: [{ id: fileContent.content.id }],
},
);
Combining Filters
Use both filters for precise control:
await client.promptAgent(
"How does this code implement the algorithm described in the docs?",
undefined,
{ id: specificationId },
undefined,
undefined,
undefined,
undefined,
undefined,
{
collections: [{ id: "algorithm-docs" }],
},
{
contents: [{ id: "implementation-file-id" }],
},
);
Advanced Workflows
Creating Workflows for Content Processing
Workflows automatically process content when ingested:
import { Graphlit, Types } from "graphlit-client";
const client = new Graphlit();
const summarizationSpec = await client.createSpecification({
name: "Summarizer",
type: Types.SpecificationTypes.Summarization,
serviceType: Types.ModelServiceTypes.OpenAi,
openAI: {
model: Types.OpenAiModels.Gpt4O_128K,
},
});
const workflow = await client.createWorkflow({
name: "Document Intelligence",
preparation: {
summarizations: [
{
type: Types.SummarizationTypes.Summary,
specification: { id: summarizationSpec.createSpecification.id },
},
],
},
});
await client.updateProject({
workflow: { id: workflow.createWorkflow.id },
});
const content = await client.ingestUri(
"https://example.com/report.pdf",
);
Creating Specifications
Specifications configure how AI models behave:
import { Graphlit, Types } from "graphlit-client";
const conversationSpec = await client.createSpecification({
name: "Customer Support AI",
type: Types.SpecificationTypes.Completion,
serviceType: Types.ModelServiceTypes.OpenAi,
systemPrompt: "You are a helpful customer support assistant.",
openAI: {
model: Types.OpenAiModels.Gpt4O_128K,
temperature: 0.7,
completionTokenLimit: 2000,
},
});
await client.streamAgent(
"How do I reset my password?",
(event) => {
if (event.type === "message_update") {
console.log(event.message.message);
}
},
undefined,
{ id: conversationSpec.createSpecification.id },
);
API Reference
Client Methods
const client = new Graphlit(organizationId?, environmentId?, jwtSecret?);
Content Operations
ingestUri(uri, name?, id?, isSynchronous?, ...) - Ingest content from URL
ingestText(text, name?, textType?, ...) - Ingest text content directly
queryContents(filter?) - Search and query content
getContent(id) - Get content by ID
deleteContent(id) - Delete content
extractContents(prompt, tools, specification?, filter?) - Extract data from content
summarizeContents(summarizations, filter?) - Summarize content
isContentDone(id) - Check if content processing is complete
Conversation Operations
createConversation(input?) - Create a new conversation
streamAgent(prompt, handler, ...) - Stream AI responses
promptAgent(prompt, ...) - Get AI response without streaming
deleteConversation(id) - Delete conversation
Specification Operations
createSpecification(input) - Create AI model configuration
querySpecifications(filter?) - List specifications
deleteSpecification(id) - Delete specification
Workflow Operations
createWorkflow(input) - Create content processing workflow
queryWorkflows(filter?) - List workflows
updateProject(input) - Update project settings
Event Types
type AgentStreamEvent =
| { type: "conversation_started"; conversationId: string }
| { type: "message_update"; message: { message: string } }
| { type: "tool_update"; toolCall: any; status: string }
| {
type: "reasoning_update";
content: string;
format: "thinking_tag" | "markdown" | "custom";
isComplete: boolean;
}
| {
type: "context_window";
usage: { usedTokens: number; maxTokens: number; percentage: number };
}
| { type: "conversation_completed"; message: { message: string } }
| { type: "error"; error: { message: string; recoverable: boolean } };
Testing & Examples
All examples in this README are tested and verified. See test/readme-simple.test.ts for runnable versions of these examples.
To run the examples yourself:
git clone https://github.com/graphlit/graphlit-client-typescript.git
cd graphlit-client-typescript
npm install
cp .env.example .env
npm test test/readme-simple.test.ts
Support
License
MIT License - see LICENSE file for details.