Integrate
Remaind is a substrate, not a framework. It does not run your agent or own your model session. It gives your loop a durable .context/ directory so work larger than the live window can survive resets and handoffs with source-linked evidence, validation, and a mechanical resume gate.
Setup
Install
python3 -m pip install --upgrade remaindRemaind is local-first: no hosted Remaind memory service is required, and your project continuity lives in .context/. Model-backed compaction can talk to a local runtime or an OpenAI-compatible endpoint over HTTP. Requires Python 3.11+.
remaind init
remaind doctor
# JSON for an operator UI or harness:
remaind doctor --json
# Scheduler-friendly alert surface:
remaind monitor --jsondoctor is the quickest readiness check: it validates the context folder and reports whether a configured model runtime is detected.
Five-minute proof path
One copy-paste path from claim to local proof.
This path installs the published package, creates local memory, checks the offline plan boundary, verifies readiness, runs the finance handoff proof, and then runs the golden continuity and handoff proof suite. remaind launch, remaind capture, and remaind handoff are the work commands after the proof path is trusted.
python3 -m pip install --upgrade remaind
remaind plan
remaind init
remaind doctor
remaind demo finance-handoff \
--force
remaind proofFull command output includes local workspace paths and detailed evidence tables. Those paths vary by machine; the PASS lines below are the stable checks to look for. See the Demo page for the interactive reset comparison.
Hermes integration
Hermes can use Remaind as both a memory provider and a context engine. The provider gives Hermes source-linked continuity tools; the context engine keeps startup small and creates fast reset prompts when a session approaches its model window.
# From the workspace Hermes should use:
remaind init
# Install the provider + context engine and update Hermes config safely:
remaind hermes activate --workspace "$PWD"
# Fast readiness checks before opening Hermes:
remaind hermes status --require-ready
remaind hermes speed --checkpoint-smoke --require-ready
remaind hermes ux-proof --require-readyFor launch or release-candidate validation, run the full gate and save the reports. It checks installed readiness, low-noise UX, live Hermes loading, source-linked task quality, provider comparison, lifecycle safety, and the repeated reset loop.
# Full launch gate:
remaind hermes verify \
--force \
--include-live \
--context-window 131072 \
--total-tokens 500000 \
--report-dir reports/hermes-launch-gate
# Shareable diagnostic bundle:
remaind hermes support-bundle \
--out reports/hermes-support \
--force \
--zip \
--include-live
remaind hermes support-bundle-check --bundle reports/hermes-support.zip| Gate | What it proves |
|---|---|
| Memory provider | Hermes loads RemaindMemoryProvider with context, search, capture, handoff, and checkpoint tools. |
| Context engine | Hermes loads RemaindContextEngine so context pressure creates task-slice reset prompts. |
| Speed | Startup context stays small, cached, and measurable before a live model session starts. |
| UX proof | The recommended low-noise Hermes path stays small, checkpoint-ready, and warns when default startup is heavy. |
| Reset loop | At the 70% guard, Remaind creates TASK_SLICE_BRIEF.md and CONTEXT_RESET_PROMPT.md without broad resume-packet startup. |
| Long tasks | The long-run proof repeats reset/resume cycles beyond a 500k-token simulated workload. |
| Support | The support bundle verifies checksums, UX proof evidence, redaction, and absence of project memory. |
The public API
import remaind is the entire stable surface. Everything in remaind.__all__ is stable; the underscore-prefixed modules are internal — do not import from them.
import remaind
remaind.__all__ # the entire stable public surface
remaind.__version__The five-step integration
Initialize — once per project
Create the .context/ directory, then read the session_id and task_id that init generated — every event you log needs them.
import remaind
base = "./my-agent-run" # the directory that will hold .context/
remaind.init(base) # creates base/.context/ (InitError if it exists)
# Every event needs a session_id + task_id — generated by init, read once:
state = remaind.status(base)
session_id = state["session_id"]
task_id = state["task_id"]Log events as the agent works
Open one EventWriter for the run and append an event for every meaningful thing that happens.
artifacts/ with excerpts + a hash kept in the event. UTF-8 bytes that look like text are decoded and redacted first.writer = remaind.EventWriter.open(base)
writer.append(remaind.EventInput(
type="user_message",
actor="user",
summary="Asked to refactor the auth module", # short — for handovers & search
session_id=session_id,
task_id=task_id,
content="Please refactor src/auth/ to use the new token format...",
importance=3, # a critical user instruction
))Event types: user_message, assistant_message, tool_call, tool_result, command_output, file_change, decision, error. (compaction, validation, resume, rollback, init are written by Remaind itself.)
Importance drives what compaction preserves — tag it honestly. 0 trace · 1 normal · 2 decision / file change / blocker / result (always preserved) · 3 critical user instruction / active next step (explicit in state or handover). See the Docs for the full table.
Keep the derived state current as work progresses — update_state validates, recomputes the threshold band, and writes atomically with a history snapshot:
remaind.update_state(base, lambda st: {
**st,
"next_step": "wire the new token format into the middleware",
"decisions": st["decisions"] + ["token format v2"], # lists are append-only
})Track the context budget
Remaind does not see your real model window — you feed it an estimate; it tells you which band you are in.
tokens = remaind.estimate_tokens(whole_context_so_far)
remaind.update_state(base, lambda st: {**st, "estimated_context_tokens": tokens})
cs = remaind.compaction_status(base)
cs.band # "normal" | "warning" | "hard" | "emergency"
cs.recommendation # human-readable next action
cs.compaction_needed # band != "normal"
cs.compaction_urgent # band is "hard" or "emergency"Compact when the band climbs
A compactor only proposes a candidate; a structured validator decides whether to accept it. If the candidate drops a decision, ungrounds next_step, or fails to represent an importance = 3 item, it is rejected and the prior handover is kept untouched.
try:
result = remaind.compact(base)
print(f"handover {result.handover_chars_before} -> {result.handover_chars_after} chars")
except remaind.CompactionRejected as exc:
# The candidate was unfaithful. Nothing lost — the prior handover stands.
# A validation event records exactly why.
print("rejected:", exc.validation["missing_items"])
except remaind.CompactionError as exc:
print("compaction could not run:", exc)Handoff into a fresh context
When you start a fresh model context — a new run, after hitting the window limit, or when moving work to another model — start a transfer so the receiver gets the packet, adapter bundle, capture contract, and finish command in one folder. Injecting it is your job: Remaind assembles the working memory; your harness decides where it goes in the next model context.
# Start a model-to-model transfer:
remaind transfer start --path ./my-agent-run \
--from-model "source model" \
--to-model "receiving model" \
--completed "implemented the retry route" \
--decision "use provider + event_id for idempotency" \
--next-step "run the focused retry tests"
# After the receiving model writes its final output:
remaind transfer finish --path ./my-agent-run \
--from-model "receiving model" \
--from-file receiver-output.mdFor embedded loops, remaind.resume(base) remains the lower-level packet builder:
result = remaind.resume(base)
fresh_context = result.packet.content # markdown — assembled for a fresh agent
# Injecting the packet is YOUR job — typically prepended to the new
# context's system prompt or sent as its first message:
start_model_session(system_prompt=BASE_PROMPT + "\n\n" + fresh_context)
gate = result.packet.gate
if gate.should_interrupt:
for concern in gate.concerns: # conflict / missing next_step /
print("RESUME GATE:", concern) # unrepresented instruction / risky toolReference
A complete minimal agent loop
The five steps above, wired into one loop — copy it as a starting point.
import remaind
base = "./my-agent-run"
remaind.init(base)
state = remaind.status(base)
sid, tid = state["session_id"], state["task_id"]
writer = remaind.EventWriter.open(base)
def log(type_, actor, summary, *, content=None, importance=1):
writer.append(remaind.EventInput(
type=type_, actor=actor, summary=summary,
session_id=sid, task_id=tid, content=content, importance=importance,
))
# No compactor to wire — remaind.compact() uses your configured model
# automatically if one is reachable, and the rule-based fallback otherwise.
while not done:
user_msg = get_user_message()
log("user_message", "user", user_msg[:80], content=user_msg, importance=3)
reply, tool_calls, total_tokens = run_model_turn(...)
log("assistant_message", "assistant", reply[:80], content=reply)
for call in tool_calls:
log("tool_call", f"tool:{call.name}", call.summary, content=call.args)
log("tool_result", f"tool:{call.name}", call.result_summary,
content=call.result, importance=2)
remaind.update_state(base, lambda st: {**st, "estimated_context_tokens": total_tokens})
cs = remaind.compaction_status(base)
if cs.compaction_urgent:
try:
remaind.compact(base) # uses your configured model if reachable
except remaind.CompactionRejected:
pass # prior handover kept — safe
if cs.band == "emergency":
packet = remaind.resume(base).packet
reset_model_context(packet.content) # your code injects itThe beyond-context pattern
For tasks with more source material than the model can see at once, do not try to force the archive into a single prompt. Store the raw evidence locally, promote durable facts with source links, then feed the fresh model only the validated resume packet.
# Pattern for work larger than the live model window:
# 1. Store raw evidence as events/artifacts.
# 2. Promote durable facts into state, handover, or source-linked memories.
# 3. Build a small resume packet for the next model window.
writer.append(remaind.EventInput(
type="tool_result",
actor="tool:archive_reader",
summary="indexed archive segment 42",
session_id=sid,
task_id=tid,
content=large_segment, # routed to artifacts/ when large
importance=2,
))
packet = remaind.resume(base).packet
assert packet.token_count < 24_000
start_model_session(system_prompt=BASE_PROMPT + "\n\n" + packet.content)Run a huge prompt from terminal
For users who just want to point Remaind at a large local report, transcript, or prompt file, remaind run is the direct route. It initializes .context/ when needed, indexes the file, builds active/run_packet.md, calls the configured model with that compact packet, writes active/run_answer.md, and logs the task back into Remaind.
# Guided memory-first launch:
remaind launch --path ./my-agent-run
remaind launch --path ./my-agent-run --input file --file /absolute/path/to/huge-prompt.md
cat /absolute/path/to/huge-prompt.md | remaind launch --path ./my-agent-run --input paste --task "solve this task"
# One-command terminal path for a huge local prompt/report:
remaind run /absolute/path/to/huge-prompt.md "solve this task" --path ./my-agent-run
# Packet only, no generation:
remaind run /absolute/path/to/huge-prompt.md "solve this task" --path ./my-agent-run --no-model
# Optional: force extra evidence searches:
remaind run /absolute/path/to/huge-prompt.md "find contradictions" --query "revenue assumption" --query "cost forecast"Compaction runs on your chosen model
remaind.compact(base) takes no model arguments — it is invisible by design, and supports local-first or API-backed model endpoints over plain HTTP:
- Ollama — auto-detected on its universal default port. If it's running, Remaind just uses it. Nothing to configure.
- OpenAI-compatible servers — opt-in (vLLM, llama.cpp, LM Studio, hosted-compatible gateways, …). No canonical port, so set
REMAIND_OPENAI_BASE_URLto the endpoint's/v1URL; it takes precedence over Ollama. UseREMAIND_OPENAI_API_KEYwhen the endpoint requires a bearer token.
If neither is reachable, compaction falls back to deterministic rule-based bookkeeping that never fails. If you configure an external API endpoint, only the compact prompt for that model-backed operation is sent to that provider.
Optional environment overrides — the Ollama zero-config path needs none: OLLAMA_HOST, REMAIND_OLLAMA_MODEL, REMAIND_OPENAI_BASE_URL, REMAIND_OPENAI_MODEL, and REMAIND_DISABLE_LOCAL_MODEL (force the rule-based compactor).
remaind compact reports which compactor ran — e.g. via local model via Ollama (llama3.1), via OpenAI-compatible API (model-name), or rule-based fallback — so you can confirm your model is actually in use.
- Pick a chat model. Without
REMAIND_OLLAMA_MODEL/REMAIND_OPENAI_MODEL, the first model the runtime lists is used — if that's an embedding or base model it can't follow the compaction prompt, so the candidate is rejected and the handover never shrinks (safe, but stuck). - Detection is fast and silent. A ~1s probe — a runtime that's up but slow to answer reads as absent and you fall back to rule-based with no error. Check the
remaind compactoutput line.
Reviewed handoff memory
For compliance-reviewed handoffs, store the reviewed item with source evidence, reviewer identity, reason, and typed scope. Later handoffs request a packet for the exact reviewed subject; ambiguity fails closed and unresolved conflicts escalate before the model acts.
from datetime import UTC, datetime
import remaind
base = "./finance-agent-run"
as_of = datetime(2026, 5, 28, 15, 0, tzinfo=UTC)
remaind.init(base)
state = remaind.status(base)
writer = remaind.EventWriter.open(base)
source = writer.append(remaind.EventInput(
type="tool_result",
actor="tool:compliance-review",
summary="Compliance approved Orion Capital marketing disclosure",
session_id=state["session_id"],
task_id=state["task_id"],
content="Reviewer approved this disclosure only for Orion Capital.",
importance=3,
tags=["finance", "policy_exception", "reviewed_source"],
source="compliance review",
))
item = remaind.make_reviewed_memory_item(
item_id="rm-orion-marketing-approval",
kind=remaind.ReviewedMemoryKind.EXCEPTION,
disposition=remaind.ReviewDisposition.APPROVE,
subject_key="policy:marketing_disclosure:orion-capital",
statement="Compliance approved the Orion Capital marketing disclosure.",
reason="Reviewer confirmed the disclosure copy was already approved.",
scope=remaind.ReviewedScope(
client_account=remaind.AccountRef("orion-capital"),
workflow="policy_exception",
jurisdiction="US",
),
reviewer=remaind.ReviewerRef("reviewer-compliance-1", "compliance_reviewer"),
created_at=as_of,
source_event_ids=(source["id"],),
audit_tags=("finance", "policy_exception"),
)
remaind.append_reviewed_memory_item(base, item)
packet = remaind.build_reviewed_memory_packet_from_store(
base,
request_context=remaind.ReviewRequestContext(
client_account_id="orion-capital",
workflow="policy_exception",
subject_key="policy:marketing_disclosure:orion-capital",
jurisdiction="US",
),
as_of=as_of,
)
assert packet.packet.surfaced_ids == ("rm-orion-marketing-approval",)remaind demo finance-handoff --force to see this flow write source events, capture reviewed memories, rebuild packets from the real ledger, and report Packet Recall, False Application Rate, Honor Rate, and Reviewed Decision Retention.The starter kit path
If you want a full local-first operator setup instead of embedding the library yourself, use the Sovereign Memory starter kit. It adds bootstrap, model profiles, readiness checks, startup prompts, Qwen Code and console adapters, and built-in proofs.
cd starter-kits/sovereign-memory-starter
./bootstrap.sh --profile qwen-large --agent qwen-code
remaind monitor --smoke
make proof-2mProfiles are available for OpenAI-compatible API models, local runtimes, and custom model servers. Starter profiles use local project folders that the operator controls.
CLI for shell-out harnesses
Harnesses that shell out rather than import can drive the lifecycle ops directly: remaind init, validate, status --json, compact, resume, capture, handoff, rollback --to, and run FILE "TASK". Fine-grained event logging is still Python API driven, while post-work capture can be done from the terminal with remaind capture. Sensitive workspaces can start with remaind init --secure, open a bounded handoff window with remaind unlock --ttl 30m, export through remaind handoff --secure --ttl 30m, then remaind handoff-decrypt in the receiving folder. See the Docs for the full CLI reference.
What Remaind does not do for you
- It does not run your agent loop — you drive the loop, while compact/run can call your configured model endpoint.
- It does not guess your live model window — your harness or provider passes token telemetry, and Remaind acts on that signal.
- It does not decide event importance — you tag each event.
- It does not inject the resume packet — resume assembles it; placing it is your harness's job.
- It does not provide one-shot full attention across every token in a giant archive.
- It does not summarize without a model — when no configured model is reachable, compaction is rule-based bookkeeping and the handover grows.
- It is single-writer — do not point two processes at one .context/.
Exception reference
| Exception | Raised by | Meaning / what to do |
|---|---|---|
| InitError | init | .context/ already exists — use force=True or a clean base. |
| EventValidationError | EventWriter.append | the event failed its schema — nothing was appended; inspect exc.event. |
| StateValidationError | update_state | the mutator returned a schema-invalid state — state.json untouched. |
| HandoverValidationError | write_handover | the handover is missing a required section — see exc.missing. |
| CompactionRejected | compact | the validator rejected the candidate — prior handover stands; inspect exc.validation. |
| CompactorResponseError | compact (model-backed path) | the model endpoint was unreachable or returned an unusable response — usually transient; check the runtime or API configuration. |
| RunError | run_prompt / remaind run | the source file, local retrieval, context setup, or model call failed — run doctor --smoke or retry with --no-model. |
| LargeDocumentError | large-doc APIs | source file missing, context not initialized, source drift, invalid regex, or invalid line range. |
| RollbackError | rollback | unparseable target, or no snapshot covers it. |