@personize/sdk
v0.6.6
Published
Official Personize SDK
Downloads
1,250
Readme
Personize SDK
The official Node.js/TypeScript SDK for the Personize Product API. Authenticate with your secret key to access guidelines, smart guidelines, RAG memory, prompt execution, agents, and evaluation tools.
Installation
npm install @personize/sdkQuick Start
import { Personize } from '@personize/sdk';
const client = new Personize({
secretKey: 'sk_live_...',
// baseURL: 'http://localhost:3000' // Optional: for local development
});
// Verify API key
const testResult = await client.test();
console.log(testResult.data.organizationId);
// Read plan limits
const me = await client.me();
console.log(me.data.plan.name);
console.log(me.data.plan.limits);API Endpoints
| Method | Path | SDK Method |
| :--- | :--- | :--- |
| Identity | | |
| GET | /api/v1/test | client.test() |
| GET | /api/v1/me | client.me() |
| AI | | |
| POST | /api/v1/ai/smart-guidelines | client.ai.smartGuidelines(opts) |
| POST | /api/v1/prompt | client.ai.prompt(opts) |
| POST | /api/v1/prompt (stream) | client.ai.promptStream(opts) |
| Memory | | |
| POST | /api/v1/memorize | client.memory.memorize(opts) |
| POST | /api/v1/smart-recall | client.memory.smartRecall(opts) |
| POST | /api/v1/recall | client.memory.recall(opts) |
| POST | /api/v1/search | client.memory.search(opts) |
| POST | /api/v1/batch-memorize | client.memory.memorizeBatch(opts) |
| POST | /api/v1/smart-memory-digest | client.memory.smartDigest(opts) |
| POST | /api/v1/memory/properties | client.memory.properties(opts) |
| Guidelines | | |
| GET | /api/v1/guidelines | client.guidelines.list() |
| POST | /api/v1/guidelines | client.guidelines.create(payload) |
| GET | /api/v1/guidelines/:id/structure | client.guidelines.getStructure(id) |
| GET | /api/v1/guidelines/:id/section | client.guidelines.getSection(id, opts) |
| PATCH | /api/v1/guidelines/:id | client.guidelines.update(id, payload) |
| DELETE | /api/v1/guidelines/:id | client.guidelines.delete(id) |
| GET | /api/v1/actions/:id/history | client.guidelines.history(id) |
| Collections | | |
| GET | /api/v1/collections | client.collections.list() |
| POST | /api/v1/collections | client.collections.create(payload) |
| PATCH | /api/v1/collections/:id | client.collections.update(id, payload) |
| DELETE | /api/v1/collections/:id | client.collections.delete(id) |
| GET | /api/v1/collections/:id/history | client.collections.history(id) |
| Agents | | |
| GET | /api/v1/agents | client.agents.list() |
| GET | /api/v1/agents/:id | client.agents.get(id) |
| POST | /api/v1/agents/:id/run | client.agents.run(id, opts) |
| Evaluation | | |
| POST | /api/v1/evaluate/memorization-accuracy | client.evaluate.memorizationAccuracy(opts) |
All endpoints require Authorization: Bearer sk_live_... and count against your plan limits.
Usage
Guidelines
// List all guidelines
const vars = await client.guidelines.list();
// Create a guideline
await client.guidelines.create({ name: 'ICP', value: '...', tags: ['sales'] });
// Update a guideline
await client.guidelines.update(guidelineId, { value: 'new content' });
// Get guideline structure (headings)
const structure = await client.guidelines.getStructure(guidelineId);
// Get a specific section
const section = await client.guidelines.getSection(guidelineId, { header: '## Pricing' });
// Delete a guideline
await client.guidelines.delete(guidelineId);
// Version history
const history = await client.guidelines.history(guidelineId, { limit: 5 });Smart Guidelines
const ctx = await client.ai.smartGuidelines({
message: 'Write a sales sequence for our top 3 ICPs',
tags: ['sales'],
excludeTags: ['internal'],
sessionId: 'my-session', // for incremental context delivery
});
console.log(ctx.data.compiledContext);Content Budget
Control how much guideline content is delivered:
const result = await client.ai.smartGuidelines({
message: "write a cold email",
maxContentTokens: 5000, // deliver ~2-3 full guidelines, rest as summaries
});
// Demoted guidelines (over budget) returned with id + description for follow-up
if (result.data.budgetMetadata?.demotedGuidelines) {
for (const g of result.data.budgetMetadata.demotedGuidelines) {
// Fetch specific section: client.guidelines.getSection(g.id, { header: "Cold Email" })
console.log(`${g.name}: ${g.description} — sections: ${g.sections.join(', ')}`);
}
}Default: 10,000 tokens. Guidelines too large for the budget are automatically trimmed to relevant sections. Remaining guidelines are returned as summaries with id, description, and sections[] for follow-up via client.guidelines.getSection().
Prompt Execution
// Simple prompt (defaults to 'pro' tier)
const response = await client.ai.prompt({
prompt: 'Summarize our Q4 sales strategy',
});
console.log(response.data?.metadata?.creditsCharged); // credits used
// With explicit tier
const fast = await client.ai.prompt({
prompt: 'Quick summary of today',
tier: 'basic', // cheapest, fastest
});
const premium = await client.ai.prompt({
prompt: 'Deep analysis of market trends',
tier: 'ultra', // highest quality model
});
// BYOK — use your own API key + model + provider (Pro/Enterprise plans only)
const byok = await client.ai.prompt({
prompt: 'Generate a report',
openrouterApiKey: 'sk-or-v1-...', // your OpenRouter key
model: 'anthropic/claude-sonnet-4-20250514',
provider: 'openrouter',
});
// BYOK billing: flat 5 credits/call — no per-token charge, you pay your provider directly
// Without BYOK, model/provider are rejected — use tier to control quality level
// Multi-step instructions with evaluation
const result = await client.ai.prompt({
instructions: [
{ prompt: 'Analyze the data', maxSteps: 5 },
{ prompt: 'Write a summary based on the analysis', maxSteps: 3 },
],
evaluate: { criteria: 'sales', serverSide: true },
});
// Multimodal — image analysis
const analysis = await client.ai.prompt({
prompt: 'Describe what you see in this screenshot.',
attachments: [
{ name: 'dashboard.png', mimeType: 'image/png', data: base64EncodedImage },
],
});
// Multimodal — PDF extraction via URL
const extraction = await client.ai.prompt({
prompt: 'Extract the key terms from this contract.',
attachments: [
{ name: 'contract.pdf', mimeType: 'application/pdf', url: 'https://your-bucket.s3.amazonaws.com/contract.pdf' },
],
});
// Output extraction + auto-memorize
const research = await client.ai.prompt({
instructions: [
{ prompt: 'Research the company using search tools', maxSteps: 5 },
{ prompt: 'Write a personalized outreach email', maxSteps: 3 },
],
outputs: [
{ name: 'company_profile' },
{ name: 'outreach_email' },
],
memorize: {
email: '[email protected]',
websiteUrl: 'acme.com',
type: 'Company',
captureToolResults: true,
},
evaluate: { criteria: 'sales', serverSide: true },
});
console.log(research.data?.outputs?.company_profile);
console.log(research.data?.evaluation?.finalScore);Streaming Prompt Execution
promptStream() returns an async generator that yields Server-Sent Events as they arrive. Use this for real-time UI updates, progressive output delivery, or when you need structured outputs as soon as each one finishes generating.
import type { PromptSSEEvent } from '@personize/sdk';
// Stream with structured outputs — events arrive as each output closes
for await (const event of client.ai.promptStream({
prompt: 'Generate a hero section and social proof for our landing page',
outputs: [
{ name: 'hero' },
{ name: 'social_proof' },
],
})) {
switch (event.type) {
case 'text':
// Raw LLM text chunks (everything outside <output> markers)
process.stdout.write(event.chunk);
break;
case 'output':
// A named output extracted — fired once per output as soon as </output> closes
// event.data is already parsed (JSON object or plain string)
console.log(`Output "${event.name}":`, event.data);
break;
case 'done':
// Final event — includes all outputs, evaluation, and metadata
console.log('All outputs:', event.outputs);
console.log('Metadata:', event.metadata);
break;
case 'error':
// Non-fatal error during streaming
console.error('Stream error:', event.message);
break;
}
}SSE Event Types:
| Event | Frequency | Description |
| :--- | :--- | :--- |
| text | Many per response | Plain text chunks from the LLM |
| output | Once per named output | Extracted output (JSON or string) — fired as soon as </output> closes |
| step_complete | Once per instruction step | Multi-step mode: step metadata |
| done | Once at end | Final reconciliation with all outputs + metadata |
| error | 0 or more | Non-fatal streaming errors |
Options:
| Option | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| streamTimeout | number | 120000 | Overall stream timeout in ms |
| signal | AbortSignal | — | External abort signal for cancellation |
All other PromptOptions parameters (outputs, context, instructions, tier, memorize, evaluate, etc.) are supported.
Cancellation:
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000); // cancel after 5s
for await (const event of client.ai.promptStream({
prompt: '...',
signal: controller.signal,
})) {
// ...
}Entity Identifiers
All memory endpoints support multiple CRM key types for entity scoping:
| Key | Use case |
|-----|----------|
| email | Contact lookup |
| websiteUrl | Company lookup |
| recordId | Direct record ID |
| customKeyName + customKeyValue | Custom CRM field (e.g. hubspot_id) |
| phoneNumber | Phone-based lookup |
| postalCode | Location-based lookup |
| deviceId | Device-based lookup |
| contentId | Content-based lookup |
You can pass multiple keys simultaneously for better matching.
Memory (RAG)
// Memorize content (dual extraction: structured + free-form)
// Response includes recordId for immediate use in recall/digest calls
const memorized = await client.memory.memorize({
content: 'Meeting notes: John prefers email contact. He is VP of Sales at Acme Corp.',
speaker: 'Sales Rep',
enhanced: true,
tags: ['meetings'],
email: '[email protected]',
});
console.log(memorized.data?.recordId); // REC#<hex> — deterministic, use for recall/digest
// Smart recall — deep mode (default): reflection + answer generation, ~10-20s, 2 credits
const results = await client.memory.smartRecall({
query: 'What does John prefer?',
limit: 5,
minScore: 0.7,
mode: 'deep',
});
// Smart recall — fast mode: skips reflection, ~500ms, 1 credit
const fast = await client.memory.smartRecall({
query: 'contact info for John',
email: '[email protected]',
mode: 'fast',
// min_results: 10 (default in fast mode — always returns top N even below score threshold)
});
// Custom keys — bring your own identifier for any entity type
// Use customKeyName/customKeyValue when email or websiteUrl don't apply.
// The recordId is generated deterministically from orgId + type + key — same key always resolves to the same record.
await client.memory.memorize({
content: 'Student enrolled in Advanced AI course. GPA 3.8, Dean\'s List.',
type: 'Student',
customKeyName: 'studentNumber',
customKeyValue: 'S-2024-1234',
enhanced: true,
});
// More examples: LinkedIn profiles, web pages, code files, products...
await client.memory.memorize({ content: '...', type: 'Person', customKeyName: 'linkedinUrl', customKeyValue: 'https://linkedin.com/in/johndoe' });
await client.memory.memorize({ content: '...', type: 'Webpage', customKeyName: 'pageUrl', customKeyValue: 'https://docs.example.com/api/auth' });
await client.memory.memorize({ content: '...', type: 'File', customKeyName: 'filePath', customKeyValue: 'src/auth/oauth.ts' });
await client.memory.memorize({ content: '...', type: 'Product', customKeyName: 'sku', customKeyValue: 'PRD-X100-BLK' });
// Recall by the same custom key — no need to know the recordId
const student = await client.memory.smartRecall({
query: 'What courses is this student enrolled in?',
type: 'Student',
customKeyName: 'studentNumber',
customKeyValue: 'S-2024-1234',
mode: 'fast',
});
// Direct recall — DynamoDB lookup: properties + freeform memories (no AI, type required)
const direct = await client.memory.recall({
query: 'What do we know about Acme?',
type: 'Contact',
email: '[email protected]',
});
// direct.data.memories — structured properties from Snapshot
// direct.data.freeformMemories — AI-extracted memories from Freeform table
// Direct recall by custom key
const student = await client.memory.recall({
query: 'Academic record',
type: 'Student',
customKeyName: 'studentNumber',
customKeyValue: 'S-2024-1234',
});
// Search/filter records by property conditions — works with any type value
const found = await client.memory.search({
groups: [{
conditions: [{ property: 'company-name', operator: 'equals', value: 'Acme Corp' }],
}],
returnRecords: true,
pageSize: 50,
});
// Search across a custom entity type
const deansList = await client.memory.search({
type: 'Student',
returnRecords: true,
groups: [{
conditions: [{ property: 'gpa', operator: 'GTE', value: 3.5 }],
}],
});
// Access property values: records[recordId][propertyName].value (plain string)
for (const [recordId, props] of Object.entries(found.data?.records ?? {})) {
const email = props['email']?.value; // plain string — whatever was stored
const company = props['company-name']?.value;
console.log(`${recordId}: ${email} at ${company}`);
}
// Note: 'email' and 'company-name' must match the property names in your collection definition
// --- Advanced Search Patterns ---
// Key-only lookup: find a record by email without needing property conditions
const byEmail = await client.memory.search({
email: '[email protected]',
returnRecords: true,
});
// Key-only lookup: find a record by custom key (no groups needed)
const byStudentNumber = await client.memory.search({
type: 'Student',
customKeyName: 'studentNumber',
customKeyValue: 'S-2024-1234',
returnRecords: true,
});
// Secondary key: find Students where email is a secondary attribute (not the primary key)
// Works because memorize stores all CRM keys on every LanceDB row
const studentByEmail = await client.memory.search({
type: 'Student',
email: '[email protected]',
returnRecords: true,
});
// Cross-type search: find ALL records with this email across ALL entity types
// Returns Contacts, Students, Employees — whatever has this email
const crossType = await client.memory.search({
email: '[email protected]',
returnRecords: true,
});
// Property-value lookup: find records by a stored property (e.g. LinkedIn URL)
// Use this when the lookup key is a property value, not a CRM identifier
const byLinkedIn = await client.memory.search({
type: 'Contact',
returnRecords: true,
groups: [{
conditions: [{ property: 'linkedin_url', operator: 'EQ', value: 'https://linkedin.com/in/johndoe' }],
}],
});
// Batch sync — unified call with per-property extractMemories control
// IMPORTANT: Set extractMemories: true on rich text fields (notes, transcripts, descriptions)
// to enable AI extraction and semantic search. Without it, only structured storage occurs.
await client.memory.memorizeBatch({
source: 'Hubspot',
mapping: {
entityType: 'contact',
// email: 'email' means "use the 'email' field from each row as the contact identifier"
// The value must match the key name in your rows array (e.g., row.email)
// Use websiteUrl instead for Company records, or recordId for direct ID matching
email: 'email',
properties: {
email: { sourceField: 'email', collectionId: 'col_std', collectionName: 'Standard', extractMemories: false },
full_name: { sourceField: 'fullname', collectionId: 'col_std', collectionName: 'Standard', extractMemories: false },
notes: { sourceField: 'notes', collectionId: 'col_gen', collectionName: 'Generated', extractMemories: true },
},
},
rows: [
{ email: '[email protected]', fullname: 'John Smith', notes: 'VP Sales, interested in enterprise plan' },
],
});
// Batch sync with custom keys — for non-Contact/Company entity types
await client.memory.memorizeBatch({
source: 'University DB',
mapping: {
entityType: 'Student',
customKeyName: 'studentNumber', // the identifier name
customKey: 'student_id', // source field in rows holding the value
properties: {
full_name: { sourceField: 'name', collectionId: 'col_std', collectionName: 'Standard', extractMemories: false },
gpa: { sourceField: 'gpa', collectionId: 'col_std', collectionName: 'Standard', extractMemories: false },
notes: { sourceField: 'notes', collectionId: 'col_gen', collectionName: 'Generated', extractMemories: true },
},
},
rows: [
{ student_id: 'S-2024-1234', name: 'Alice Chen', gpa: '3.8', notes: 'Dean\'s List, AI research focus' },
{ student_id: 'S-2024-5678', name: 'Bob Park', gpa: '3.5', notes: 'Full-stack internship at Stripe' },
],
});
// Smart memory digest — compiled context for an entity
const digest = await client.memory.smartDigest({
email: '[email protected]',
type: 'Contact',
token_budget: 1000,
});
console.log(digest.data?.compiledContext); // ready-to-use markdown for LLM prompts
Get Record Properties
Fetch current property values for a record, joined with collection schema descriptions and the update flag.
// Get specific properties with schema info
const result = await client.memory.properties({
email: '[email protected]',
propertyNames: ['Tasks', 'Lifecycle Stage'],
nonEmpty: true,
});
for (const prop of result.data.properties) {
console.log(`${prop.name}: ${JSON.stringify(prop.value)}`);
console.log(` Type: ${prop.type}, Update: ${prop.update}`);
console.log(` Description: ${prop.description}`);
}Each property includes:
value— current valuedescription— from the collection schema, tells AI how to interpret/updateupdate—truemeans replaceable (usememory.update()withpropertyValue),falsemeans append-only (usearrayPush)type— property type (text,number,boolean,array,date,options)collectionName— which collection this property belongs to
Options:
propertyNames— filter to specific properties (recommended to save tokens)includeDescriptions— join with collection schema (default:true)nonEmpty— exclude null/empty values (default:false)- Identifiers:
email,websiteUrl,recordId,customKeyName+customKeyValue
Agents
// List agents
const agents = await client.agents.list();
// Get agent details and expected inputs
const agent = await client.agents.get(agentId);
console.log(agent.data.expectedInputs); // ['companyName', 'industry']
// Run an agent
const result = await client.agents.run(agentId, {
inputs: { companyName: 'Acme Corp', industry: 'SaaS' },
email: '[email protected]',
});Collections
// List collections
const collections = await client.collections.list();
// Create a collection
await client.collections.create({
collectionName: 'Deal Properties',
entityType: 'Contact',
properties: [
{ propertyName: 'Deal Stage', type: 'options', options: 'Discovery,Proposal,Closed' },
],
});
// Update a collection
await client.collections.update(collectionId, {
properties: [{ propertyName: 'Budget', type: 'number', description: 'Estimated budget' }],
});
// Delete a collection
await client.collections.delete(collectionId);
// Version history (full snapshots or compact diffs)
const history = await client.collections.history(collectionId, { mode: 'diff', limit: 10 });Evaluation
// Run memorization accuracy evaluation against a collection
const evaluation = await client.evaluate.memorizationAccuracy({
collectionId: 'col_123',
input: 'John Smith is VP of Sales at Acme Corp, based in NYC.',
skipStorage: true,
});
console.log(evaluation.data.summary.propertiesOptimized);Tiers & Pricing
Generate Tiers (Prompt)
| Tier | Input Credits/1K tokens | Output Credits/1K tokens | Best For |
| :--- | :--- | :--- | :--- |
| basic | 1.0 | 2.0 | High-volume, simple tasks |
| pro | 1.0 | 3.0 | Balanced quality & cost (default) |
| ultra | 1.0 | 5.0 | Complex reasoning, highest quality |
Memorize Tiers
| Tier | Credits/1K tokens | Best For |
| :--- | :--- | :--- |
| basic | 1 | Bulk imports, simple data |
| pro | 3 | General use (default) |
| pro_fast | 5 | Pro quality, lower latency |
| ultra | 12 | Maximum extraction quality |
Retrieval (Recall & Smart Guidelines)
| Operation | Mode | Credits/Call |
| :--- | :--- | :--- |
| Smart Recall | mode: 'fast' | 1 |
| Smart Recall | mode: 'deep' | 2 |
| Smart Guidelines | mode: 'fast' | 1 |
| Smart Guidelines | mode: 'deep' | 1 |
Smart Recall cost depends on mode: fast = 1 credit, deep = 2 credits. All other read operations (recall, smart guidelines, smart context) charge a flat 1 credit per call.
1 credit = $0.01.
Direct Providers
BYOK (Bring Your Own Key)
Pro and Enterprise plans can pass their own API key. Billing switches to a flat 5 credits per call (no per-token charge — you pay your provider directly).
When using BYOK, you must provide both model and provider. Without BYOK, model and provider are rejected — use tier to control quality level.
// BYOK: must specify all three
await client.ai.prompt({
prompt: '...',
openrouterApiKey: 'sk-or-v1-...',
model: 'anthropic/claude-sonnet-4-20250514',
provider: 'openrouter',
});
// Without BYOK: use tier (model/provider auto-selected)
await client.ai.prompt({
prompt: '...',
tier: 'pro', // basic, pro (default), ultra
});Error cases:
model/providerwithoutopenrouterApiKey→400 BYOK requiredopenrouterApiKeywithoutmodel/provider→400 model and provider required- BYOK on a plan that doesn't allow it →
403 byok_not_allowed
Response metadata includes byok: true and creditsCharged reflecting the flat 5-credit charge.
Smart Recall Modes
The mode parameter controls smart recall behavior:
| Mode | Latency | Credits | Description |
| :--- | :--- | :--- | :--- |
| "fast" | ~500ms | 1 | Skips reflection and answer generation. Returns raw vector results with guaranteed minimum count. |
| "deep" | ~10-20s | 2 | Enables reflection + answer generation for higher-quality, synthesized responses. |
Default is "deep". The mode parameter takes precedence over the individual enable_reflection, generate_answer, and fast_mode flags. If mode is set, those flags are ignored.
Recency Bias
Use prefer_recent to boost recent memories with exponential decay:
const result = await client.memory.smartRecall({
query: "what changed on this contact recently?",
email: "[email protected]",
mode: "deep",
prefer_recent: true,
recency_half_life_days: 30, // aggressive: 30-day half-life
});Default half-life is 90 days. A memory 90 days old scores ~37% of its original relevance. Set to 7-30 for "what happened this week/month" queries.
Best Practices: Query Crafting for smartRecall
The smartRecall endpoint uses vector similarity search. Query quality directly impacts result relevance. When building AI pipelines that call smartRecall, the AI agent is responsible for crafting embedding-friendly queries.
Do:
- Use specific, descriptive queries that match the language of stored data
- Include entity names, property names, or domain-specific terms
- Example:
"John Smith role title company background"instead of"Tell me about this contact"
Don't:
- Use vague meta-queries like
"What do we know?"or"Tell me everything" - Use task-oriented queries like
"open tasks pending action items"when only profile data was memorized
Example — AI pipeline pattern:
// BAD: vague query → low similarity scores → few or no results
const bad = await client.memory.smartRecall({ query: 'Tell me about this contact', email });
// GOOD: specific query targeting stored data types
const good = await client.memory.smartRecall({
query: `${contactName} role company background interests preferences`,
email,
mode: 'fast',
});Guaranteed minimum results: In mode: 'fast', smartRecall guarantees at least 10 results (configurable via min_results) even when scores fall below the threshold. This ensures your AI workflow always has context to reason about — it can then decide whether the data is sufficient or not.
Configuration
| Option | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| secretKey | string | Yes | Your secret key (sk_live_...). |
| baseURL | string | No | Custom API endpoint (default: https://agent.personize.ai). |
| timeout | number | No | Request timeout in ms (default: 30000). |
| maxRetries | number | No | Max retry attempts for 429/5xx errors (default: 3). |
| retryDelay | number | No | Base delay in ms for exponential backoff (default: 1000). |
Test Key (Local Development)
const client = new Personize({
secretKey: 'sk_live_TEST_KEY_00000000000000000000000000000000000000000000000000000000',
baseURL: 'http://localhost:3000',
});Migration from 0.6.2
New in 0.6.3:
| Feature | Details |
| :--- | :--- |
| evaluationCriteria on PromptOptions | Compatibility alias for evaluate: { criteria, serverSide: true } |
| message on RecallOptions / SmartRecallOptions | Compatibility alias for query |
| Legacy memory.recall() routing | If you call recall() with legacy advanced-recall-style inputs (message, limit, omitted type, collection-name scoping), the SDK routes to /smart-recall automatically |
| Shorthand semantic memory.search() | search({ query, limit, collectionName }) is accepted and routed to /smart-recall when no filter groups are provided |
| collectionName / collectionNames on memorize() | Collection names are resolved client-side into collectionIds |
| Legacy collection payload aliases | collections.create() now accepts name, slug, description, array options, and updateSemantics |
| records shorthand on memorizeBatch() | Accepts record-style input and normalizes it client-side into memorize() + /batch-memorize calls |
See SDK_0_6_3_COMPATIBILITY_CHANGES.md for the full design notes and tradeoffs.
Migration from 0.5.x
New in 0.6.0:
| Feature | Details |
| :--- | :--- |
| tier on PromptOptions | Select generate tier: basic, pro (default), ultra |
| tier on MemorizeOptions / BatchMemorizeOptions | Select memorize tier: basic, pro, pro_fast, ultra |
| openrouterApiKey on PromptOptions | BYOK — use your own API key (Pro/Enterprise plans). Requires model + provider. |
| model / provider on PromptOptions | Custom model/provider selection. Requires BYOK (openrouterApiKey). Without BYOK, use tier. |
| creditsCharged in response metadata | Credits consumed by the request |
| SmartGuidelines mode: 'full' → mode: 'deep' | Renamed for consistency. 'full' still accepted for backward compatibility. |
Migration from 0.3.x
Breaking changes in 0.4.0:
| 0.3.x | 0.4.0 | Notes |
| :--- | :--- | :--- |
| client.memory.recall(opts) | client.memory.smartRecall(opts) | Advanced recall with reflection (route changed to /smart-recall) |
| client.memory.export(opts) | client.memory.search(opts) | Filter/search records (route changed to /search) |
| MemorizeProOptions | MemorizeOptions | Type renamed (old name still available as deprecated alias) |
| RecallProOptions | SmartRecallOptions | Type renamed (old name still available as deprecated alias) |
| ExportOptions / ExportResponse | SearchOptions / SearchResponse | Types renamed (old names still available as deprecated aliases) |
New in 0.4.0:
client.test()— Verify API key validityclient.agents.get(id)— Get agent details and expected inputsclient.memory.recall(opts)— Direct DynamoDB lookup: properties + freeform memories (no AI)client.memory.search(opts)— Search/filter records withproperty-based conditionsclient.evaluate.memorizationAccuracy(opts)— Three-phase memorization evaluationattachmentsonPromptOptions— Multimodal support (images, PDFs, documents)sessionIdonSmartGuidelinesOptions— Progressive context delivery across multi-step workflows- New fields on
MemorizeOptions:collectionIds,skipStorage,skipDualWrite,skipPropertySelection - New fields on
SmartRecallOptions:max_reflection_rounds,filters
Skills
AI-assistant skills for Claude Code, Codex, and Cursor are available separately:
npx skills add personizeai/personize-skills --allSee personizeai/personize-skills for the full catalog.
