@sentygent/sdk
v0.1.1
Published
Sentygent SDK for AI agent observability
Downloads
208
Readme
@sentygent/sdk
TypeScript SDK for Sentygent — AI Observability & Evaluation Platform.
Instrument your AI agents and pipelines to capture LLM calls, tool executions, RAG retrievals, and conversation lifecycle events. Works with any LLM provider.
Installation
npm install @sentygent/sdkPeer Dependencies (optional)
Install only the SDKs you use for auto-instrumentation:
# For Anthropic auto-instrumentation
npm install @anthropic-ai/sdk
# For AWS Bedrock auto-instrumentation
npm install @aws-sdk/client-bedrock-runtimeQuick Start
import { SentygentClient } from '@sentygent/sdk';
const sentygent = new SentygentClient({
apiKey: process.env.SENTYGENT_API_KEY!,
agent: 'my-agent',
});
await sentygent.trace('conversation-123', async (span) => {
span.captureLifecycle('conversation_start');
// Your agent logic here...
span.captureLifecycle('conversation_end');
});Provider Support
Sentygent works with any LLM provider. The integration method depends on your provider:
| Provider | Method | What you get |
|----------|--------|-------------|
| Anthropic | instrumentAnthropic() — zero-code | Automatic capture of all messages.create and messages.stream calls |
| AWS Bedrock | instrumentBedrock() — zero-code | Automatic capture of ConverseCommand, InvokeModelCommand + streaming variants |
| OpenAI | span.captureLLM() — typed helper | You provide execute + extractUsage. SDK handles timing, errors, event structure |
| Cohere, Mistral, Groq, Together, etc. | span.captureLLM() — typed helper | Same as OpenAI — works with any provider that returns token counts |
| Ollama, vLLM, local models | span.captureLLM() — typed helper | extractUsage can return null if provider doesn't expose tokens. Timing still captured |
Auto-Instrumentation: Anthropic
Wrap the Anthropic client once. All LLM calls are captured automatically — model, tokens, cost, latency.
import Anthropic from '@anthropic-ai/sdk';
import { SentygentClient, instrumentAnthropic } from '@sentygent/sdk';
const sentygent = new SentygentClient({
apiKey: process.env.SENTYGENT_API_KEY!,
agent: 'my-agent',
});
const anthropic = instrumentAnthropic(new Anthropic(), sentygent);
// Use as normal — all calls are captured automatically
await sentygent.trace('conv-123', async () => {
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello!' }],
});
});Streaming is also supported:
await sentygent.trace('conv-123', async () => {
const stream = anthropic.messages.stream({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Tell me a story' }],
});
for await (const event of stream) {
// Process stream events...
}
const message = await stream.finalMessage();
});Auto-Instrumentation: AWS Bedrock
import { BedrockRuntimeClient, ConverseCommand } from '@aws-sdk/client-bedrock-runtime';
import { SentygentClient, instrumentBedrock } from '@sentygent/sdk';
const sentygent = new SentygentClient({
apiKey: process.env.SENTYGENT_API_KEY!,
agent: 'my-agent',
});
const bedrock = instrumentBedrock(
new BedrockRuntimeClient({ region: 'eu-west-1' }),
sentygent,
);
await sentygent.trace('conv-123', async () => {
await bedrock.send(
new ConverseCommand({
modelId: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
messages: [{ role: 'user', content: [{ text: 'Hello!' }] }],
}),
);
});Typed Helper: Any Provider (OpenAI, Cohere, Mistral, Groq, etc.)
Use span.captureLLM() to capture calls to any LLM provider. You provide the execute function and a callback to extract token usage.
import OpenAI from 'openai';
const openai = new OpenAI();
await sentygent.trace('conv-123', async (span) => {
span.captureLifecycle('conversation_start');
const result = await span.captureLLM({
provider: 'openai',
model: 'gpt-4o',
execute: () => openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'Hello!' }],
}),
extractUsage: (r) => ({
promptTokens: r.usage?.prompt_tokens ?? 0,
completionTokens: r.usage?.completion_tokens ?? 0,
}),
cost: 0.003, // Optional: pre-computed cost in euros (overrides pricing table)
});
span.captureLifecycle('conversation_end');
});Provider values: 'anthropic', 'bedrock', 'openai', or 'other' for any unlisted provider.
If your provider doesn't expose token counts (e.g. some local models), return null from extractUsage:
await span.captureLLM({
provider: 'other',
model: 'llama-3-70b',
execute: () => ollama.chat({ model: 'llama3', messages }),
extractUsage: () => null, // Tokens unavailable — timing still captured
});Capturing Tool Calls
await span.captureTool({
name: 'web_search',
input: { query: 'latest news' },
execute: () => searchAPI.search('latest news'),
tags: { step: 'search' }, // Optional dimensional tags
});Capturing RAG / Retrieval
For RAG, vector search, or any retrieval step:
await span.captureRetrieval({
provider: 'bedrock-kb', // or 'pinecone', 'opensearch', etc.
query: 'leadership styles',
execute: () => knowledgeBase.retrieve(query),
extractResults: (r) => ({
resultsCount: r.chunks.length,
relevantCount: r.chunks.filter(c => c.score >= 0.5).length,
meanScore: avg(r.chunks.map(c => c.score)),
topScore: Math.max(...r.chunks.map(c => c.score)),
}),
searchType: 'hybrid', // Optional: 'semantic', 'keyword', 'hybrid'
cost: 0.0001, // Optional: retrieval cost in euros
tags: { courseId: 'lid-101' }, // Optional dimensional tags
});Tags (Dimensional Metadata)
Tags let you segment metrics by any dimension: course, intent, pipeline step, model version, etc.
// Tags on individual events
await span.captureLLM({
provider: 'anthropic',
model: 'claude-sonnet-4-20250514',
execute: () => anthropic.messages.create({ ... }),
extractUsage: (r) => ({ ... }),
tags: { step: 'classify', intent: 'chat' },
});
// Tags on spans (inherited by all events from that span)
const child = span.child('analysis', { tags: { step: 'analyze' } });
await child.captureLLM({ ... }); // inherits step=analyze
// Tags at trace level (inherited by all spans and events)
await sentygent.trace('conv-123', async (span) => { ... }, {
tags: { courseId: 'liderazgo-101' },
});Tags are visible in the dashboard trace view as pill badges on each event.
Request-Response Pipelines
For pipeline architectures where each HTTP request is a complete trace, use request() instead of trace(). It automatically emits conversation_start and conversation_end, which triggers quality scoring.
app.post('/api/chat', async (req, res) => {
const answer = await sentygent.request(req.body.sessionId, async (span) => {
// No need to manually emit conversation_start/end
const intent = await span.captureLLM({ tags: { step: 'classify' }, ... });
const chunks = await span.captureRetrieval({ ... });
const response = await span.captureLLM({ tags: { step: 'generate' }, ... });
return response;
}, { tags: { courseId: req.body.courseId } });
res.json(answer);
});Multi-Agent Tracing
For systems where multiple agents collaborate in a single conversation:
const sentygent = new SentygentClient({ agent: 'orchestrator' });
await sentygent.trace('conv-123', async (span) => {
span.captureLifecycle('conversation_start');
// Sub-agent with different slug
const searchSpan = span.child('search', { agent: 'search-agent' });
await searchSpan.captureLLM({ ... });
await searchSpan.captureTool({ ... });
// Another sub-agent
const analysisSpan = span.child('analysis', { agent: 'analysis-agent' });
await analysisSpan.captureLLM({ ... });
// Orchestrator composes final response
await span.captureLLM({ ... });
span.captureLifecycle('conversation_end');
});The dashboard groups spans by agent with color-coded timeline and per-agent cost breakdown.
Child Spans
await sentygent.trace('conv-123', async (span) => {
const child = span.child('planning-step');
await child.captureLLM({ ... });
const toolSpan = span.child('tool-execution');
await toolSpan.captureTool({ ... });
});Configuration
const sentygent = new SentygentClient({
apiKey: 'snt_...', // Required: your API key
agent: 'my-agent', // Required: registered agent slug
environment: 'production', // Default: 'production'
endpoint: 'https://api.sentygent.com', // Default API endpoint
flushInterval: 5000, // Flush every 5s (default)
maxBatchSize: 100, // Events per batch (default)
maxBufferSize: 10000, // Max buffered events (default)
retryAttempts: 3, // Retry failed sends (default)
debug: false, // Enable debug logging
disabled: false, // Kill switch — disables all operations
});Graceful Shutdown
The SDK registers beforeExit and SIGTERM handlers to flush remaining events. You can also call shutdown manually:
await sentygent.shutdown();Error Handling
The SDK never throws from transport operations. If the API is unreachable after retries, a warning is logged and the SDK continues. Your application is never affected by SDK failures.
Troubleshooting
Events not appearing in dashboard:
- Verify your API key is correct
- Check that the agent slug matches a registered agent
- Enable
debug: truefor detailed logging - Ensure
shutdown()is called before process exit
High memory usage:
- Reduce
maxBufferSizeif your agent generates many events - Reduce
flushIntervalto send events more frequently
