@rbkunnela/alma-memory
v0.7.0
Published
TypeScript/JavaScript SDK for ALMA Memory - Persistent memory for AI agents
Maintainers
Readme
ALMA Memory - TypeScript/JavaScript SDK
Official TypeScript/JavaScript SDK for ALMA Memory - Persistent memory for AI agents.
Features
- Type-Safe: Full TypeScript support with comprehensive type definitions
- Zero Dependencies: Uses native
fetch(Node.js 18+) - Dual Package: Supports both CommonJS and ES Modules
- Retry Logic: Built-in exponential backoff for reliability
- Error Handling: Rich error types for precise error handling
- JSDoc Comments: Comprehensive documentation for IDE support
Installation
npm install alma-memory
# or
yarn add alma-memory
# or
pnpm add alma-memoryRequirements
- Node.js 18.0.0 or higher (for native
fetchsupport) - A running ALMA MCP server
Quick Start
import { ALMA } from 'alma-memory';
// Create client
const alma = new ALMA({
baseUrl: 'http://localhost:8765',
projectId: 'my-project',
});
// Retrieve relevant memories for a task
const result = await alma.retrieve({
query: 'authentication flow',
agent: 'dev-agent',
topK: 5,
});
console.log(result.memories?.heuristics);
// Inject memories into your prompt
console.log(result.prompt_injection);API Reference
Creating a Client
import { ALMA, createClient } from 'alma-memory';
// Using constructor
const alma = new ALMA({
baseUrl: 'http://localhost:8765',
projectId: 'my-project',
timeout: 30000, // optional, default 30s
headers: { 'X-Custom': 'value' }, // optional
retry: {
maxRetries: 3, // optional, default 3
baseDelay: 1000, // optional, default 1000ms
maxDelay: 10000, // optional, default 10000ms
},
});
// Using helper function
const alma2 = createClient({
baseUrl: 'http://localhost:8765',
projectId: 'my-project',
});Retrieving Memories
Retrieve relevant memories for a task context:
const result = await alma.retrieve({
query: 'form validation testing', // Description of current task
agent: 'qa-agent', // Agent name
userId: 'user-123', // Optional: for user preference retrieval
topK: 10, // Optional: max items per memory type (default: 5)
});
// Check success
if (result.success) {
// Access memories by type
console.log('Heuristics:', result.memories?.heuristics);
console.log('Anti-patterns:', result.memories?.anti_patterns);
console.log('User preferences:', result.memories?.preferences);
console.log('Domain knowledge:', result.memories?.domain_knowledge);
// Use formatted prompt injection
const prompt = `${result.prompt_injection}\n\nNow perform the task...`;
}Learning from Outcomes
Record task outcomes to build the memory system:
// Record successful outcome
await alma.learn({
agent: 'dev-agent',
task: 'Implement user authentication',
taskType: 'authentication', // Optional: for grouping
outcome: 'success',
strategyUsed: 'Used JWT with refresh tokens and PKCE',
durationMs: 45000, // Optional
});
// Record failure with error details
await alma.learn({
agent: 'dev-agent',
task: 'Deploy to production',
outcome: 'failure',
strategyUsed: 'Direct push to main branch',
errorMessage: 'CI tests failed due to missing environment variables',
feedback: 'Should use feature branches', // Optional user feedback
});Adding User Preferences
Store user preferences that persist across sessions:
await alma.addPreference({
userId: 'user-123',
category: 'code_style', // or 'communication', 'workflow', etc.
preference: 'Always use TypeScript strict mode',
source: 'explicit_instruction', // or 'inferred_from_feedback'
});Adding Domain Knowledge
Store factual knowledge within an agent's scope:
await alma.addKnowledge({
agent: 'dev-agent',
domain: 'authentication',
fact: 'The API uses OAuth 2.0 with PKCE for mobile clients',
source: 'documentation', // or 'code_analysis', 'user_stated'
});Pruning Memories
Clean up old or low-confidence memories:
// Prune all agents
const result = await alma.forget({
olderThanDays: 90, // Remove outcomes older than 90 days
belowConfidence: 0.3, // Remove heuristics below 30% confidence
});
console.log(`Pruned ${result.pruned_count} memories`);
// Prune specific agent
await alma.forget({
agent: 'test-agent',
olderThanDays: 30,
});Getting Statistics
// All agents
const allStats = await alma.stats();
console.log(`Total memories: ${allStats.stats?.total_count}`);
console.log(`Heuristics: ${allStats.stats?.heuristics_count}`);
// Specific agent
const agentStats = await alma.stats('dev-agent');Health Check
const health = await alma.health();
if (health.status === 'healthy') {
console.log(`Server healthy with ${health.total_memories} memories`);
console.log(`Registered agents: ${health.registered_agents?.join(', ')}`);
}Error Handling
The SDK provides specific error types for different failure scenarios:
import {
ALMA,
ALMAError,
ConnectionError,
ValidationError,
TimeoutError,
ServerError,
ScopeViolationError,
isConnectionError,
isValidationError,
} from 'alma-memory';
try {
await alma.retrieve({ query: 'test', agent: 'my-agent' });
} catch (error) {
if (isConnectionError(error)) {
console.error(`Cannot connect to server at ${error.url}`);
// Show retry UI or check server status
} else if (isValidationError(error)) {
console.error(`Invalid input: ${error.field} - ${error.message}`);
// Show validation error to user
} else if (error instanceof TimeoutError) {
console.error(`Request timed out after ${error.timeout}ms`);
// Retry with longer timeout
} else if (error instanceof ServerError) {
console.error(`Server error: ${error.serverMessage}`);
// Log for debugging
}
}Error Types
| Error Class | Description | Properties |
|-------------|-------------|------------|
| ALMAError | Base error class | code, statusCode, cause |
| ConnectionError | Server unreachable | url |
| ValidationError | Invalid input | field, value |
| TimeoutError | Request timeout | timeout |
| ServerError | Server returned error | serverMessage, rpcCode |
| ScopeViolationError | Agent scope violation | agent, domain |
| NotFoundError | Resource not found | resourceType, resourceId |
TypeScript Types
All types are exported for use in your applications:
import type {
// Configuration
ALMAConfig,
RetryConfig,
// Memory types
Heuristic,
Outcome,
UserPreference,
DomainKnowledge,
AntiPattern,
MemorySlice,
MemoryScope,
MemoryType,
// Request options
RetrieveOptions,
LearnOptions,
AddPreferenceOptions,
AddKnowledgeOptions,
ForgetOptions,
// Response types
RetrieveResponse,
LearnResponse,
StatsResponse,
HealthResponse,
} from 'alma-memory';Usage with AI Frameworks
With LangChain
import { ALMA } from 'alma-memory';
import { ChatOpenAI } from '@langchain/openai';
const alma = new ALMA({
baseUrl: 'http://localhost:8765',
projectId: 'langchain-project',
});
async function runWithMemory(task: string, agent: string) {
// Retrieve relevant memories
const memories = await alma.retrieve({ query: task, agent });
// Create prompt with memories
const prompt = `${memories.prompt_injection}
Task: ${task}
Please complete the task using the context above.`;
// Run LLM
const llm = new ChatOpenAI();
const result = await llm.invoke(prompt);
// Learn from outcome
await alma.learn({
agent,
task,
outcome: 'success',
strategyUsed: 'Used memory-augmented prompt',
});
return result;
}With Vercel AI SDK
import { ALMA } from 'alma-memory';
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
const alma = new ALMA({
baseUrl: 'http://localhost:8765',
projectId: 'vercel-ai-project',
});
async function chat(userMessage: string, agent: string) {
const memories = await alma.retrieve({
query: userMessage,
agent,
});
const { text } = await generateText({
model: openai('gpt-4'),
system: memories.prompt_injection,
prompt: userMessage,
});
return text;
}Configuration
Environment Variables
You can configure the client using environment variables:
const alma = new ALMA({
baseUrl: process.env.ALMA_BASE_URL || 'http://localhost:8765',
projectId: process.env.ALMA_PROJECT_ID || 'default',
timeout: parseInt(process.env.ALMA_TIMEOUT || '30000'),
});Custom Headers
Add authentication or tracking headers:
const alma = new ALMA({
baseUrl: 'http://localhost:8765',
projectId: 'my-project',
headers: {
'Authorization': `Bearer ${process.env.ALMA_TOKEN}`,
'X-Request-ID': generateRequestId(),
},
});Memory Types
ALMA supports five types of memories:
| Type | Description | Example | |------|-------------|---------| | Heuristic | Learned strategies that work | "When testing forms, validate happy path first" | | Outcome | Raw task results (success/failure) | "OAuth implementation succeeded in 45s" | | UserPreference | User constraints and preferences | "No emojis in documentation" | | DomainKnowledge | Facts about the domain | "API uses JWT with 24h expiry" | | AntiPattern | What NOT to do | "Don't use sleep() for async waits" |
Running Tests
# Run tests
npm test
# Run with coverage
npm run test:coverage
# Watch mode
npm run test:watchBuilding
# Build all formats (CJS, ESM, types)
npm run build
# Clean build artifacts
npm run cleanLicense
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please read our Contributing Guide for details.
Related
- ALMA Memory Python SDK - The original Python implementation
- ALMA MCP Server - The MCP server this SDK connects to
- Competitive Analysis - How ALMA compares to alternatives
