AIStor Memory
Integrations

OpenAI Codex / Agents SDK

Give a self-hosted Codex or Agents SDK sandbox durable memory — mount an AIStor Memory Bucket (cortex) at /workspace, the workspace the agent works in and remembers through, so apply_patch edits survive teardown.

Status - Ready

Self-serve today: a working sandbox image, mount wrapper, credential template, one-command runner, and an external agent-worker smoke live in this repo. Codex Cloud (hosted) is not supported - see the note at the end.

AIStor Memory is the memory your agents keep: one mount of a MinIO AIStor Memory Bucket (a cortex) that the agent both works in and remembers through. In a self-hosted Codex (or OpenAI Agents SDK) sandbox, that memory is the workspace — mounted at the agent's working directory, where the model's edits become durable files rather than session residue, alongside the memory files it reads (CLAUDE.md, AGENTS.md) and the annotations it writes under .aimem/annot/.

Codex treats apply_patch as its canonical edit primitive and expects a writable filesystem under that directory; the cortex mount provides it. Because the workspace lives in a durable AIStor cortex, the agent's actual files and edits survive sandbox teardown — any later session re-mounts the same workspace at full fidelity, byte-for-byte, not a summary.

Newer agent runtimes keep the model loop, approvals, tracing, and model API key in a trusted worker. Only typed shell or filesystem tool calls cross into the execution sandbox. The sandbox owns the AIStor Memory mount and narrow storage credentials, while the worker never opens /workspace directly.

The repository's external_worker_smoke.py validates this split. It dispatches typed list, read, and write calls from the CI worker into a separate sandbox and asserts that OPENAI_API_KEY is absent there. The CI workflow removes and recreates the sandbox, then invokes the script again to read the same AIStor Memory-backed file. Its optional Agents SDK pass uses the identical tool bridge for a real model call without danger-full-access.

The co-located image flow below remains useful for self-hosted Codex CLI and backward compatibility. For new orchestrators, use the split worker/executor boundary and adapt the tool transport to the sandbox provider's client or MCP.

Codex Cloud (the hosted offering) is not currently supported. Its 12-hour container-snapshot lifecycle is incompatible with a live FUSE daemon.

Integration shape

  1. Build the checked-in example image. It extends ghcr.io/openai/codex-universal with aimem, the setuid aimem-fusermount helper, Codex CLI, and Python SDK dependencies.
  2. The entrypoint mounts the bucket at /workspace, waits for the mount, registers OPENAI_API_KEY with Codex CLI when present, then execs the agent command from inside the mount.
  3. Codex CLI and the Codex SDK must select the full-access sandbox (--sandbox danger-full-access on the CLI; sandbox=Sandbox.full_access in the Python SDK; sandboxMode: "danger-full-access" in the TypeScript SDK). Codex's built-in bubblewrap (bwrap) sandbox otherwise reconstructs the workspace mount namespace and shadows the FUSE mount. See openai/codex#14794, #15505.

Quick start

The bucket must be a cortex

aimem mounts only a Memory Bucket (cortex), never a plain S3 bucket. Before you set AIMEM_BUCKET, create the cortex launcher-side with aimem cortex create my-project --endpoint-url https://aistor.example.com (or aimem cortex convert an existing bucket). At mount time aimem requires an explicit endpoint URL and real signing credentials (AIMEM_ACCESS_KEY / AIMEM_SECRET_KEY — anonymous or default-chain mounts are refused), then verifies over the Memory API that the target is a cortex and that the AIStor server is on a paid/Enterprise tier; a plain bucket fails with 'my-project' is not a Memory Bucket (cortex). See Prerequisites.

Use the example context instead of recreating Dockerfiles or wrapper scripts by hand:

cd examples/openai-agents-sdk
cp .env.example .env
$EDITOR .env
./run-agent

Fill in these .env values:

VariableRequiredNotes
AIMEM_BUCKETyesCortex to mount at /workspace (must already be a Memory Bucket)
AIMEM_ENDPOINTyesMinIO AIStor endpoint URL (Enterprise / paid tier)
AIMEM_ACCESS_KEYyesAIStor Memory S3 access key
AIMEM_SECRET_KEYyesAIStor Memory S3 secret key
OPENAI_API_KEYyesUsed by Agents SDK, Codex CLI, and SDKs
AIMEM_SESSION_TOKENnoTemporary credential token, when needed
AIMEM_AGENTnoAgent-memory warmup profile (default codex)
AIMEM_WORKDIRnoMount path inside the container (default /workspace)
AIMEM_LOCALnoStaging dir for open-for-write files (default /var/cache/aimem-staging)
AIMEM_AGENT_MODELnoModel agent.py uses (default gpt-5-mini)
AIMEM_SMOKE_MODELnoModel the Agents SDK / Codex SDK smoke scripts use (default gpt-5-mini)

./run-agent builds aimem-openai-agents-sdk:latest if it is missing, mounts the bucket at AIMEM_WORKDIR (/workspace by default), and runs python /agent.py. That demo agent writes SUMMARY.md through AIStor Memory.

If you already export the variables in your shell, skip .env; run-agent passes them through.

Run

Agents SDK Python — default entry point (run-agent with no args runs python /agent.py):

./run-agent

Codex CLI - same mounted workspace, with the bwrap bypass:

./run-agent codex exec --sandbox danger-full-access --skip-git-repo-check \
  "summarize the repo"

Agents SDK smoke:

./run-agent python /agent_smoke.py

Codex SDK smoke:

./run-agent python /codex_sdk_smoke.py

Image options

Pin an AIStor Memory release, then rebuild:

AIMEM_VERSION=RELEASE.<date> AIMEM_BUILD=1 ./run-agent

Build against local binaries, offline, or an unreleased build by dropping Linux/amd64 aimem and aimem-fusermount into bin/, then rebuilding:

AIMEM_BUILD=1 ./run-agent

Override the Codex base image or SDK pins with environment variables:

CODEX_IMAGE=my-org/codex-base:latest \
OPENAI_AGENTS_VERSION=<version> \
OPENAI_CODEX_SDK_VERSION=0.1.0b2 \
AIMEM_BUILD=1 ./run-agent

OPENAI_AGENTS_VERSION=latest is a release placeholder; pin it before cutting the public image.

SDK shape

Codex SDK (Python) — same full-access requirement as the CLI (step 3), driven from your code; point the SDK at the Codex binary already in the image:

import os
from openai_codex import Codex, CodexConfig, Sandbox

config = CodexConfig(codex_bin="/usr/local/bin/codex")
with Codex(config) as codex:
    codex.login_api_key(os.environ["OPENAI_API_KEY"])
    thread = codex.thread_start(
        sandbox=Sandbox.full_access,   # required — see Integration shape step 3
        cwd="/workspace",              # the AIStor Memory mount
    )
    result = thread.run("Diagnose the test failure and propose a fix.")
    print(result.final_response)

The image installs openai-codex with --no-deps because openai-codex==0.1.0b2 pins a Codex CLI wheel that is not published for glibc Linux. The SDK is then configured to use /usr/local/bin/codex.

The TypeScript SDK (@openai/codex-sdk) is the same shape:

import { Codex } from "@openai/codex-sdk";
const codex = new Codex();
const thread = codex.startThread({
  sandboxMode: "danger-full-access",
  workingDirectory: "/workspace",
});
const turn = await thread.run("Diagnose the test failure and propose a fix.");
console.log(turn.finalResponse);

Both SDKs spawn the same Codex binary that the CLI uses, so the full-access requirement (Integration shape step 3) applies identically.

What the agent sees

PathModeNotes
/workspace/rwBucket-backed workspace; atomic upload on close
/workspace/.aimem/annot/rwPer-object annotation namespace
/var/cache/aimem-staging/rwStaging dir - random writes land here first

Teaching the agent the workspace

On every mount, AIStor Memory installs the aimem skill into $HOME automatically — $HOME/.agents/skills/aimem/ (read by Codex CLI and the SDKs) and $HOME/.claude/skills/aimem/ — so an agent whose reasoning runs inside the sandbox picks it up with no extra steps. Set AIMEM_INSTALL_SKILL=0 to opt out. Instruction files (CLAUDE.md, AGENTS.md, .cursorrules) read from the mount also carry an in-memory preamble overlay.

When the model loop runs outside the sandbox — the recommended agent-worker boundary above — that worker never sees the mount or the installed skill. Load the same skill into the worker from the public repo instead:

npx skills add minio/skills/aimem

See the SKILLS section of the AIStor Memory overview for the full three-tier model.

FUSE availability

AIStor Memory opens /dev/fuse directly and forwards the device fd to the setuid-root aimem-fusermount helper, which performs the privileged mount(2). The host docker daemon must allow /dev/fuse and grant CAP_SYS_ADMIN; Docker Desktop, GitHub Actions, and most production hosts do. The agent process itself runs unprivileged inside the container.

Reference

  • The complete build context lives in examples/openai-agents-sdk/. TODO(release): link this to the public AIStor Memory repo or release bundle.
  • openai/codex - the Codex CLI.
  • ghcr.io/openai/codex-universal - base image.