Concepts
Event System
Feed structured events into Magneteco memory
Event System
Magneteco's event system allows your applications to feed structured events into the memory system, not just conversations. This is crucial because:
- Important things happen outside conversations (user actions, system events)
- Structured events have higher signal-to-noise than raw text
- Events from external systems (webhooks) can enrich memory
Event Flow
┌─────────────────────────────────────────────────────────────────┐
│ EVENT SOURCES │
├──────────────┬──────────────┬──────────────┬────────────────────┤
│ Your App │ Webhooks │ Cron Jobs │ Other Services │
└──────┬───────┴──────┬───────┴──────┬───────┴────────┬───────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ MAGNETECO EVENT API │
│ POST /events POST /webhooks/:source │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ EVENT PROCESSOR │
│ 1. Validate event structure │
│ 2. Load event template for eventType │
│ 3. Transform to natural language │
│ 4. Queue for extraction (same pipeline as conversations) │
└─────────────────────────────────────────────────────────────────┘
│
▼
[Normal Memory Pipeline]Event Schema
interface MemoryEvent {
// Required
appId: string; // Your app identifier
userId: string; // User this event relates to
eventType: string; // Event type (app-specific)
source: string; // Where event originated
timestamp: string; // ISO 8601 timestamp
data: Record<string, unknown>; // Event-specific payload
// Optional hints
suggestedCategory?: string;
suggestedEntities?: Array<{
name: string;
type: string;
}>;
importance?: 'low' | 'medium' | 'high' | 'critical';
}Event Templates
Event templates transform structured events into natural language for the extraction pipeline.
Defining Templates
export const eventTemplates = {
tanda: {
sow_approved: (data) =>
`SOW "${data.sowTitle}" for project "${data.projectName}" was approved by ` +
`${data.approverName}. The project can now proceed to execution. ` +
`Client: ${data.clientName}.`,
deadline_missed: (data) =>
`IMPORTANT: Deadline missed for ${data.itemType} "${data.itemName}" on project ` +
`"${data.projectName}". Was due ${data.dueDate}, now ${data.daysOverdue} days overdue. ` +
`Client: ${data.clientName}. Escalation may be required.`,
client_feedback: (data) =>
`Client feedback received from ${data.contactName} at ${data.clientName}: ` +
`"${data.feedback}". Sentiment: ${data.sentiment}.`,
},
glapi: {
journal_posted: (data) =>
`Journal entry ${data.entryId} was posted: "${data.memo}". ` +
`Total amount: ${data.currency}${data.amount}. ` +
`Accounts affected: ${data.accounts.join(', ')}.`,
budget_exceeded: (data) =>
`Budget exceeded for ${data.accountName} (${data.accountCode}): ` +
`Spent ${data.currency}${data.actualAmount} vs budget ${data.currency}${data.budgetAmount} ` +
`(${data.percentOver}% over). Period: ${data.period}.`,
},
};Using Events
Basic Event Tracking
import { MagnetoClient } from '@magneteco/client';
const memory = new MagnetoClient({
appId: 'tanda',
baseUrl: process.env.MAGNETECO_URL,
});
// Track a simple event
await memory.trackEvent({
userId: 'user-123',
eventType: 'sow_approved',
data: {
sowTitle: 'Phase 1 Implementation',
projectName: 'NetSuite Migration',
clientName: 'Acme Corp',
approverName: 'Jane Smith',
},
importance: 'high',
});With Entity Hints
await memory.trackEvent({
userId: 'user-123',
eventType: 'client_feedback',
data: {
contactName: 'Bob Johnson',
clientName: 'Acme Corp',
feedback: 'Very happy with the testing coverage',
sentiment: 'positive',
},
suggestedEntities: [
{ name: 'Bob Johnson', type: 'Contact' },
{ name: 'Acme Corp', type: 'Client' },
],
});Importance Levels
| Level | Description | Processing |
|---|---|---|
low | Informational | Normal processing, lower retrieval priority |
medium | Standard events | Normal processing |
high | Important events | Higher confidence score, flagged in summaries |
critical | Must not be forgotten | Highest confidence, never pruned |
// Importance affects confidence multiplier
const confidenceMultiplier = {
low: 0.8,
medium: 1.0,
high: 1.2,
critical: 1.5,
};
// Critical events are protected from pruning
function shouldPrune(item: MemoryItem): boolean {
if (item.metadata?.importance === 'critical') return false;
// ... normal pruning logic
}Webhook Integration
Supported Sources
Magneteco can receive webhooks from external services:
stripe- Payment eventsgithub- Repository eventsnetsuite- ERP eventssalesforce- CRM eventsslack- Messaging eventscustom- Generic handler
Webhook Mappers
Each source has a mapper that validates and transforms webhooks:
interface WebhookMapper {
// Validate webhook authenticity
validateSignature?: (payload: any, headers: Record<string, string>) => boolean;
// Determine if this webhook should create a memory
shouldProcess: (payload: any) => boolean;
// Extract user ID from webhook
extractUserId: (payload: any) => string | null;
// Map to MemoryEvent
mapToEvent: (payload: any) => MemoryEvent | null;
}Example: Stripe Mapper
const stripeMapper: WebhookMapper = {
validateSignature: (payload, headers) => {
const signature = headers['stripe-signature'];
return verifyStripeSignature(payload, signature);
},
shouldProcess: (payload) => {
const relevantEvents = [
'invoice.paid',
'invoice.payment_failed',
'customer.subscription.created',
];
return relevantEvents.includes(payload.type);
},
extractUserId: (payload) => {
return payload.data.object.customer_metadata?.magneteco_user_id;
},
mapToEvent: (payload) => ({
appId: 'my-app',
userId: payload.data.object.customer_metadata?.magneteco_user_id,
eventType: payload.type.replace('.', '_'),
source: 'stripe',
timestamp: new Date(payload.created * 1000).toISOString(),
data: {
customerId: payload.data.object.customer,
amount: payload.data.object.amount_paid,
currency: payload.data.object.currency,
},
importance: payload.type === 'invoice.payment_failed' ? 'high' : 'medium',
}),
};Best Practices
Event Design
- Be specific with event types:
sow_approvednotsow_updated - Include context: Who, what, when, why
- Use consistent naming:
snake_casefor event types - Set appropriate importance: Don't overuse
critical
Template Design
- Write naturally: Templates should read like descriptions
- Include relationships: "Jane approved Bob's SOW"
- Add implications: "This means the project can proceed"
- Keep it concise: 2-3 sentences is ideal
Webhook Integration
- Validate signatures: Always verify authenticity
- Filter noise: Not every webhook needs memory
- Extract user context: Ensure proper routing
- Handle failures gracefully: Don't lose events