Adding memories
Store text with encode (POST /v1/memories), read the structured outcome, and control content dedup, event time, and idempotent retries.
- A Brain API key bound to a
(namespace, agent)scope. See Authentication. @brain-db/sdk(TypeScript) orbrain-db-sdk(Python) installed.BRAIN_API_KEYset, or passed at client construction.- Familiarity with the write pipeline.
A small adapter that encodes memories from your application and logs, per write, whether the memory was newly stored or deduplicated, its salience, and how many edges were added.
One verb, one memory
encode stores one piece of text. There is no batch verb and no "messages" shape — you call encode once per memory. Each call runs the full write pipeline (embed → persist, then async derivation: auto-edges, temporal edges, and knowledge extraction) and returns once the memory is durably persisted. See the write pipeline for what runs synchronously versus after the acknowledgement.
Over HTTP this is POST /v1/memories; over the wire protocol it is the ENCODE verb.
Step-by-step
Pass the text. context (a u64 you choose) groups related memories; occurred_at records when the event happened, distinct from ingest time.
import { BrainHttpClient } from "@brain-db/sdk";
const brain = new BrainHttpClient({
apiKey: process.env.BRAIN_API_KEY!,
baseUrl: "https://api.arc-labs.ai",
});
const res = await brain.encode({ text: "Sarah prefers dark mode in the editor." });
console.log(res.memory_id, res.was_deduplicated, res.salience, res.auto_edges_added);import os
from brain_db_sdk import BrainHttpClient
brain = BrainHttpClient(os.environ["BRAIN_API_KEY"], base_url="https://api.arc-labs.ai")
res = brain.encode(text="Sarah prefers dark mode in the editor.")
print(res.memory_id, res.was_deduplicated, res.salience, res.auto_edges_added)use brain_db_sdk::BrainHttpClient;
use brain_db_sdk::http::EncodeInput;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let brain = BrainHttpClient::new("https://api.arc-labs.ai", &std::env::var("BRAIN_API_KEY")?);
let res = brain
.encode(&EncodeInput {
text: "Sarah prefers dark mode in the editor.".to_string(),
..Default::default()
})
.await?;
println!(
"{} {} {} {}",
res.memory_id, res.was_deduplicated, res.salience, res.auto_edges_added
);
Ok(())
}curl -X POST https://api.arc-labs.ai/v1/memories \
-H "Authorization: Bearer $BRAIN_API_KEY" \
-H 'Content-Type: application/json' \
-d '{ "text": "Sarah prefers dark mode in the editor." }'The response is a structured outcome, not a list of memories. Each field reports one thing about the write:
memory_idstringoptionalwas_deduplicatedbooleanoptionalsaliencenumberoptionalkindnumberoptionalauto_edges_addednumberoptionalcreated_at_unix_nanosnumberoptionalFor the full field reference and the durable write-artifact bundle, see POST /v1/memories and GET /v1/memories/{id}/inspect.
When the text describes something that happened at a specific moment (a login, a purchase, a decision), stamp occurred_at so temporal recall and the FollowedBy edges anchor to event time rather than ingest time.
await brain.encode({
text: "User upgraded to the Pro plan.",
occurred_at: Date.parse("2026-04-30T00:00:00Z") * 1_000_000, // unix nanoseconds
context: 42,
});brain.encode(
text="User upgraded to the Pro plan.",
occurred_at=1_777_593_600_000_000_000, # unix nanoseconds
context=42,
)brain
.encode(&EncodeInput {
text: "User upgraded to the Pro plan.".to_string(),
occurred_at: Some(1_777_593_600_000_000_000), // unix nanoseconds
context: Some(42),
..Default::default()
})
.await?;Brain deduplicates byte-identical text automatically. The fingerprint is BLAKE3(text) scoped to (agent, context); a matching write returns the existing memory with was_deduplicated: true and does not create a new row. This is a database policy, always on — there is no flag to check for it on the HTTP path.
When the same text is a genuinely distinct observation that must coexist (the same fact re-stated at a different occurred_at), opt out on the wire client with allowDuplicates (see Idempotency for the dedup-versus-idempotency distinction).
Encoding over the wire
The wire client exposes the same verb with more control — wait mode, allowDuplicates, per-request actAs, and transactions. Build the request with EncodeBuilder, which mints the requestId and fills defaults.
import { BrainClient, EncodeBuilder, WaitMode } from "@brain-db/sdk";
const client = await BrainClient.connect("127.0.0.1", 9090, {
auth: { kind: "token", token: new TextEncoder().encode(process.env.BRAIN_TOKEN!) },
});
// wait(WaitMode.Derived) blocks until async derivation finishes and returns the
// full write-analysis trace; the default (Ack) returns at the durable ack.
const res = await client.encode(
new EncodeBuilder("Sarah prefers dark mode.").wait(WaitMode.Derived).build(),
);import os
from brain_db_sdk import BrainClient, EncodeBuilder
from brain_db_sdk.client import Auth
client = BrainClient.connect(
"127.0.0.1", 9090, Auth.token(os.environ["BRAIN_TOKEN"].encode()),
)
# .derived() blocks until async derivation finishes and returns the write trace.
res = client.encode(EncodeBuilder("Sarah prefers dark mode.").derived().build())use std::net::SocketAddr;
use brain_db_sdk::{Auth, BrainClient, EncodeBuilder};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr: SocketAddr = "127.0.0.1:9090".parse()?;
let token = std::env::var("BRAIN_TOKEN")?;
let client = BrainClient::connect(addr, Auth::Token(token.into_bytes())).await?;
// wait_derived() blocks until async derivation finishes and returns the
// full write-analysis trace; the default (Ack) returns at the durable ack.
let res = client
.encode(&EncodeBuilder::new("Sarah prefers dark mode.").wait_derived().build())
.await?;
Ok(())
}See Wire client and Typed graph for the full wire surface.
Log memory_id and was_deduplicated on every write. A run of was_deduplicated: true where you expected new rows usually means the same text is being replayed — reach for an explicit occurred_at or allowDuplicates rather than mutating the text to dodge the fingerprint.
Was this page helpful?