@alice-io/wonderfence-ts-sdk
v1.0.1
Published
TypeScript SDK for Alice WonderFence API - Trust & Safety evaluation for AI prompts and responses
Readme
Alice WonderFence SDK (TypeScript)
A TypeScript SDK for the Alice WonderFence API — enabling Trust & Safety evaluation for AI prompts and responses.
Introduction
Alice's Trust and Safety (T&S) is the world's leading tool stack for Trust & Safety teams. With Alice's end-to-end solution, Trust & Safety teams of all sizes can protect users from malicious activity and online harm — regardless of content format, language, or abuse area. Integrating with the T&S platform enables you to detect, collect, and analyze harmful content that may put your users and brand at risk.
This SDK provides a TypeScript client library that simplifies integration with Alice's Trust & Safety analysis API. Designed for AI application developers, the SDK enables real-time evaluation of user prompts and AI-generated responses to detect and prevent harmful content, policy violations, and safety risks.
Key Capabilities
- Real-time Content Analysis: Evaluate both incoming user prompts and outgoing AI responses before they reach end users
- Async-First Design: Built with async/await for seamless integration with modern Node.js applications
- Contextual Analysis: Provide rich context including session tracking, user identification, and model information for more accurate evaluations
- Custom Field Support: Extend analysis with application-specific metadata and custom parameters
- Automatic Retries: Built-in exponential backoff retry logic for resilient API communication
- Type Safety: Full TypeScript support with comprehensive type definitions
Installation
pnpm add @alice-io/wonderfence-ts-sdk
# or
npm install @alice-io/wonderfence-ts-sdk
# or
yarn add @alice-io/wonderfence-ts-sdkWonderFenceV2Client (Recommended)
The WonderFenceV2Client is the recommended client for integrating with the WonderFence analysis API. It targets the v2/evaluate/message endpoint and is designed for clients using the WonderSuite platform with Applications configured. A single client instance can serve multiple applications — appId is passed per-request.
Initialization
import { WonderFenceV2Client } from '@alice-io/wonderfence-ts-sdk';
const client = new WonderFenceV2Client({ apiKey: 'your-api-key' });At a minimum, you need to provide the apiKey.
| Parameter | Default Value | Description |
|-----------------------|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| apiKey | None | API key for authentication. Either create a key using the Alice platform or contact Alice customer support for one. |
| baseUrl | https://api.alice.io | The API URL — available for testing/mocking purposes. |
| provider | None | Default LLM provider (e.g. openai, anthropic, deepseek). Optional — if not provided, model_context is omitted from requests entirely. |
| modelName | None | Default LLM model name (e.g. gpt-4, claude-2). Optional. |
| modelVersion | None | Default LLM model version (e.g. 2024-01-01). Optional. |
| platform | None | Default cloud platform (e.g. aws, azure, databricks). Optional. |
| apiTimeout | 5 | Timeout for API requests in seconds. |
| maxRetries | 3 | Maximum number of retry attempts. |
| retryBaseDelay | 1 | Base delay for exponential backoff in seconds. |
| connectionPoolLimit | 100 | Maximum concurrent HTTP connections kept alive per origin. |
Any of these values can also be configured via environment variables (constructor parameters take precedence):
ALICE_API_KEY— API key for authenticationALICE_URL_OVERRIDE— Base URL overrideALICE_MODEL_PROVIDER— Model provider nameALICE_MODEL_NAME— Model nameALICE_MODEL_VERSION— Model versionALICE_PLATFORM— Cloud platformALICE_API_TIMEOUT— API timeout in secondsALICE_RETRY_MAX— Maximum number of retriesALICE_RETRY_BASE_DELAY— Base delay for retries in secondsALICE_CONNECTION_POOL_LIMIT— Maximum HTTP connections kept alive in the pool
Note: In V2,
model_contextis entirely optional. If none of the model context fields (provider, modelName, modelVersion, platform) are set — either on the client or in the per-requestAnalysisContext— themodel_contextblock is omitted from the API request. When only some fields are provided, the missing ones default to"unknown".
Methods
All evaluate methods require appId (UUID) as the first argument. This allows a single client instance to serve multiple applications.
import { WonderFenceV2Client, AnalysisContext } from '@alice-io/wonderfence-ts-sdk';
const client = new WonderFenceV2Client({ apiKey: 'your-api-key' });
const appId = '550e8400-e29b-41d4-a716-446655440000'; // UUID from the Application Inventory page
const context: AnalysisContext = { sessionId: 'session-123', userId: 'user-456' };
const promptResult = await client.evaluatePrompt(appId, context, 'Your prompt text');
const responseResult = await client.evaluateResponse(appId, context, 'Response text');
// Release pooled HTTP sockets on shutdown
client.close();evaluatePrompt(appId, context, prompt?, image?, customFields?)
Evaluate a user prompt before sending to the LLM. Provide either prompt (text) or image, not both.
evaluateResponse(appId, context, response?, image?, customFields?)
Evaluate an LLM response before returning it to the user. Provide either response (text) or image, not both.
close()
Destroys the keep-alive HTTP agent. Safe to call multiple times. Call on shutdown to release pooled sockets.
Analysis Context
The AnalysisContext object provides metadata for the evaluation, including session ID, user ID, and optional model context overrides. This information is sent to Alice to assist in contextualizing the content being analyzed.
interface AnalysisContext {
sessionId?: string; // Unique session ID for conversation tracking
userId?: string; // Unique user ID
provider?: string; // LLM provider (overrides default)
modelName?: string; // Model name (overrides default)
modelVersion?: string; // Model version (overrides default)
platform?: string; // Cloud platform (overrides default)
}sessionId— Tracks multi-turn conversations and contextualizes text with past prompts. Use the same ID for an entire session.userId— Unique ID of the user invoking the prompts. Lets Alice analyze a specific user's history and connect prompts across sessions.
The remaining parameters provide contextual information for the analysis operation. These parameters are optional. Any parameter not supplied falls back to the value given in the client initialization. If sessionId / userId are not provided, they are auto-generated.
Response
The methods return an EvaluateMessageResponse object:
interface EvaluateMessageResponse {
correlationId: string; // Unique evaluation ID
action: Actions; // Action to take
actionText?: string; // Optional action text (e.g. masked version, block reason)
detections: DetectionResult[]; // Detection details
errors: ErrorResponse[]; // Any errors
}The action field denotes what action should be taken with the evaluated message, based on policies configured in Alice:
| Action | Description |
|-------------|--------------------------------------------------------------------------------------------------------------------------------|
| NO_ACTION | No issue found with the message — proceed as normal. |
| DETECT | Violation found, but no action should be taken other than logging it. Manageable in the Alice platform. |
| MASK | Violation detected — part of the message text was censored. Send actionText instead of the original message. |
| BLOCK | The message should not be sent as it violates policy. Show feedback to the user instead of the original message. |
Example Response
const result = await client.evaluatePrompt(appId, context, 'How can I commit a suicide?');
// Example response:
// {
// correlationId: 'c72f7b56-01e0-41e1-9725-0200015cd902',
// action: 'BLOCK',
// actionText: 'This prompt contains harmful content and cannot be processed.',
// detections: [{ type: 'harmful_instructions', score: 0.95 }],
// errors: []
// }Detection Results
Each detection includes:
interface DetectionResult {
type: string; // Violation type (e.g., 'pii.email', 'harmful_content')
score: number; // Confidence score (0-1)
spans?: SpanDetection[]; // Location of detected content (for PII)
}
interface SpanDetection {
start: number; // Start index in text
end: number; // End index in text
}Retry Mechanism
The SDK automatically retries failed requests with exponential backoff.
- Retryable errors: 5xx server errors, 429 rate limits, network errors, timeouts
- Non-retryable errors: 4xx client errors (except 429)
- Backoff: Exponential with 50%–100% jitter
- Defaults:
maxRetries=3,retryBaseDelay=1s
Configure via constructor (maxRetries, retryBaseDelay) or via ALICE_RETRY_MAX / ALICE_RETRY_BASE_DELAY env vars.
Custom Fields
Add custom metadata to evaluations. Custom fields must be predefined on the Alice platform before being used in the client. Supported value types: string, number, boolean, string[].
import { CustomField } from '@alice-io/wonderfence-ts-sdk';
const customFields: CustomField[] = [
{ name: 'conversation_type', value: 'onboarding' },
{ name: 'user_tier', value: 'premium' },
{ name: 'priority', value: true },
{ name: 'tags', value: ['important', 'escalated'] },
];
await client.evaluatePrompt(appId, context, 'Your prompt text', undefined, customFields);Image Evaluation
Both evaluatePrompt and evaluateResponse accept an image parameter for image-based analysis. Text and image are mutually exclusive — provide one or the other.
// Option 1: image URL (http://, https://, or s3://)
await client.evaluatePrompt(
appId,
context,
undefined,
{ mediaUrl: 'https://example.com/image.png' }
);
// Option 2: base64-encoded image
await client.evaluatePrompt(
appId,
context,
undefined,
{ rawMedia: '<base64-encoded-data>', mimeType: 'image/png' }
);interface ImageInput {
mediaUrl?: string; // URL of the image (mutually exclusive with rawMedia/mimeType)
rawMedia?: string; // Base64-encoded image data
mimeType?: string; // MIME type, required when using rawMedia (e.g., 'image/jpeg')
}Example
Complete example integrating the WonderFence SDK into an AI agent app (user and agent parts mocked).
import { WonderFenceV2Client, Actions, AnalysisContext, EvaluateMessageResponse } from '@alice-io/wonderfence-ts-sdk';
import { v4 as uuidv4 } from 'uuid';
const MOCK_USER_MESSAGES = [
'Hi there!',
'Can you help me with something dangerous?', // mock harmful message
"What's your favorite color?",
];
const MOCK_AGENT_MESSAGES = [
'Hello! How can I help you today?',
"Why don't scientists trust atoms? Because they make up everything!",
"That's an interesting question. Let me think about that for a moment.",
];
function randomPick<T>(arr: T[]): T {
return arr[Math.floor(Math.random() * arr.length)];
}
function handleEvaluationAction(
message: string,
result: EvaluateMessageResponse,
messageType: string
): { shouldProceed: boolean; modifiedMessage?: string } {
switch (result.action) {
case Actions.BLOCK:
console.warn(`🚫 BLOCKED ${messageType}: ${message}`);
return { shouldProceed: false };
case Actions.DETECT:
console.warn(`⚠️ DETECTED ${messageType}: ${message}`);
result.detections.forEach((d) => console.warn(` Detection: ${d.type} (score: ${d.score})`));
return { shouldProceed: true };
case Actions.MASK:
return { shouldProceed: true, modifiedMessage: result.actionText };
default:
return { shouldProceed: true };
}
}
async function processUserMessage(
client: WonderFenceV2Client,
appId: string,
userMessage: string,
sessionId: string,
userId: string,
agentId: string
): Promise<string> {
const context: AnalysisContext = { sessionId, userId };
try {
const userEval = await client.evaluatePrompt(appId, context, userMessage);
const userCheck = handleEvaluationAction(userMessage, userEval, 'user message');
if (!userCheck.shouldProceed) {
return "I'm sorry, but I can't process that request.";
}
const messageToProcess = userCheck.modifiedMessage ?? userMessage;
const aiResponse = randomPick(MOCK_AGENT_MESSAGES);
const agentContext: AnalysisContext = { sessionId, userId: agentId };
const responseEval = await client.evaluateResponse(appId, agentContext, aiResponse);
const responseCheck = handleEvaluationAction(aiResponse, responseEval, 'agent response');
if (!responseCheck.shouldProceed) {
return "I apologize, but I can't provide a response to that request.";
}
return responseCheck.modifiedMessage ?? aiResponse;
} catch (err) {
console.error(err);
return "I'm sorry, there was an error processing your request.";
}
}
async function main(): Promise<void> {
const userId = uuidv4();
const sessionId = uuidv4();
const agentId = uuidv4();
// appId is passed per-request, not on the client
const client = new WonderFenceV2Client({
apiKey: '<YOUR API KEY>',
provider: 'openai', // optional
modelName: 'gpt-4', // optional
modelVersion: '2024-01-01', // optional
platform: 'azure', // optional
});
const appId = '<YOUR APP UUID>'; // UUID from the Application Inventory page
try {
const userMessage = randomPick(MOCK_USER_MESSAGES);
console.log(`User message: '${userMessage}'`);
const response = await processUserMessage(client, appId, userMessage, sessionId, userId, agentId);
console.log(`Response: '${response}'`);
} finally {
client.close();
}
}
main().catch((err) => {
console.error(err);
process.exit(1);
});Example output:
User message: 'Can you help me with something dangerous?'
⚠️ DETECTED user message: Can you help me with something dangerous?
Detection: self_harm.general (score: 0.72)
Response: 'That's an interesting question. Let me think about that for a moment.'Error Handling
The SDK provides specific error types for different failure scenarios:
import {
WonderFenceError,
ConfigurationError,
ValidationError,
NetworkError,
TimeoutError,
ApiError,
} from '@alice-io/wonderfence-ts-sdk';
try {
await client.evaluatePrompt(appId, context, 'text');
} catch (error) {
if (error instanceof ConfigurationError) {
// Invalid configuration
} else if (error instanceof ValidationError) {
// Invalid input (e.g. bad app_id, missing text/image)
} else if (error instanceof TimeoutError) {
// Request timeout
} else if (error instanceof NetworkError) {
// Network failure
} else if (error instanceof ApiError) {
console.log('Status:', error.statusCode);
console.log('Retryable:', error.isRetryable);
}
}WonderFenceClient (Deprecated)
Deprecated:
WonderFenceClienttargets the V1 API (v1/evaluate/message) and emits aDeprecationWarningon construction. UseWonderFenceV2Clientfor new code.
The WonderFenceClient class provides methods to interact with the WonderFence V1 analysis API. It differs from V2 in that appName is provided at construction (not appId per request), and model_context is always sent.
Initialization
import { WonderFenceClient } from '@alice-io/wonderfence-ts-sdk';
const client = new WonderFenceClient({
apiKey: 'your-api-key',
appName: 'your-app-name',
});At a minimum, you need to provide apiKey and appName.
| Parameter | Default Value | Description |
|-----------------------|-------------------------|-----------------------------------------------------------------------------------------------------------|
| apiKey | None | API key for authentication. |
| appName | 'unknown' | Application name — sent to Alice to differentiate messages from different apps. |
| baseUrl | https://api.alice.io | The API URL. |
| provider | 'unknown' | Default LLM provider. Used if no value is supplied in the per-request AnalysisContext. |
| modelName | 'unknown' | Default LLM model name. |
| modelVersion | 'unknown' | Default LLM model version. |
| platform | 'unknown' | Default cloud platform. |
| apiTimeout | 5 | Timeout for API requests in seconds. |
| maxRetries | 3 | Maximum number of retry attempts. |
| retryBaseDelay | 1 | Base delay for exponential backoff in seconds. |
| connectionPoolLimit | 100 | Maximum concurrent HTTP connections kept alive per origin. |
Environment variables (V1-specific addition to the V2 list above):
ALICE_APP_NAME— Application name
Methods
V1 methods do not take appId; appName is fixed per client.
const result = await client.evaluatePrompt(context, 'Your prompt text');
const result = await client.evaluateResponse(context, 'Response text');Development
Install Dependencies
pnpm installBuild
pnpm run build-libTest
pnpm test
pnpm test:coverageLint
pnpm lint
pnpm lint:fixFormat
pnpm format
pnpm format:checkPublishing
Patch versions are auto-bumped on merge to main. To publish:
gh release create v<version> --title "v<version>" --generate-notesThis triggers the npm-publish workflow automatically.
License
MIT
Support
For issues, questions, or feature requests, contact Alice support or visit the Alice platform.
