AIStor Memory

AIStor Memory — the agent's memory, in three forms

The full feature surface across the three forms of one memory — Workspace, Long-term memory (warmup, annotations, metadata, search, structured memory, skills), and the secrets Vault — with all the operator reference.

AIStor Memory is the memory your agents keep. It is one thing the agent uses: a mount of a MinIO AIStor Memory Bucket (a cortex) that the agent both works in and remembers through. Everything persists to AIStor — your storage, your keys — and AIStor Memory teaches the agent, automatically, how to use it.

Anything an agent needs to keep is memory. AIStor Memory holds it in three forms on one customer-owned cortex — each a distinct purpose and lifecycle, not three separate systems:

  1. Workspace — active work. The mount the agent works in: it reads project files and vendor memory and edits them in place with the tools it already uses — git, editors, sqlite, build tools all run unchanged — and the resulting state lands back in the cortex when files close. The real files survive sandbox teardown because they live in the durable cortex, not in session residue.
  2. Long-term memory — what the agent learned. Durable knowledge that shapes future work: the memory files agents already look for (CLAUDE.md, AGENTS.md, MEMORY.md) warmed on mount; writable per-object annotations; read-only object metadata and tags as provenance; server-side search across the whole cortex; and structured memory as queryable tables (experimental). The aimem skill teaches the agent to use all of it.
  3. Vault — authority to act. Secrets held in the cortex (encrypted server-side) or provisioned from your own external store, leased into the agent as environment variables at launch — never written to the mount.

The rest of this page is the full feature surface, organized by form, followed by the mount and configuration reference.

The cortex — one mount for all three forms

AIStor Memory mounts only a Memory Bucket — a cortex. On mount it verifies the target is a cortex over the Memory API and refuses a plain bucket (not a Memory Bucket (cortex)); there is no opt-out. A cortex is a first-class AIStor bucket built for agents — compressed, encrypted, KMS-backed, and version-tracked — created with aimem cortex create or by converting an existing bucket with aimem cortex convert. See the CLI reference for the full cortex verb set (create · convert · list · get · delete · credentials).

The mount gate is strict and refuses to proceed unless, in order: an endpoint is configured (the endpoint_url: config key or the --endpoint-url flag), real signing credentials (AIMEM_ACCESS_KEY / AIMEM_SECRET_KEY, not anonymous or default-chain) are present, the target is verified as a cortex over the Memory API (not a plain bucket), and the credentials can reach the Memory API — which is an Enterprise / paid-tier AIStor capability, so an unlicensed server or a credential lacking memory:GetCortex fails the check (access denied by the Memory API … or the server is not on a paid tier).

Workspace — active work

The Workspace form is the durable mount the agent works in — the tools it already uses (git, editors, sqlite, build tools) run unchanged against real files. It ships exactly the contract an autonomous coding agent (Claude Code, Cursor, Codex, …) or sandbox VM needs:

  1. Read project files and any vendor-specific memory (CLAUDE.md, .claude/, AGENTS.md, MEMORY.md, .cursorrules, .cursor/).
  2. Edit those files in place — git, editors, sqlite, and the rest of the toolchain work as they would on any local disk.
  3. Have the resulting state land back in the cortex atomically when files close, so it survives sandbox teardown and the next session re-mounts it byte-for-byte.

How it works — mandatory workspace mode

Every file opened for writing is staged on fast local storage (the staging directory). The staging file is the agent's working copy. On close() / fsync() the staged contents are uploaded to S3 atomically. Random writes, O_RDWR, and O_TRUNC all work because they hit the staging file, not the network. mmap and copy_file_range are not native syscalls here (they return ENOSYS), but the kernel falls back to read+write over that same staging file, so memory-mapped tools still function.

The staging directory is required and can be supplied three ways — at least one of them must be present:

  • the local: key in a --config <FILE> YAML file (the canonical, reviewable form — fewest flags),
  • the --local <DIR> CLI flag, or
  • the AIMEM_LOCAL environment variable.

If more than one is set, CLI/env win over the config file. If none is present the mount is refused before it starts (a local staging directory is required; set --local <DIR>, the AIMEM_LOCAL env var, or the `local:` key in --config). There is no auto-detection and no default.

The chosen path is logged at mount; size your staging volume for the agent's expected open-write working set (NVMe is recommended).

Config file (--config <FILE>)

A --config <FILE> YAML file is a serialization of the long-flag surface: each key is a long flag with dashes rewritten to underscores (endpoint_url, metadata_ttl, …). Two keys are special: version is required and must be the quoted string "1.0" (a bare version: 1.0 parses as a float and is rejected), and unknown keys are a hard parse error. The canonical workspace mount puts the staging dir, endpoint, and any tunables in the file so the command line carries only the cortex, the mount point, and the config path:

# /etc/aimem/mount.yaml
version: "1.0"
local: /var/cache/aimem
endpoint_url: https://aistor.example.com
agent: claude
# Signing credentials come from AIMEM_ACCESS_KEY / AIMEM_SECRET_KEY in the
# environment — never flags, never the config file.
aimem my-cortex /workspace --config /etc/aimem/mount.yaml

Positionals (the cortex/bucket and mount point) and --config itself are never config-file keys — they always come from the command line.

Long-term memory — what the agent learned

The Long-term memory form is durable knowledge that shapes future work, kept beside the data that formed it. It is realized today through the memory files the agent warms on mount, writable per-object annotations (.aimem/annot/…) for reasoned notes co-located with the bytes they describe, read-only object metadata and tags (read as xattrs) for provenance the agent reasons over, server-side search across the whole cortex, and structured memory as queryable tables (experimental). The aimem skill teaches the agent to use all of it.

Agent-memory warmup

On every mount, AIStor Memory warms the vendor-specific memory paths into the --local store, so first-touch reads of CLAUDE.md / .claude/... / etc. are served from local NVMe via FUSE passthrough instead of S3.

Selected by the agent: key in a --config <FILE> YAML file (or the --agent flag): claude · codex · cursor · auto:

claudeCLAUDE.md, .claude/
codexAGENTS.md, .agents/, MEMORY.md
cursor.cursorrules, .cursor/, AGENTS.md
autoAll of the above

The warmup task runs in the background; the mount becomes operational immediately — warmup never blocks it — and first-touch reads are served from local disk via FUSE passthrough as soon as the warmup task publishes each object into --local. The warmed objects share the one --local store with write staging; there is no separate in-memory cache tier.

Custom warmup manifest

To warm additional objects beyond the agent-type defaults, set the agent_manifest: key in your --config <FILE> YAML file to the path of a JSONL manifest (the manifest is a config-file setting — there is no --agent-manifest CLI flag). Each line is a JSON object with key and size, plus optional etag and priority (0=Low, 1=Medium, 2=High, 3=Critical; defaults to Medium):

{"key": "CLAUDE.md", "size": 4096, "priority": 3}
{"key": "docs/runbook.md", "size": 18234}

etag is optional: when omitted, AIStor Memory resolves the real etag (and true size) with a HEAD at warm time, so the cached blocks match the key the read path looks up. This costs one HEAD per etag-less entry — negligible for a handful of files, but for a large manifest populate etag (e.g. from --generate-workspace-manifest) to keep warmup purely streaming. Warming never makes a file read-only — warmed paths stay ordinary read-write workspace files; this only pre-populates the read cache.

The manifest is composed with, not a replacement for, the agent-type defaults — both sets get warmed, and overlapping keys are de-duplicated at the cache layer.

To produce a starter manifest for the current workspace, run --generate-workspace-manifest <FILE>. AIStor Memory lists the agent-type memory paths, writes them as JSONL to FILE, and exits without mounting. Edit the file (trim keys, set priorities) and point the agent_manifest: config key at it.

Search over data at rest

aimem search <cortex> -e <regex> runs regex search server-side over the cortex's objects — the server decrypts and decompresses the objects server-side, matches in place, and streams back matches, so the agent searches its memory without downloading the workspace:

# Every -e pattern must match (AND semantics); RE2 syntax, line-oriented.
aimem search my-cortex -e 'TODO' -e 'auth' --ext md --ignore-case --content

Flags: -e/--pattern (repeatable, required; all patterns must match), --prefix to restrict to a key prefix, --ext (repeatable) to limit by file extension, --ignore-case, and --content to print the matching lines in grep style (name:line:text) instead of just the object names — plus the usual cortex connection flags. Patterns are RE2 (linear-time, no backreferences/lookaround) and matched per line by default; pass --multiline/-U to let a pattern span line boundaries. Search requires the memory:Search action on a paid-tier server.

Structured memory (experimental)

Records and events can be kept as queryable Apache Iceberg tables in the same cortex (aimem bio), so a run's activity becomes durable, queryable memory alongside the files. Every cortex is warehouse-enabled automatically — whether created fresh or converted from an existing bucket with aimem cortex convert — so there is no separate warehouse to stand up. This is experimental and evolving.

SKILLS — the agent's mount manual

The Long-term memory form includes the aimem skill that teaches any LLM agent to use everything above. AIStor Memory ships a first-class Agent Skill named aimem that teaches the agent how to work inside the mount: how to locate its workspace, the POSIX durability semantics, where to keep long-lived memory, how to read object metadata, how to leave and inherit per-object annotations, and how to search cortex memory server-side. A skill is a folder with a SKILL.md (real YAML frontmatter, name: aimem) plus a references/ directory that the agent loads on demand:

aimem/
├── SKILL.md
└── references/
    ├── navigation.md    # locate your mount point (findmnt) + how the root maps to objects
    ├── workspace.md     # POSIX semantics: staging, close-to-commit, rename
    ├── memory.md        # where CLAUDE.md / AGENTS.md / MEMORY.md live
    ├── metadata.md      # read S3 user-metadata + tags as xattrs
    ├── annotations.md   # durable per-object notes via .aimem/annot/
    └── search.md        # server-side regex over cortex memory (aimem search)

The skill is generic — it bakes in no bucket, region, or mount point; it teaches the agent to find its own mount with findmnt -S aimem. That means the same skill works for any AIStor Memory mount, and it works in egress-restricted sandboxes because it is bundled into the binary, not fetched.

An agent discovers the skill through three tiers, widening in scope. The first two are automatic — you do nothing.

Tier 1 — read-time preamble (automatic, in the workspace)

On every mount, AIStor Memory prepends a short orientation preamble to the served bytes of the agent's instruction files (CLAUDE.md, AGENTS.md, .cursorrules) as they are read. Any agent that reads its bootstrap file at startup immediately learns it is in an AIStor Memory workspace and is pointed at the installed skill (Tier 2) — even if the repo shipped no CLAUDE.md of its own.

The preamble is injected in memory only; it is never written back to the bucket. It is disabled automatically when the mount root is a git repository (so it can't dirty a tracked, committable file), and can be turned off with AIMEM_PREAMBLE_OVERLAY=0.

Tier 2 — installed skill (automatic, in $HOME)

Also on every mount, AIStor Memory installs the aimem skill into the agent's home skill directories so it survives the agent leaving the workspace:

~/.agents/skills/aimem/     # read by Codex CLI, Cursor, Gemini CLI, Copilot
~/.claude/skills/aimem/     # read by Claude Code (honors CLAUDE_CONFIG_DIR)

These coding agents auto-load skills from those paths, so installing there is the deterministic discovery path. The write is offline (no bucket, no S3, no network), create-only (an existing SKILL.md is never overwritten), and crash-safe (staged in a temp dir, published with one atomic rename).

The install is skipped when $HOME resolves under the mount point — writing there would push the skill into the bucket through FUSE instead of to local disk. Turn the whole step off with AIMEM_INSTALL_SKILL=0.

Tier 3 — public skill (host-side, for out-of-sandbox agents)

Some agents run their reasoning outside the sandbox — e.g. the OpenAI Agents SDK or other managed-agent harnesses, where the model lives in the control plane and only issues commands into the compute box. For those, an in-sandbox install (Tiers 1–2) is invisible: the reasoning model never sees files written inside the box.

Those harnesses install the aimem skill host-side from MinIO's public Agent Skills repository (minio/skills), alongside their own skills, before the run starts:

npx skills add minio/skills/aimem

minio/skills is MinIO's public home for all its agent skills. The aimem skill there is the same generic SKILL.md + references/ that ships in the binary, so a host-side install and an in-sandbox install are identical.

Vault — secrets an agent needs to act

The Vault form is the authority an approved agent receives: the secrets it needs to act, held in your own store and leased into the agent at launch. The cortex itself is a first-class, writable secret store — the Vault pillar — and an external store (HashiCorp Vault/OpenBao KV, a cloud secret manager) is also supported.

Coding agents need credentials. The OPENAI_API_KEY so the agent can self-introspect. The GITHUB_TOKEN for pushing to a PR branch. The NPM_TOKEN for npm publish. The PG connection string for the deploy step. Every one of those, written into a .env file in the workspace bucket as plaintext, is a prompt-injection waiting to happen: the agent reads the file, the agent chats with an untrusted source, the agent gets convinced to exfiltrate the file.

AIStor Memory's model is the Docker/Kubernetes one: secrets are provisioned and injected, never written into the workspace bucket. A launcher outside the sandbox fetches only the secrets that agent is granted and injects them into the agent process as environment variables. The store credential is held by the launcher, never handed to the agent.

The default secret store is the cortex itself — AIStor Memory's Memory-API secrets endpoint, where values are persisted encrypted server-side (see aimem secret put/get/list/delete below), so the Vault lives on the same AIStor as the rest of the agent's memory. As an optional bridge, if your secrets already live in a generic external store (HashiCorp Vault/OpenBao KV, a cloud secret manager), the launcher can lease them from there instead of copying them into the cortex — useful when that store is your org's mandated source-of-truth. Either way, one distinction to keep clear: aimem the client holds no secret bytes on disk or in the workspace bucket (it is a pass-through), which is not the same as "secrets are never stored anywhere" — the cortex is a first-class, writable secret store.

provision takes exactly one source. Either resolve from a cortex over the Memory API:

# Launch the agent with the granted secrets injected as env vars.
# All store/signing credentials stay with the launcher; the agent only
# sees the resolved values.
aimem secret provision \
  --cortex my-cortex \
  --endpoint-url https://aistor.example.com \
  --access-key "$AIMEM_ACCESS_KEY" \
  --secret-key "$AIMEM_SECRET_KEY" \
  --grant OPENAI_API_KEY=openai \
  --grant GITHUB_TOKEN=gh-pat \
  -- claude

…or from a generic HTTP secret store:

aimem secret provision \
  --store-endpoint https://vault.example.com \
  --store-token "$VAULT_TOKEN" \
  --grant OPENAI_API_KEY=openai \
  -- claude

# With no trailing command, emit KEY=VALUE lines for the caller to inject:
eval "$(aimem secret provision --cortex my-cortex \
  --endpoint-url https://aistor.example.com \
  --grant OPENAI_API_KEY=openai)"

provision launches the agent as a child process and exits with its status. Before launching, it scrubs the full store/connection credential set from the child's environment — AIMEM_SECRET_STORE_TOKEN, AIMEM_SECRET_STORE_ENDPOINT, AIMEM_ACCESS_KEY, AIMEM_SECRET_KEY, AIMEM_SESSION_TOKEN, AIMEM_ENDPOINT_URL, and AIMEM_REGION — so neither an HTTP-store token nor the cortex signing credentials ever reach the agent.

Nothing readable is written to the workspace bucket, and a prompt-injected agent cannot enumerate or re-fetch the store — it holds only the values it was leased, never the store or signing credentials.

Managing secrets in the cortex

When the store is the cortex itself, AIStor Memory is not just a fetch client — it is a first-class, writable secret store. Secret bytes are held encrypted server-side by the Memory API; aimem never persists them to disk or the workspace bucket. Four subcommands manage them:

# Store a secret. Prefer piping the value on stdin over --value
# (a --value is visible in the process list and shell history):
printf '%s' "$OPENAI_API_KEY" | aimem secret put my-cortex openai
aimem secret put my-cortex gh-pat --value "$GITHUB_TOKEN"

# Fetch a secret's plaintext value (written to stdout):
aimem secret get my-cortex openai

# Enumerate the secret names in a cortex:
aimem secret list my-cortex

# Delete a secret:
aimem secret delete my-cortex openai

Each subcommand takes the same connection flags / AIMEM_* env as any other cortex command (endpoint, region, access key, secret key, optional session token). secret provision --cortex <name> then reads back exactly these secrets to inject into an agent.

What makes it different

Secrets are held in your own store — the cortex, a writable first-class store you populate with aimem secret put, or an external store (HashiCorp Vault/OpenBao, a cloud manager) — never in a vendor's database. The launcher injects only the leased values as environment variables at agent start; the agent never holds the store or signing credentials, cannot enumerate or re-fetch the store, and nothing readable is written to the workspace bucket. A .env file in the bucket, by contrast, is plaintext — one prompt injection away from full exfiltration.

Configuration

aimem secret provision requires exactly one secret source — either --cortex (the AIStor Memory-API endpoint) or --store-endpoint (a generic HTTP store) — and they are mutually exclusive. A provision command with neither errors at runtime. The one flag that is always required is --grant; everything else depends on the chosen source.

--grant VAR=name (repeatable) binds env var VAR to secret name:

Env varFlagMeaning
--grant VAR=nameBind env var VAR to store secret name

Source A — cortex (--cortex <name>). Resolves over the Memory API using the standard cortex connection inputs:

Env varFlagMeaning
AIMEM_ENDPOINT_URL--endpoint-urlMemory-API / S3 endpoint (required)
AIMEM_ACCESS_KEY--access-keyAccess key (required)
AIMEM_SECRET_KEY--secret-keySecret key (required)
AIMEM_REGION--regionSigV4 region (optional, default us-east-1)
AIMEM_SESSION_TOKEN--session-tokenSession token (optional)

Source B — generic HTTP store (--store-endpoint <url>). Bearer-auth against your own store:

Env varFlagMeaning
AIMEM_SECRET_STORE_ENDPOINT--store-endpointSecret-store base URL
AIMEM_SECRET_STORE_TOKEN--store-tokenBearer token (optional; only valid with --store-endpoint; held launcher-side)

With a trailing -- <command> the command is launched with the secrets injected and the full store/signing credential set scrubbed; without one, KEY=VALUE lines are printed for the caller to consume.

What aimem does not ship

AIStor Memory is memory backed directly by the object store you already run — nothing extra to operate. The read path is served from the single --local store via FUSE passthrough: the agent-memory files (CLAUDE.md / .claude/ / AGENTS.md / .cursor/ / MEMORY.md / .cursorrules) are warmed into it on mount, and everything else is fetched from S3 on demand through the prefetcher and cached in --local as it is read. (Writes are separate — staged locally and uploaded atomically on close().) There is no separate in-memory cache, no multi-disk block caches, no shared remote cache clusters, and no S3 Express bucket caches — those would be at odds with the agent-memory contract (one writer, fast iteration on a small hot set, atomic upload on close). If you need a tunable read-cache tier for a non-agent workload, reach out — we can talk about the right substrate.