Tool & action memory

Every action a user takes in your app is a signal. Ingest it. Retrieve it. Use it to personalise every LLM interaction that follows.

Note
The pattern: whenever a user completes a meaningful action — creating a project, making a purchase, completing a task, toggling a feature — ingest a structured note. The synthesized memory will reflect their behaviour history.

What to ingest

Ingest actions as structured sentences. Be specific enough that synthesis produces useful facts.

ActionWhat to ingest
Created project"Created project 'API Gateway Rewrite' — goal: migrate from REST to GraphQL"
Made purchase"Purchased Pro plan. Previously on Free for 3 months."
Completed task"Completed 'Set up CI/CD pipeline' in the DevOps workspace"
Enabled feature"Enabled two-factor authentication on their account"
Searched for"Searched for 'webhook retry logic' three times this session"

Ingest an action

typescriptaction-memory.ts
"kw">const ANANSI_URL = "https:">class="cm">//anansimemory.com"; "kw">const ANANSI_KEY = process.env.ANANSI_API_KEY!; "kw">interface ActionEvent { userId: "kw">string; actionType: "kw">string; "kw">class="cm">// "project_created", "purchase", "task_completed", etc. description: "kw">string; "kw">class="cm">// human-readable summary of the action resourceId?: "kw">string; "kw">class="cm">// ID of the affected resource resourceType?: "kw">string; "kw">class="cm">// "project", "task", "order", etc. } "kw">export "kw">async "kw">function ingestAction(event: ActionEvent) { "kw">await fetch(`${ANANSI_URL}/v1/ingest`, { method: "POST", headers: { Authorization: `Bearer ${ANANSI_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ userId: event.userId, content: event.description, sourceType: "action", metadata: { actionType: event.actionType, resourceId: event.resourceId, resourceType: event.resourceType, timestamp: "kw">new Date().toISOString(), }, }), }); } "kw">class="cm">// Wire it up to your app events "kw">await ingestAction({ userId: "user_abc", actionType: "project_created", description: "Created project 'API Gateway Rewrite' with goal: migrate ">from REST to GraphQL. Team size: 3.", resourceId: "proj_xyz", resourceType: "project", }); "kw">await ingestAction({ userId: "user_abc", actionType: "task_completed", description: "Completed task 'Set up OpenTelemetry SDK' in the API Gateway Rewrite project.", resourceId: "task_123", resourceType: "task", });

Retrieve action history for personalisation

After a few actions, the synthesized profile reflects the user's behaviour pattern. Use it to personalise every subsequent LLM response.

typescript
"kw">class="cm">// Before "kw">any LLM call for this user "kw">const memory = "kw">await fetch( `${ANANSI_URL}/v1/context?userId=user_abc&q=${encodeURIComponent(userQuestion)}`, { headers: { Authorization: `Bearer ${ANANSI_KEY}` } } ).then((r) => r.json()); "kw">class="cm">// memory.static will contain synthesized action history: "kw">class="cm">// "Working on API Gateway Rewrite project (REST to GraphQL migration)" "kw">class="cm">// "Completed CI/CD and OpenTelemetry setup tasks" "kw">class="cm">// "Active in DevOps workspace" "kw">class="cm">// memory.relevant will surface specific action chunks: "kw">class="cm">// relevant[0].metadata.actionType === "project_created" "kw">class="cm">// relevant[0].metadata.resourceId === "proj_xyz"

Recommended action types

typescript
"kw">class="cm">// Use consistent actionType strings — they appear in metadata and "kw">class="cm">// help you filter relevant[] results by action category later. "kw">type ActionType = | "project_created" | "project_updated" | "project_completed" | "task_created" | "task_completed" | "task_blocked" | "purchase" | "upgrade" | "downgrade" | "feature_enabled" | "feature_disabled" | "search" | "">export" | "share" | "login" | "onboarding_step";