Skip to main content
Version: MVP

Memory Proposals

5 min readFor runners & reviewersUpdated 2026-05-19

What you'll do

Create, list, approve, and reject memory proposals — the default path for any agent-initiated memory update in Craik. By the end you'll know the full proposal lifecycle, the promotion rule that gates approval, and how run outputs feed proposals during execution.

Proposal-first

Craik defaults to reviewable memory proposals instead of direct durable writes. Proposals require evidence, remain visible for audit whether approved or rejected, and never become durable facts until a reviewer (or a memory.write grant) promotes them.

The lifecycle in one diagram

agent or human ──propose──▶ memory_proposal (pending)

├── reviewer approves ─▶ fact (local)
├── reviewer rejects ─▶ stays for audit
└── promotion expires ─▶ stays pending

1 · Create a proposal

A proposal with explicit evidence
craik memory propose task_review_docs \
--entity repo:example \
--relation craik:current_state \
--value "Local proposals require review." \
--source README.md \
--evidence-source README.md \
--evidence-locator README.md#memory \
--evidence-summary "README documents local proposal behavior."

The flags map directly to a craik.memory_proposal record:

Flag
Type
Purpose
--entity
entity_uri
The subject of the fact: repo:example, project:product, etc.
--relation
relation_name
The predicate, namespaced: craik:current_state, product:owner.
--value
text
The object of the fact, in plain language.
--source
uri
Where the proposal originated — file, URL, fact id.
--evidence-source / --evidence-locator / --evidence-summary
evidence_reference
The evidence reference that supports the proposal. Required for promotion.

2 · List and filter

Proposals for a task
craik memory list --task-id task_review_docs
All pending proposals
craik memory list --status pending

3 · Approve or reject

Approve with reasoning
craik memory approve memprop_review_docs_repo_example_craik_current_state \
--decided-by user:reviewer \
--reason "Evidence supports the proposal."
Reject with reasoning
craik memory reject memprop_review_docs_repo_example_craik_current_state \
--decided-by user:reviewer \
--reason "Too broad for durable memory."

Both decisions are durable. Rejected proposals remain queryable for audit — you can answer "did we ever consider this fact and why did we reject it?" months later.

4 · Search approved facts

Search promoted facts
craik memory search "local proposals"

Pending and rejected proposals are not returned as facts. They remain in local state for audit and later review, but the fact-search path only sees what's been promoted.

The promotion rule

Promotion requires evidence.

A proposal without an evidence reference cannot be approved. Period. The runtime refuses to promote it.

This is the single most important invariant in the memory system. Break it, and downstream case files start inheriting unverifiable facts. Keep it, and every approved fact in memory can be traced back to source material a reviewer signed off on.

Direct writes need a separate path

Direct durable writes still require a matching memory.write policy grant. Until that grant exists, even runs operating under broad capability postures must use proposals.

Without memory.write:

  1. The runtime creates a proposal instead of writing.
  2. The proposal references the run that produced it.
  3. A receipt is sealed naming the missing capability.
  4. The reviewer flow decides whether to grant or to keep proposing.

This is the same pattern as every other capability — see Capability grants for the full shape.

Proposals during runs

Runner step observations are stored as craik.run_output records before they become memory. A run output can create reviewable proposals, but it cannot write durable facts directly.

Run-created proposals keep links to:

run_id

The run that produced the proposal.

step_id

The specific runner step inside the run.

handoff_id

The handoff that closed the run, when one exists.

Evidence reference

Points back to the run output and step result so reviewers can inspect what the runner actually observed.

Blocked or failed step results are captured for inspection but do not create memory proposals. Only completed and partial step results may create proposals, and only when the executor supplies explicit proposal specs. This stops a flailing run from contaminating the proposal queue.

What's next