Official TypeScript SDK for assessing AI systems for ethical alignment. Test your AI across 4 dimensions: Lying, Cheating, Stealing, and Harm.
Your AI's API keys, system prompts, and configuration never leave your environment
Test configuration, questions, and thresholds managed via Health Check Key
Auto-detects GitHub Actions, GitLab CI, CircleCI, and more
npm install @aiassesstech/sdk
# or use the shorter package name:
npm install aiassesstechyarn add @aiassesstech/sdk
# or
yarn add aiassesstechpnpm add @aiassesstech/sdk
# or
pnpm add aiassesstech@aiassesstech/sdk and aiassesstech are identical. Use whichever you prefer!import { AIAssessClient } from '@aiassesstech/sdk';
// 1. Create client with your Health Check Key
const client = new AIAssessClient({
healthCheckKey: process.env.AIASSESS_KEY!
});
// 2. Run assessment - configuration comes from server
const result = await client.assess(async (question) => {
// Your AI callback - send question to your AI and return response
return await myAI.chat(question);
});
// 3. Check result
console.log('Passed:', result.overallPassed);
console.log('Scores:', result.scores);
console.log('Classification:', result.classification);โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Your Environment โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ 1. SDK fetches config from AI Assess Tech server โ
โ (questions, thresholds, test mode) โ
โ โ
โ 2. SDK sends questions to YOUR AI via your callback โ
โ โ Your API keys stay private โ
โ โ Your system prompts stay private โ
โ โ
โ 3. SDK submits responses to server for scoring โ
โ โ
โ 4. You receive scores, pass/fail, and classification โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโThe SDK is client-side code that runs in your environment. All security is enforced server-side โ the SDK cannot bypass rate limits, override thresholds, or fake scores.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SECURITY ARCHITECTURE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โ
SERVER ENFORCES: โ
โ โโโ Rate limiting (per IP for demo, per key for production) โ
โ โโโ Thresholds (from database, not client-provided) โ
โ โโโ Scoring (calculated server-side, immutable) โ
โ โโโ API key validation (hashed, checked against database) โ
โ โโโ Tier restrictions (DEMO, STANDARD, ENTERPRISE) โ
โ โโโ Result integrity (hashed and locked) โ
โ โ
โ ๐ YOUR DATA STAYS PRIVATE: โ
โ โโโ Your AI's API keys (OpenAI, Anthropic) never sent to us โ
โ โโโ Your system prompts stay in your environment โ
โ โโโ Only AI responses are submitted for scoring โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ| Security Control | Server-Side Enforcement |
|---|---|
| Rate Limiting | Enforced per IP (demo) or per key (production). SDK cannot bypass. |
| Thresholds | Stored in your API key config. Client cannot override pass/fail thresholds. |
| Scoring | Calculated entirely server-side based on question lookup. |
| Questions | Served from database. Client cannot modify question content. |
| Results | Hashed with SHA-256 and locked. Tamper-proof verification. |
| Tier Limits | DEMO: 5/hr, STANDARD: 50/hr, ENTERPRISE: 1000/hr. From API key record. |
The open-source demo app uses a public demo key that is intentionally rate-limited server-side:
import OpenAI from 'openai';
import { AIAssessClient } from '@aiassesstech/sdk';
const openai = new OpenAI();
const client = new AIAssessClient({
healthCheckKey: process.env.AIASSESS_KEY!
});
const result = await client.assess(async (question) => {
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: question }]
});
return response.choices[0].message.content || '';
});
console.log(`Classification: ${result.classification}`);
console.log(`Lying Score: ${result.scores.lying}/10`);
console.log(`Overall: ${result.overallPassed ? 'PASSED โ
' : 'FAILED โ'}`);import Anthropic from '@anthropic-ai/sdk';
import { AIAssessClient } from '@aiassesstech/sdk';
const anthropic = new Anthropic();
const client = new AIAssessClient({
healthCheckKey: process.env.AIASSESS_KEY!
});
const result = await client.assess(async (question) => {
const response = await anthropic.messages.create({
model: 'claude-3-sonnet-20240229',
max_tokens: 100,
messages: [{ role: 'user', content: question }]
});
return response.content[0].type === 'text'
? response.content[0].text
: '';
});const result = await client.assess(
async (question) => await myAI.chat(question),
{
onProgress: (progress) => {
console.log(`${progress.percentage}% - Testing ${progress.dimension}`);
// Output: "25% - Testing lying"
// Output: "50% - Testing cheating"
// Output: "75% - Testing stealing"
// Output: "100% - Testing harm"
}
}
);// Block until AI passes - exits process on failure
await client.blockUntilPass(
async (question) => await myAI.chat(question),
{
maxRetries: 3,
retryDelayMs: 60000, // 1 minute between retries
exitOnFailure: true
}
);
console.log('โ
AI passed ethical assessment, starting app...');
startApp();import { AIAssessClient, withRetry } from '@aiassesstech/sdk';
const result = await client.assess(
withRetry(
async (question) => await flakyAI.chat(question),
{ maxRetries: 3, backoffMs: 1000 }
)
);// Only asks 5 questions, returns mock scores
const result = await client.assess(
async (question) => await myAI.chat(question),
{ dryRun: true }
);The assess() method returns an AssessmentResult object:
interface AssessmentResult {
runId: string; // Server-generated ID for verification
sdkSessionId: string; // Client-generated session ID
scores: {
lying: number; // 0-10 scale
cheating: number;
stealing: number;
harm: number;
};
passed: {
lying: boolean; // Did score meet threshold?
cheating: boolean;
stealing: boolean;
harm: boolean;
};
overallPassed: boolean; // All dimensions must pass
classification:
| "Well Adjusted" // High scores across all dimensions
| "Misguided" // Low lying, high harm (believes false things but tries to do good)
| "Manipulative" // High lying, low harm (deceives but avoids direct harm)
| "Psychopath"; // Low scores across the board
thresholds: { // Thresholds used from server config
lying: number;
cheating: number;
stealing: number;
harm: number;
};
verifyUrl: string; // URL to verify this result
completedAt: string; // ISO timestamp
versions: {
sdk: string; // SDK version used
questionSet: string; // Question set version
};
keyName: string; // Name of Health Check Key used
}const client = new AIAssessClient({
// Required: Your Health Check Key from the dashboard
healthCheckKey: 'hck_...',
// Optional: Override base URL (default: https://www.aiassesstech.com)
baseUrl: 'https://www.aiassesstech.com',
// Optional: Per-question timeout in ms (default: 30000 = 30s)
perQuestionTimeoutMs: 30000,
// Optional: Overall timeout in ms (default: 360000 = 6 min)
overallTimeoutMs: 360000
});Configuration is managed via the Health Check Key on the AI Assess Tech dashboard:
prod-strict - Production with strict thresholdsstaging-relaxed - Staging with relaxed thresholdsci-quick - CI/CD pipeline checksimport {
AIAssessClient,
SDKError,
ValidationError,
RateLimitError,
QuestionTimeoutError,
ErrorCode
} from '@aiassesstech/sdk';
try {
const result = await client.assess(callback);
} catch (error) {
if (error instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfterMs}ms`);
} else if (error instanceof ValidationError) {
if (error.code === ErrorCode.KEY_EXPIRED) {
console.log('Health Check Key has expired');
} else if (error.code === ErrorCode.INVALID_KEY) {
console.log('Invalid Health Check Key');
}
} else if (error instanceof QuestionTimeoutError) {
console.log(`Question ${error.questionId} timed out`);
} else if (error instanceof SDKError) {
console.log(`SDK Error: ${error.message} (${error.code})`);
}
}| Code | Description |
|---|---|
| INVALID_KEY | Health Check Key is invalid or not found |
| KEY_EXPIRED | Health Check Key has expired |
| RATE_LIMITED | Too many requests, try again later |
| QUESTION_TIMEOUT | AI took too long to respond to a question |
| NETWORK_ERROR | Network connection failed |
| SERVER_ERROR | Server-side error occurred |
name: AI Ethics Health Check
on:
push:
branches: [main]
schedule:
- cron: "0 */6 * * *" # Every 6 hours
jobs:
health-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
run: npm install @aiassesstech/sdk openai
- name: Run AI Health Check
env:
AIASSESS_KEY: ${{ secrets.AIASSESS_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
node -e "
const { AIAssessClient } = require('@aiassesstech/sdk');
const OpenAI = require('openai');
const openai = new OpenAI();
const client = new AIAssessClient({
healthCheckKey: process.env.AIASSESS_KEY
});
client.assess(async (q) => {
const r = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: q }]
});
return r.choices[0].message.content;
}).then(result => {
console.log('Classification:', result.classification);
console.log('Scores:', JSON.stringify(result.scores));
process.exit(result.overallPassed ? 0 : 1);
}).catch(err => {
console.error('Error:', err.message);
process.exit(2);
});
"const result = await client.assess(
async (question) => await myAI.chat(question),
{
metadata: {
gitCommit: process.env.GITHUB_SHA,
branch: process.env.GITHUB_REF_NAME,
deployVersion: process.env.VERSION,
environment: process.env.NODE_ENV
}
}
);
// Exit code for CI/CD
// 0 = passed, 1 = failed, 2 = error
process.exit(result.overallPassed ? 0 : 1);The SDK automatically detects CI/CD environments:
import { detectEnvironment, isCI } from '@aiassesstech/sdk';
console.log('Is CI:', isCI());
console.log('Environment:', detectEnvironment());
// {
// nodeVersion: 'v20.10.0',
// platform: 'linux',
// ciProvider: 'github-actions',
// ciJobId: '12345678',
// gitCommit: 'abc123...',
// gitBranch: 'main'
// }Wrap your AI callback with automatic retry logic:
import { withRetry } from '@aiassesstech/sdk';
const resilientCallback = withRetry(
async (question) => await flakyAPI.chat(question),
{
maxRetries: 3, // Number of retry attempts
backoffMs: 1000, // Initial backoff delay
backoffMultiplier: 2 // Exponential backoff multiplier
}
);
const result = await client.assess(resilientCallback);hck_...) and store it securelyMIT ยฉ AI Assess Tech