Requires: @anthropic-ai/claude-agent-sdk v0.2.0+ as a peer dependency. Works with the query() function for one-shot and multi-turn interactions.
What Gets Tracked Automatically
Sessions
Created on init, completed on result — with agent name, user ID, and metadata.
Tool Calls
Every tool execution (Bash, Read, Write, etc.) with input, output, and tool use ID.
Tokens & Cost
Prompt tokens, completion tokens, total tokens, and estimated cost in USD.
Conversation Threading
Group related sessions with convoId — multi-turn conversations appear linked.
Errors
Failed tool calls, errored sessions, and generator exceptions — all recorded.
Duration
Wall-clock time from start to result, plus API-side duration when available.
Installation
npm install @sentrial/sdk @anthropic-ai/claude-agent-sdk
Quick Start
Wrap the query() function once, then use it exactly like normal.
import { query } from '@anthropic-ai/claude-agent-sdk';
import { SentrialClient, wrapClaudeAgent } from '@sentrial/sdk';
// 1. Create a Sentrial client
const sentrial = new SentrialClient({
apiKey: process.env.SENTRIAL_API_KEY,
});
// 2. Wrap query()
const trackedQuery = wrapClaudeAgent(query, {
client: sentrial,
defaultAgent: 'my-agent',
userId: 'user-123',
});
// 3. Use normally — everything is tracked
for await (const message of trackedQuery({
prompt: 'Fix the failing tests in src/auth.ts',
options: {
maxTurns: 10,
permissionMode: 'bypassPermissions',
},
})) {
if (message.type === 'assistant') {
// Handle assistant messages
}
}
// Session auto-completed with tokens, cost, duration, and all tool calls
Configuration Options
const trackedQuery = wrapClaudeAgent(query, {
client: sentrial, // required — SentrialClient instance
defaultAgent: 'my-agent', // optional — agent name for grouping (default: 'claude-agent')
userId: 'user-123', // optional — ties sessions to your end users (default: 'anonymous')
convoId: 'convo-abc', // optional — group sessions into a conversation thread
extraMetadata: { // optional — merged into every session's metadata
environment: 'production',
version: '1.2.0',
},
});
Fail-Safe by Default — If Sentrial is unreachable, all messages pass through unchanged. Your agent never breaks due to tracking failures.
Conversation Threading
Use convoId to group related sessions into a conversation. Each call to trackedQuery() creates a new session, but they appear linked in the dashboard.
const convoId = `user-${userId}-${Date.now()}`;
const trackedQuery = wrapClaudeAgent(query, {
client: sentrial,
defaultAgent: 'code-assistant',
userId,
convoId,
});
// Session 1: Explore the codebase
for await (const msg of trackedQuery({
prompt: 'List all API routes and their handlers',
})) { /* ... */ }
// Session 2: Follow-up (same convoId, linked in dashboard)
for await (const msg of trackedQuery({
prompt: 'Add rate limiting to the /api/users endpoint',
})) { /* ... */ }
The wrapper uses PostToolUse and PostToolUseFailure hooks to capture every tool execution. Hooks fire asynchronously and never block the agent. A session-ready gate ensures hooks wait for session creation before tracking.
// No extra code needed — tool calls are tracked automatically
for await (const message of trackedQuery({
prompt: 'Read package.json and tell me the project name',
options: {
allowedTools: ['Bash', 'Read', 'Glob'],
},
})) {
// Each tool call (Read, Bash, etc.) is recorded as an event
// with input args, output, and execution metadata
}
In the dashboard, each tool call appears as an event under the session timeline.
Error Handling
If the agent errors or the generator throws, the session is automatically marked as failed with the error message.
try {
for await (const message of trackedQuery({
prompt: 'Deploy to production',
})) {
// ...
}
} catch (error) {
// Session already marked as failed in Sentrial
// with failure_reason = error.message
console.error(error);
}
Full Production Example
import { query } from '@anthropic-ai/claude-agent-sdk';
import { SentrialClient, wrapClaudeAgent } from '@sentrial/sdk';
const sentrial = new SentrialClient({
apiKey: process.env.SENTRIAL_API_KEY!,
});
async function runAgent(userPrompt: string, userId: string) {
const convoId = `session-${userId}-${Date.now()}`;
const trackedQuery = wrapClaudeAgent(query, {
client: sentrial,
defaultAgent: 'code-review-agent',
userId,
convoId,
extraMetadata: {
environment: process.env.NODE_ENV,
},
});
let result = '';
for await (const message of trackedQuery({
prompt: userPrompt,
options: {
model: 'claude-sonnet-4-20250514',
maxTurns: 15,
permissionMode: 'bypassPermissions',
allowedTools: ['Bash', 'Read', 'Write', 'Glob', 'Grep'],
},
})) {
if (message.type === 'result') {
result = message.result ?? '';
}
}
return result;
}
What You See in the Dashboard
Session Overview
Agent name, user ID, conversation thread, status, duration, cost.
Input / Output
The prompt and Claude’s final response.
Tool Call Timeline
Every Bash, Read, Write, Glob call — with input, output, and tool use ID.
Token & Cost Breakdown
Prompt tokens, completion tokens, total, estimated USD cost.
Next Steps