Docs/TypeScript SDK

TypeScript SDK

The @fetchai/agentverse-memory package provides a fully type-safe async client for the Agentverse Memory API. Ships as ESM + CJS dual output with full TypeScript declaration files. Works in Node.js 18+, Deno, and modern browsers.

Node.js 18+v0.1.0-alphanpmESM + CJS

1Installation

npm install @fetchai/agentverse-memory
# or
yarn add @fetchai/agentverse-memory
# or
pnpm add @fetchai/agentverse-memory

TypeScript types are bundled — no separate @types/ package needed.

Optional peer dependencies for framework integrations:

npm install @fetchai/agentverse-memory @langchain/core # LangChain integration
npm install @fetchai/agentverse-memory mastra # Mastra integration
npm install @fetchai/agentverse-memory vercel-ai # Vercel AI SDK integration

2Authentication

Get a free API key at memory.agentverse.ai. Explorer tier is free, includes graph memory, no credit card required.

export AVMEM_API_KEY="avmem_sk_your_key_here"
import { MemoryClient } from "@fetchai/agentverse-memory";
// Reads AVMEM_API_KEY from process.env automatically
const client = new MemoryClient({ agentId: "my-agent" });
// Or pass explicitly (useful for edge functions and multi-tenant setups)
const client = new MemoryClient({
apiKey: process.env.AVMEM_API_KEY!,
agentId: "my-agent",
baseUrl: "https://am-server-jbneh74b5q-uc.a.run.app",
timeout: 10_000, // milliseconds
});

agentId is any stable string — use consistent IDs across sessions. Suggested format: service-role-tenantId (e.g. crm-assistant-acme).

3Your First 5 Minutes

1. Store an Episode

quickstart.ts
import { MemoryClient } from "@fetchai/agentverse-memory";
const client = new MemoryClient({ agentId: "research-agent-1" });
const episode = await client.episodes.store({
content:
"User asked for Q1 revenue breakdown by region. " +
"Retrieved from Salesforce. Delivered 3-bullet summary via Slack.",
metadata: {
userId: "user_42",
sessionId: "sess_abc123",
tags: ["finance", "q1", "slack"],
},
importance: 0.8, // 0.0–1.0; higher = pheromone boost on retrieval
});
console.log(episode.id); // ep_01hxq7kn3mabc
console.log(episode.createdAt); // 2026-05-14T08:00:00.042Z
// No LLM calls at write time — 0.035ms p95 in-process engine write op (am-local)

2. Retrieve by Natural Language

const results = await client.episodes.query({
query: "What did the user ask about sales?",
limit: 5,
minScore: 0.4,
});
for (const r of results) {
console.log(`[${r.score.toFixed(2)}] ${r.content.slice(0, 80)}`);
console.log(" ↳", r.metadata.tags);
}
// [0.94] User asked for Q1 revenue breakdown by region.
// ↳ ['finance', 'q1', 'slack']

3. Store a Semantic Fact

// Store a knowledge triple (subject, predicate, object)
const fact = await client.facts.store({
subject: "Acme Corp",
predicate: "signed_contract_with",
object: "Fetch.ai",
metadata: {
validAt: "2026-01-15",
confidence: 0.95,
source: "CRM",
},
});
console.log(fact.id); // fact_02hyr9mp4n...
// Connect more facts to build the graph
await client.facts.store({
subject: "Fetch.ai", predicate: "headquartered_in", object: "London",
});
// Query the graph with natural language
const hits = await client.facts.query({ query: "Where is Fetch.ai based?", limit: 3 });
for (const h of hits) {
console.log(`${h.subject} → ${h.predicate} → ${h.object}`);
}
// Fetch.ai → headquartered_in → London

TypeScript Types

All request and response objects are exported. IDE autocompletion covers every parameter and return value.

import type {
Episode,
EpisodeStoreParams,
EpisodeQueryParams,
EpisodeQueryResult,
Fact,
FactStoreParams,
FactQueryResult,
GraphTraversalResult,
PathResult,
WorkingMemoryItem,
Procedure,
SharedSpace,
MemoryStats,
HealthStatus,
} from "@fetchai/agentverse-memory";
// Typed return values — no casting needed
const episode: Episode = await client.episodes.get("ep_01hx...");
const graph: GraphTraversalResult = await client.facts.traverseGraph({
seedNode: "Acme Corp", maxDepth: 2,
});
graph.nodes.forEach((node: Fact) => {
console.log(node.subject, node.predicate, node.object);
});

Memory Types

Episodicclient.episodes.*
const ep = await client.episodes.store({ content: "...", metadata: { ... }, importance: 0.8 });
const results = await client.episodes.query({ query: "...", limit: 5, minScore: 0.4 });
const list = await client.episodes.list({ limit: 50 });
const ep2 = await client.episodes.get("ep_01hx...");
await client.episodes.update("ep_01hx...", { content: "updated" });
await client.episodes.delete("ep_01hx...");
const timeline = await client.episodes.searchTimeline({
start: "2026-01-01T00:00:00Z", end: "2026-03-31T23:59:59Z",
});
await client.episodes.consolidate({ ids: ["ep_01hx...", "ep_02hy..."] });
Semanticclient.facts.*
const fact = await client.facts.store({ subject: "Acme Corp", predicate: "signed_contract_with",
object: "Fetch.ai", metadata: { confidence: 0.95 } });
const facts = await client.facts.query({ query: "What contracts does Acme Corp have?", limit: 10 });
// Graph traversal — A* with pheromone weights — free on all tiers
const graph = await client.facts.traverseGraph({ seedNode: "Acme Corp", maxDepth: 2 });
const path = await client.facts.findPath({ source: "Acme Corp", target: "London" });
console.log(path.nodes.map((n) => n.label).join(" → "));
// Acme Corp → Fetch.ai → London
Proceduralclient.procedures.*
const proc = await client.procedures.store({
goal: "Generate a sales report",
steps: ["1. Query Salesforce", "2. Group by region", "3. Format as markdown"],
metadata: { category: "reporting" },
});
const match = await client.procedures.lookup({ goal: "Create a monthly sales summary" });
console.log(match.steps);
Workingclient.working.*

Ephemeral key-value with optional TTL. Generic type parameter gives typed value access.

// Store active task context at the start of a task
await client.working.set({
key: "currentTask",
value: { taskId: "task_99", objective: "Summarize Q1 board report", step: 3, totalSteps: 8 },
ttlSeconds: 3600, // auto-expires; 0 = no expiry
});
// Typed read — generic parameter infers value type
const task = await client.working.get<{
taskId: string; objective: string; step: number; totalSteps: number;
}>({ key: "currentTask" });
console.log(`Step ${task.value.step} of ${task.value.totalSteps}`); // Step 3 of 8
// Update mid-task, list, clear
await client.working.set({ key: "currentTask", value: { ...task.value, step: 4 } });
const keys = await client.working.list();
await client.working.clear();

Vercel AI SDK Integration vercel-ai

Use AvmemMemoryProvider to give any generateText / streamText call access to persistent memory:

vercel-ai-example.ts
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { AvmemMemoryProvider } from "@fetchai/agentverse-memory/vercel-ai";
const memory = new AvmemMemoryProvider({ agentId: "vercel-ai-assistant" });
// First session
await generateText({
model: openai("gpt-4o"),
messages: [{ role: "user", content: "Acme Corp just renewed for $420K." }],
system: await memory.systemPrompt(), // injects past memories as context
onFinish: async (result) => {
await memory.store(result.text, "assistant"); // stores the response
},
});
// Later session — new process, same memory
const { text } = await generateText({
model: openai("gpt-4o"),
messages: [{ role: "user", content: "What's Acme's contract value?" }],
system: await memory.systemPrompt(),
});
// → "Acme Corp renewed their contract for $420K."

systemPrompt() retrieves the top-K relevant past episodes and facts and formats them as a system prompt prefix. Zero prompt engineering required.

LangChain Integration @langchain/core

langchain-example.ts
import { ChatOpenAI } from "@langchain/openai";
import { ConversationChain } from "langchain/chains";
import {
AvmemChatMessageHistory,
AvmemBufferMemory,
} from "@fetchai/agentverse-memory/langchain";
// Session-scoped episodic history — persists across process restarts
const history = new AvmemChatMessageHistory({
agentId: "langchain-assistant",
sessionId: "sess_abc123",
});
const memory = new AvmemBufferMemory({ chatHistory: history });
const chain = new ConversationChain({ llm: new ChatOpenAI({ model: "gpt-4o" }), memory });
await chain.call({ input: "Acme Corp just renewed their contract for $420K." });
// Second session — new process, same memory
// await chain.call({ input: "What's Acme's contract value?" });
// → "Acme Corp renewed their contract for $420K."

For RAG, drop in AvmemRetriever:

import { AvmemRetriever } from "@fetchai/agentverse-memory/langchain";
const retriever = new AvmemRetriever({
agentId: "langchain-assistant",
memoryTypes: ["episodic", "semantic"], // query both stores
limit: 8,
});
const qa = RetrievalQAChain.fromLLM(new ChatOpenAI({ model: "gpt-4o" }), retriever);
const answer = await qa.call({ query: "What contracts did Acme Corp renew?" });

Mastra Integration mastra

mastra-example.ts
import { Agent } from "@mastra/core/agent";
import { openai } from "@ai-sdk/openai";
import { AgentverseMemoryTool } from "@fetchai/agentverse-memory/mastra";
const memoryTool = new AgentverseMemoryTool({ agentId: "mastra-research-agent" });
const researcher = new Agent({
name: "Senior Research Analyst",
instructions: "You are a thorough analyst who never forgets a finding. " +
"Always query memory before starting work, and store key findings.",
model: openai("gpt-4o"),
tools: { memory: memoryTool },
});
const result = await researcher.generate(
"Research Mem0's pricing changes from April 2026. " +
"Store each key finding. Query past research first."
);

Shared Spaces Builder+

shared-space.ts
// Orchestrator creates a shared memory space
const space = await client.spaces.create({ name: "research-team-memory" });
// Worker agent joins via invite token
const workerClient = new MemoryClient({ apiKey: "...", agentId: "worker-1" });
await workerClient.spaces.join({ spaceId: space.id, inviteToken: space.inviteToken });
// Any agent in the space queries the shared knowledge graph
const results = await client.spaces.query({
spaceId: space.id,
query: "What did the team discover about Acme Corp?",
limit: 10,
});

Pheromone Graph Traversal Phase 3 Preview

LadybugDB graph FFI wiring is in active development (Phase 3). Available in v0.2.0. The API surface below is final.
// Traverse from a seed concept — pheromone-weighted edges
const graph = await client.facts.traverseGraph({
seedNode: "Acme Corp", maxDepth: 2, limit: 20,
});
for (const node of graph.nodes) {
console.log(
`${node.subject} --[${node.predicate}]--> ${node.object}`,
` (weight: ${node.pheromoneWeight.toFixed(3)})`
);
}
// Acme Corp --[signed_contract_with]--> Fetch.ai (weight: 0.847)
// Fetch.ai --[headquartered_in]-----> London (weight: 0.612)
// A* pathfinding (Builder tier and above)
const path = await client.facts.findPath({ source: "Acme Corp", target: "London", maxDepth: 4 });
console.log(path.nodes.map((n) => n.label).join(" → "));
// Acme Corp → Fetch.ai → London

Error Handling & Retry

error-handling.ts
import { MemoryClient } from "@fetchai/agentverse-memory";
import {
AuthError, // 401 — invalid or missing API key
ForbiddenError, // 403 — feature not on your plan
NotFoundError, // 404 — resource does not exist
RateLimitError, // 429 — monthly or burst limit exceeded
ServerError, // 500/503 — server-side fault
AvmemError, // base class for all SDK errors
} from "@fetchai/agentverse-memory/errors";
const client = new MemoryClient({ agentId: "my-agent" });
try {
const episode = await client.episodes.store({ content: "Important event." });
} catch (err) {
if (err instanceof AuthError) {
console.error("Invalid API key. Check AVMEM_API_KEY.");
} else if (err instanceof ForbiddenError) {
console.error(`Feature requires upgrade: ${err.requiredPlan}`);
} else if (err instanceof RateLimitError) {
console.error(`Rate limited. Retry after ${err.retryAfter}s`);
await new Promise((r) => setTimeout(r, err.retryAfter * 1000));
// retry...
} else if (err instanceof AvmemError) {
console.error(`Unexpected error [${err.code}]: ${err.message}`);
}
}

Built-in retry via constructor (recommended for production):

const client = new MemoryClient({
agentId: "my-agent",
maxRetries: 3, // retry on 429 + 5xx
retryBackoff: 2.0, // exponential factor
});
// All calls automatically retry transient errors

Next.js & Edge Runtime

Works in Node.js, Deno, and browser runtimes. For Next.js App Router server actions:

app/actions.ts
"use server";
import { MemoryClient } from "@fetchai/agentverse-memory";
const client = new MemoryClient({
apiKey: process.env.AVMEM_API_KEY!,
agentId: "nextjs-assistant",
});
export async function storeUserMessage(sessionId: string, message: string) {
return client.episodes.store({
content: message,
metadata: { sessionId, role: "user" },
});
}
export async function getContext(query: string) {
return client.episodes.query({ query, limit: 5 });
}

For edge functions (Cloudflare Workers, Vercel Edge):

import { MemoryClient } from "@fetchai/agentverse-memory/edge";
// Identical API — uses fetch() instead of Node http/https

Method Reference

All 35 methods map 1:1 to MCP tools. See the API Reference for full parameter schemas.

MethodDescription
client.episodes.store(params)Store an episodic event
client.episodes.query(params)Natural-language search over episodes
client.episodes.get(id)Retrieve episode by ID
client.episodes.list(params)Paginated list of episodes
client.episodes.update(id, params)Update episode content or metadata
client.episodes.delete(id)Delete an episode
client.episodes.searchTimeline(params)Time-windowed search
client.episodes.consolidate(ids)Merge related episodes
client.facts.store(params)Store a knowledge triple
client.facts.query(params)Natural-language graph search
client.facts.get(id)Retrieve fact by ID
client.facts.traverseGraph(params)Multi-hop pheromone-weighted graph traversal
client.facts.findPath(params)A* shortest path between two concepts
client.facts.update(id, params)Update a fact
client.facts.delete(id)Delete a fact
client.procedures.store(params)Store a skill/workflow definition
client.procedures.query(params)Find procedures by goal description
client.procedures.get(id)Retrieve procedure by ID
client.procedures.update(id, params)Update steps or log execution outcome
client.procedures.lookup(goal)Find best procedure for a goal
client.working.set(params)Set a working memory key (with optional TTL)
client.working.get<T>(params)Get a typed working memory value
client.working.list()List all active working keys
client.working.clear()Clear all working memory
client.spaces.create(params)Create a shared memory space
client.spaces.join(spaceId, token)Join a shared space
client.spaces.query(spaceId, params)Query a shared space
client.health()Check service health
client.stats()Get usage statistics

Configuration Reference

const client = new MemoryClient({
apiKey: "avmem_sk_...", // or process.env.AVMEM_API_KEY
agentId: "my-agent", // or process.env.AVMEM_AGENT_ID
baseUrl: "https://am-server-jbneh74b5q-uc.a.run.app", // or AVMEM_BASE_URL
timeout: 10_000, // request timeout in ms (default: 10000)
maxRetries: 3, // auto-retry on 5xx (default: 3)
retryBackoff: 2.0, // exponential factor (default: 2.0)
});

Next Steps

Issues? Open an issue on GitHub or join #sdk-typescript on Discord.