SuperAgent API
Managed memory and knowledge
Cloud Superbrain (cloud-superbrain) lets a hosted app remember useful context between calls. It saves facts and decisions, finds them by words or meaning, answers from them with citations, and keeps earlier versions when something changes.
Each HivemindOS account gets an isolated memory store; no desktop session or Obsidian vault is needed. A project-bound key, or a request for one of your app’s end users, gets a brain of its own inside the account, sharing the account’s plan and allowance. See one brain per project or user. Use the local Hive Superbrain instead when a user’s Obsidian vault should stay the editable source of truth.
Costs
| Mode | Operation | Result | Charge |
|---|---|---|---|
| Lexical search | memory.search |
Fast matches from titles, content, tags, projects, entities, aliases, and usage. | 0 credits |
| Semantic recall | memory.recall |
Hybrid meaning and keyword matches, with the evidence used for ranking. Add rerank: true to have the best 20 read again against the question. |
1 credit |
| Memory Answer | memory.answer |
A concise answer grounded in returned memories, plus cited memory ids. Add stream: true to get it as it is written. |
5 credits with the default reader |
| Erase an end user | memory.erase |
Everything one of your app’s end users has in memory, gone in one call. | 0 credits |
Semantic Recall and Memory Answer are paid per use from the account’s credits; no plan is needed. Lexical search, storage within the plan, history, graph reads, capsules, and health checks use no agent credits. Call catalog.get when onboarding an account to show its plan, storage limits, and availability.
Indexing runs when memory changes, so there is no idle charge. A new memory is searchable by keyword at once and joins Semantic Recall when its index status is ready; memory.health reports that state.
Save a memory
Only title and contentText are required. Add a stable memoryKey when later calls should update one subject instead of creating new records.
const saved = await hive.services.invokeOperation(
"cloud-superbrain",
"memory.create",
{
title: "Aurora compute funding decision",
contentText: "Compute capacity starts only after the customer-funded job is accepted.",
memoryKey: "decision:aurora-compute-funding",
memoryType: "decision",
project: "Aurora",
confidence: 0.96,
tags: ["compute", "commercial"],
entities: ["Project Aurora", "Hive Compute"],
evidenceCount: 3,
},
{ idempotencyKey: "aurora-compute-decision-v1" },
);
if (!saved.ok) throw new Error(saved.error);
const memoryId = saved.result.memory.id;
- Memory types:
instruction,fact,decision,goal,commitment,preference,relationship,context,event,learning,observation,artifact,error,action, andknowledge. - Optional fields:
path,kind,mimeType,mediaUrl,links,metaTags,aliases,sourceType,actorRole,memoryOrigin, andcognitiveStage. memory.batchsaves up to 25 records; each returns its own id and generation receipt.occurredAtdates a memory written after the fact, such as one you import from another system:"2026-09-25"or a full ISO time like"2026-09-25T14:30:00Z". Recall ranks the memory by it, and Memory Answer shows the reader that date instead of the day you saved it, so “my driving test is tomorrow”, said on the 25th and imported on the 30th, is not read as still to come. It cannot be in the future (a clock up to five minutes fast is allowed) or before 1900; either is refused with 400. Every memory returnsoccurredAt, ornullwhen it is dated by when it was written.memory.updatekeeps it unless you send a new one (nullclears it);memory.evolvedates the new version now unless you pass one;capsules.importkeeps each memory’s original time.- Content that looks like a credential, private key, bearer token, seed phrase, or mnemonic is rejected. Store the credential’s name and whether it is set, and keep the value in a secret manager.
Search and answer
Lexical search is free and predictable, good for autocomplete and retrieval before a model call:
const search = await hive.services.invokeOperation(
"cloud-superbrain",
"memory.search",
undefined,
{
query: {
q: "customer-funded compute",
project: "Aurora",
memoryType: "decision",
limit: 8,
},
idempotencyKey: "aurora-memory-search-001",
},
);
Semantic recall finds memories even when the wording differs:
const recalled = await hive.services.invokeOperation(
"cloud-superbrain",
"memory.recall",
{
query: "Who pays before an Aurora GPU starts?",
mode: "hybrid",
project: "Aurora",
limit: 8,
},
{ idempotencyKey: "aurora-memory-recall-001" },
);
Add rerank: true when the order matters, for example when an agent will read only the first few results. The best 20 matches are read again against the question and the most relevant are put first. It takes about a second longer and costs the same 1 credit, and the response says reranked: true. Only memories saved in the standard tier are read again; private and confidential ones keep their place. If the second read cannot run, you get the usual order and reranked: false. Rerank runs only in the standard tier: under the private or confidential base it is refused (409 STANDARD_TIER_REQUIRED), or, with keywordFallback: true, skipped with rerankSkipped: "privacy-tier".
Where the second read runs. The second read is made by a reranking model at a third-party model provider (OpenRouter), not by HivemindOS. With rerank: true, the question and the text of up to 20 standard-tier memories (up to 12,000 characters of each) are sent to that provider, under its own terms. Memories saved in the private or confidential tier are never sent. Leave rerank off if your standard-tier memories must not leave HivemindOS.
On LongMemEval_S (500 questions, each answer among about 50 past conversations), recall puts the conversations that hold the answer in its top 5 97.7% of the time with rerank: true, and 93.7% without it. Both were 90.7% before September 28, 2026. How it was measured.
Memory Answer returns a finished, grounded response:
const answered = await hive.services.invokeOperation(
"cloud-superbrain",
"memory.answer",
{
query: "What is the Aurora compute funding policy?",
limit: 8,
},
{ idempotencyKey: "aurora-memory-answer-001" },
);
console.log(answered.result.answer);
console.log(answered.result.citedMemoryIds);
If no memory supports an answer, the request returns not found and releases the credit reservation, so you are not charged. For a question of four or more words, a memory counts as support when it matches at least two of the question’s words, the exact phrase, or its meaning; one shared word is not enough. When the only candidates are weak meaning matches (see below), the answer model reads the best three; if its answer cites none of them, you get the same not-found reply and are not charged.
About results:
- Every hit includes its memory fields, an excerpt (the part holding the most question words), a total score, matched signals, and score details.
- A hit matched only as
semantic-weakis close in meaning but not close enough to count as a strong match. Weak matches rank below every strong or worded match, so a short fact phrased differently from the question (“what pet do I have” against “I adopted a grey cat”) is still found. Check the score before relying on one. - Search matches word forms (
weddingsfindswedding), and rare words count for more than common ones. - Operational memories such as action and handoff receipts are left out of default recall. Ask for a specific operational
memoryTypeor setincludeOperational: truewhen you want them. - Set
trackUsage: falsefor diagnostic lookups that should not affect usage ranking.memory.usagerecords retrieved or final-answer use for known memory ids. memory.searchresponses includeServer-Timing: memory;dur=<ms>, the search’s own time without network.memory.recallandmemory.answerinclude a breakdown:owner,embed,vector,lexical,rows,rerank,reader,meterandtotal, in milliseconds.
To limit an answer-only worker, allow just services.invoke.cloud-superbrain.memory.answer and set a request limit on that exact selector.
Stream the answer
Add stream: true to memory.answer to show the answer as it is written instead of after the whole of it. The response is server-sent events (text/event-stream) instead of the JSON envelope:
| Event | Data |
|---|---|
meta |
Everything the buffered answer returns except answer: hits, citedMemoryIds, reader, privacy, the conversation evidence, and chargedCredits. Sent first. |
delta |
{ "text": "..." }: the next part of the answer. |
done |
{ "answer": "...", "chargedCredits": 5 }: the whole answer, once it is complete. |
error |
{ "error": "...", "chargedCredits": 5 }: the reader stopped after it started. |
It costs the same as a buffered answer, charged once. The charge is settled when the reader’s first words arrive, before the stream starts, and the response’s X-HivemindOS-Credits-Charged header says how much. So a reader that fails before writing anything is not charged, and you get the usual JSON error instead of a stream. An answer you stop reading halfway, or one cut off by an error event, was still charged once and is not charged again. A request that finds nothing returns the same not-found JSON as without stream, uncharged. When the only candidates are weak meaning matches, the answer is read whole first (it is charged only if it cites them) and arrives as one delta. A stream is not replayed for a repeated idempotency key; mode: "evidence" has no answer to stream and refuses stream: true.
With the SDK:
import { collectMemoryAnswer } from "@hivemindos/sdk";
const started = await hive.memory.answerStream({ query: "When is my driving test?" }, { endUserId: "user-42" });
if (!started.ok) throw new Error(started.error);
for await (const event of started.events) {
if (event.type === "delta") process.stdout.write(event.text);
}
// Or read it whole: const { answer, complete } = await collectMemoryAnswer(started);
Measured on 2026-10-06 through /v1 with the SDK and the default reader (10 answers each, median): a paragraph-long answer’s first words arrived in 1.03 s against 1.89 s for the buffered answer; a one-sentence answer in 0.99 s against 1.21 s; a “when” question, which the reader reasons about before it writes, in 2.15 s against 2.35 s. The longer the answer, the more streaming saves.
Choose who reads the answer
Memory Answer has a default reader, and you can name another. memory.models lists every model that can read an answer, with its privacy tier, reasoning settings, per-token price, and the most one answer can cost. The default is marked default: true. It needs no key.
const readers = await hive.services.invokeOperation(
"cloud-superbrain",
"memory.models",
{},
{ idempotencyKey: "memory-readers-001" },
);
Pass a reader’s id as model, and reasoningEffort (none, low, medium or high) when that reader lists it:
const answered = await hive.services.invokeOperation(
"cloud-superbrain",
"memory.answer",
{
query: "What is the Aurora compute funding policy?",
model: "@cf/openai/gpt-oss-120b",
reasoningEffort: "medium",
},
{ idempotencyKey: "aurora-memory-answer-002" },
);
console.log(answered.result.reader);
A setting a reader does not take is refused before anything is charged, never quietly changed. The response’s reader names the model that answered.
Price. With the default reader, an answer costs 5 credits. Another reader adds what it costs above the default for the same question, at HivemindOS rates, rounded up to a whole credit. A reader that costs less than the default still costs 5 credits. The answer first reserves the reader’s maximumCredits, then charges for the question actually sent and releases the rest.
Private and confidential answers. Pass private: true, or call through the private base URL, to have the answer read only by a model that keeps nothing it is sent. Under the confidential base, name a reader that runs in an attested enclave as model; there is no default there. In both cases the answer never uses Turbo ordering, and turbo: true is refused. memory.models under a tier’s base, or with privacy in its query, lists the readers that qualify.
A memory keeps the strictest tier it was written in and is read only by a reader that meets it. See private and confidential access.
Measured reader accuracy and speed are on the memory benchmarks page.
Past conversations
Save a chat transcript as a memory and recall reads it exchange by exchange. A memory is read as a transcript when its turns are marked **User:** and **Assistant:** (or an agent’s name), or when its lines start with User: and Assistant:. Put the conversation’s date in the frontmatter as startedAt or date; otherwise the save date is used.
await hive.services.invokeOperation(
"cloud-superbrain",
"memory.create",
{
title: "Support chat with Dana",
path: "Conversations/2026-09-14-dana.md",
contentText: [
"---",
"startedAt: 2026-09-14T15:02:00Z",
"---",
"User: The replacement blender arrived cracked, same as the first one.",
"Assistant: Sorry about that. I've refunded the second order to the original card.",
].join("\n"),
},
{ idempotencyKey: "support-chat-dana-0914" },
);
When a search or recall returns a transcript, the response also carries conversationEvidence: the best-matching exchanges across the account’s transcripts, oldest first under each conversation’s date. conversationEvidenceMemoryIds names their memories.
| Field | Default | Effect |
|---|---|---|
evidenceChars |
4,200 | The size of conversationEvidence, from 1,000 to 24,000 characters. |
evidence |
On, except at detail: "abstract" |
false leaves the exchanges out; true adds them at any detail tier. |
Memory Answer reads the same exchanges plus the best part of every other supporting memory, and knows today’s date, so “how long ago” and “which came first” questions work. If the conversations fit, it reads them whole. If not, and you pass turbo: true, the Turbo decision model orders the exchanges by how likely each is to hold the answer, and the answer reads excerpts from the best 12,000 characters. The decision model is not private, so it is used only when every exchange was written in the standard tier, and never for a private answer. Turbo also reads the best 20 candidate memories again against the question before choosing which conversations to read, the same second read as rerank: true in recall. Both run at a third-party model provider (OpenRouter): the question, the exchanges, and the candidate memories’ text are sent to it under its own terms. Turbo is off unless you pass turbo: true (since 2026-09-29); without it the answer keeps keyword order and sends nothing to that provider. The response’s turbo says whether it ran. The response’s evidenceOrder says which order was used (keyword when conversations were read whole). Neither choice changes the price.
One brain per project or user
When a request is made with a project-bound key, with X-HivemindOS-Project, or for one of your app’s end users (X-HivemindOS-End-User, or a key bound with endUserId), Cloud Superbrain reads and writes a separate brain for that project, that end user, or that end user within that project:
- It starts empty and never sees the account’s own memories, or a desktop brain synced to them. The account’s own requests never see it.
- Ids, memory keys, history, and search stay inside it. An id from another brain is not found.
- It uses the account’s plan. Every brain in the account shares the plan’s one allowance.
- Buying a plan and syncing a desktop brain need an account-level request; a scoped request is refused.
See projects and isolation for how to name an end user.
Erase an end user’s memory
When one of your app’s users deletes their account, memory.erase removes everything they have in memory in one call: every memory, its past versions, its search indexes, and the brain’s history. It is free, needs no approval, and is safe to repeat.
const erased = await hive.memory.erase({ endUserId: "user-42" });
// Same as hive.services.invokeOperation("cloud-superbrain", "memory.erase", {}, { endUserId: "user-42" })
if (!erased.ok) throw new Error(erased.error);
console.log(erased.result.memoriesErased, erased.result.complete);
- Only one end user, only yours. It erases the brain of the end user the call names, inside the key’s own account and project, and nothing else: not another end user, not another project’s brain for the same end user id, not the account’s own memories. The end user comes from a key bound with
endUserId(which erases only its own end user, and cannot name another) or fromX-HivemindOS-End-Useron an unbound key. A call that names no end user is refused with 400end_user_required; an account’s or a project’s whole brain cannot be erased this way. - Which keys can call it. Any key with the
services:invokescope whose operations includeservices.invoke.cloud-superbrain.memory.erase(a key with no operation list has every operation). To give an app server only this, allow just that selector. A key bound to an end user can erase only that end user, so a key you hand to a user’s device can erase that user and no one else. - Repeating is safe. A second erase finds nothing and returns
memoriesErased: 0. A very large brain (over 5,000 memories) returnscomplete: false; call again untilcompleteis true. - Audited. Each erase leaves a record of when it ran, for which account and project, and how many memories went. It holds no memory content and not the end user’s id. The call also appears in your usage and audit events.
Ask for only as much as you need
Recall returns whole memories by default. Pass detail to get less:
detail |
Each hit carries | Good for |
|---|---|---|
abstract |
Id, title, type, project, status, updated date, score, and a one-line excerpt. | Surveying candidates, then re-requesting the few that matter. |
overview |
The full metadata record, ranked excerpt, and score details — no body. | Ranking and filtering when the body is not needed yet. |
full |
Everything, including contentText. The default. |
Reading the memory. |
const survey = await hive.services.invokeOperation(
"cloud-superbrain",
"memory.recall",
{ query: "Who pays before an Aurora GPU starts?", mode: "hybrid", detail: "abstract", limit: 8 },
{ idempotencyKey: "aurora-memory-survey-001" },
);
detail only trims the response. It never changes which memories rank, their order, what memory.answer is grounded on, or the price. The response echoes the detail it applied.
Change, replace, or delete a memory
When new information replaces an active memory, use memory.evolve. The old record becomes superseded, the new one becomes the active head, and both stay linked.
const evolved = await hive.services.invokeOperation(
"cloud-superbrain",
"memory.evolve",
{
contentText: "Aurora capacity starts only after the customer's maximum charge is reserved.",
evolutionReason: "Clarified when funding is secured.",
},
{
pathParameters: { memoryId },
idempotencyKey: "aurora-compute-decision-v2",
},
);
memory.updateedits the current record in place, for metadata or wording fixes that do not change the underlying truth.memory.deletepermanently removes a memory and requires an exact SuperAgent approval. An operation-only deletion key needsservices.invoke.cloud-superbrain.memory.delete,approvals.create, andapprovals.decideinallowedOperations; addapiKeys.revokeonly if the worker must also revoke its own key. Prefer archiving or evolving when history matters.
Maintenance and history
- Find duplicates:
memory.consolidategroups near-duplicates within a memory type, spots memories that say they correct an earlier note but were written withoutsupersedes, and lists aged-out memories nothing has retrieved. It reports rather than merges: each group comes with the exactmemory.evolvecall to review. WithapplyArchives: trueit archives aged-out candidates (reversible, and onlycontext,event,observation, andactionmemories older than 120 days with no retrieval history).memory.healthalso reportsduplicatePressurefor scheduled checks. - Learn from what agents did:
memory.minePatternsreads operational memories and proposes recurring failures, workflows worth turning into a skill, and operations stable enough to schedule. Test traffic and retries of one task are not counted. It never creates anything; send a candidate tomemory.createto keep it. - Browse by path:
memory.browsesummarizes path groups without bodies (about 100 tokens per group atabstract, about 2,000 atoverview).memory.recallwithmode: "hierarchical"scores groups first, so a memory’s neighbours come back with it. Hierarchy only changes order; it never hides a memory. - Replay history: each write publishes an immutable generation.
generations.listreads retained generations and the replay boundary;generations.compareshows added, removed, and changed ids between two.memory.recallwithgenerationIdreplays a lexical question against an old state;temporalMode: "historical"includes superseded and archived records, andtemporalMode: "as-of"withasOfsets a time cutoff. Up to 256 generations are kept per account. A request outside the replay boundary fails rather than using newer memory. - Knowledge graph: memories with type
knowledge, aknowledgetag, or a path underSynthesis/become knowledge nodes. Useknowledge.search,knowledge.get,knowledge.backlinks(connections through entities, aliases, and links), andknowledge.graph(a bounded node-and-edge view). Useentities,aliases, andlinksconsistently for dependable navigation. - Portable capsules:
capsules.exportreturns a checksummed capsule of selected memories or the next page of the account; export at most 100 memories per part and followhasMoreandnextCursor.capsules.importchecks the schema and hash before adding records to the authenticated account; it can never grant access to the source account or overwrite another account’s memory.capsules.open,capsules.search, andcapsules.previewinspect a capsule and report what an import would change without writing anything; a damaged capsule is still shown, with a warning. The checksum detects corruption but is not encryption, so keep private capsules private.
All operations
| Operation | Method | Purpose |
|---|---|---|
catalog.get |
GET |
Read plans, limits, features, and current charges. |
memory.snapshot |
GET |
Read the account’s current managed-memory snapshot. |
memory.get |
GET |
Read one memory by id. |
memory.create |
POST |
Create or upsert one memory. |
memory.update |
PATCH |
Update one current memory. |
memory.delete |
DELETE |
Permanently delete one memory after approval. |
memory.erase |
POST |
Erase everything one end user has in memory, for account deletion. Free, no approval. |
memory.batch |
POST |
Create up to 25 memories. |
memory.evolve |
POST |
Create a new canonical head and supersede the old one. |
memory.search |
GET |
Run lexical search. |
memory.recall |
POST |
Run paid hybrid semantic recall. |
memory.answer |
POST |
Return a paid grounded answer with citations; stream: true sends it as it is written. |
memory.models |
GET |
List the models that can read a Memory Answer, with prices. |
memory.usage |
POST |
Record retrieved or final-answer use. |
memory.health |
GET |
Read plan, index, generation, duplicate pressure, and usage health. |
memory.consolidate |
POST |
Report duplicate pressure, missed corrections, and aged-out memories. |
memory.minePatterns |
POST |
Propose recurring failures, reusable workflows, and routines from operational memories. |
memory.browse |
POST |
Survey memory paths at the abstract or overview tier. |
index.rebuild |
POST |
Rebuild indexes after an import or repair. |
generations.list |
GET |
List retained immutable generations. |
generations.compare |
POST |
Compare two retained generations. |
capsules.export |
POST |
Export a checksummed capsule part. |
capsules.import |
POST |
Verify and import a capsule part. |
capsules.open |
POST |
Read a capsule’s manifest, integrity, and contents without importing. |
capsules.search |
POST |
Search inside a capsule without importing it. |
capsules.preview |
POST |
Report what importing a capsule would change. |
knowledge.search |
GET |
Search knowledge nodes. |
knowledge.get |
GET |
Read one knowledge node. |
knowledge.backlinks |
GET |
Read backlinks for a knowledge node. |
knowledge.graph |
GET |
Read a bounded knowledge graph. |