Skip to content

Enforce the memory read → dedupe → write → update-index protocol (#4116)#4388

Closed
M3gA-Mind wants to merge 4 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/GH-4116-memory-protocol
Closed

Enforce the memory read → dedupe → write → update-index protocol (#4116)#4388
M3gA-Mind wants to merge 4 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/GH-4116-memory-protocol

Conversation

@M3gA-Mind

@M3gA-Mind M3gA-Mind commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Closes #4116

Problem

The memory protocol (read-index → dedupe → write → update-index) was described to the agent but never enforced, so it was followed inconsistently: durable writes (memory_store) landed without a dedupe read (creating near-duplicates) and update_memory_md was skipped, so MEMORY.md drifted from the underlying store.

Enforcement approach

Expressed as a tinyagents graph middleware — the same "structured correction surfaced back to the model" pattern the unknown-tool recovery (#4118 / #4360) uses, and the live tool-dispatch seam.

  • agent/harness/memory_protocol.rs (new) — a pure, side-effect-free MemoryProtocolTracker state machine. classify_memory_op sorts the memory tool surface into IndexRead (memory_recall/memory_search/memory_tree_* reads), Write (memory_store/memory_forget/memory_tree_ingest_document), and IndexUpdate (update_memory_md). The tracker enforces the repeatable cycle: a write reports missing_index_read when no dedupe read preceded it and index_drift when a prior write was never synced; update_memory_md closes the cycle and arms the next; pending_index_update() exposes an unsynced write at run end.
  • tinyagents/middleware.rsMemoryProtocolMiddleware. Its after_tool advances the tracker on each successful memory op (failed ops don't demand an index update) and appends a [memory-protocol] corrective note to the tool result the model reads. Its after_agent warns when the run ends with a write that was never followed by update_memory_md.
  • tinyagents/mod.rs — registers the middleware outermost so its after_tool runs last (after the byte-cap truncation, since after-hooks run in reverse order) and the guidance survives into the transcript. No-op on turns that never touch memory.

This satisfies the acceptance criteria: enforces the read-index → dedupe → write → update-index sequence as a post-step check, and detects a write not preceded by an index read / not followed by an index update, then corrects (guidance to the model) or warns (run end).

Tests

  • memory_protocol.rs: 7 unit tests — classification, clean full cycle, missing-read flag, drift-at-next-write, pending-index-update at run end, cycle re-arming after an update, reads/other ops need no guidance.
  • middleware.rs: 4 integration tests — note appended on an unread write, clean read→write→update only reminds on the write, a failed write does not advance the protocol, a second unsynced write flags drift.

Caveat

Runtime drift detection ("write not followed by update_memory_md") fires at the next memory write within the run and is logged at run end via after_agent; the per-write forward reminder is the proactive correction. Local cargo check is clean; relying on CI for the test run.

Summary by CodeRabbit

  • New Features
    • Added memory-protocol enforcement for agent runs, including tracking of memory tool call order and a corrective note when the expected sequence is broken.
    • Introduced run-end checks to flag when memory content may be out of sync.
  • Bug Fixes
    • Prevented failed memory operations from advancing protocol state.
    • Improved detection of missing read steps and repeated writes without an intervening refresh.
  • Tests
    • Added coverage for valid cycles, violation detection, failed writes, and stale-memory handling.

…sai#4116)

Agents were told to follow a read-index -> dedupe -> write -> update-index
cycle around durable memory but it was never enforced, so writes landed
without a dedupe read (duplicating entries) and update_memory_md was
skipped (leaving MEMORY.md drifting from the store).

Add a MemoryProtocolTracker state machine and drive it from a tinyagents
MemoryProtocolMiddleware: on each successful memory op it advances the
cycle and, on a write, appends a corrective note to the tool result the
model reads (flagging a missing dedupe read or a drifting index), then
warns at run end when a write was never followed by update_memory_md.
Same structured-correction-surfaced-to-the-model pattern as the
unknown-tool recovery. Registered outermost so its guidance survives the
after-tool byte cap.
@M3gA-Mind M3gA-Mind requested a review from a team July 1, 2026 18:10
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 31 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ad40f700-e96c-4f70-946d-8bc792b0c083

📥 Commits

Reviewing files that changed from the base of the PR and between 4c98a31 and e4a2ee8.

📒 Files selected for processing (4)
  • src/openhuman/agent/harness/memory_protocol.rs
  • src/openhuman/agent/harness/mod.rs
  • src/openhuman/tinyagents/middleware.rs
  • src/openhuman/tinyagents/mod.rs
📝 Walkthrough

Walkthrough

Adds a new memory_protocol module implementing a state machine that classifies memory tool calls and detects violations of the read→dedupe→write→update-index protocol. Wires a new MemoryProtocolMiddleware into the tinyagents harness to append corrective guidance and warn on stale memory index at run end.

Changes

Memory protocol enforcement

Layer / File(s) Summary
Protocol contracts and classification
src/openhuman/agent/harness/memory_protocol.rs
Defines MEMORY_PROTOCOL_MARKER, MemoryOp enum, classify_memory_op, and MemoryProtocolObservation with guidance generation for missing index reads and index drift.
Tracker state machine and tests
src/openhuman/agent/harness/memory_protocol.rs, src/openhuman/agent/harness/mod.rs
MemoryProtocolTracker tracks per-session read→write→update-index cycles, exposes observe/observe_tool/pending_index_update, module declared in harness mod.rs, plus unit tests for classification and cycle behaviors.
Middleware integration and wiring
src/openhuman/tinyagents/middleware.rs, src/openhuman/tinyagents/mod.rs
MemoryProtocolMiddleware observes successful memory tool calls, appends corrective guidance to write results, warns on stale index in after_agent, is pushed into the harness middleware stack after tool-output truncation, and is covered by new tests.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
    participant Agent
    participant Middleware as MemoryProtocolMiddleware
    participant Tracker as MemoryProtocolTracker
    participant ToolResult

    Agent->>Middleware: after_tool(memory write result)
    Middleware->>Tracker: observe_tool(tool_name)
    Tracker-->>Middleware: MemoryProtocolObservation
    alt needs_guidance
        Middleware->>ToolResult: append corrective guidance note
    end
    Agent->>Middleware: after_agent(run end)
    Middleware->>Tracker: pending_index_update()
    Tracker-->>Middleware: true/false
    alt pending update
        Middleware->>Agent: emit stale-index warning
    end
Loading

Suggested labels: agent

Poem

A rabbit reads the index page,
before it writes, at every stage 🐇
Write, then update, don't skip the cage,
MEMORY.md stays free of rage.
Hop, sync, and close the loop with glee!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly states the main change: enforcing the memory read→dedupe→write→update-index protocol.
Linked Issues check ✅ Passed The PR implements the requested memory protocol enforcement, stale-index detection, and regression tests.
Out of Scope Changes check ✅ Passed The changes stay focused on memory-protocol tracking, middleware enforcement, and related tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. label Jul 1, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1243ede870

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/openhuman/agent/harness/memory_protocol.rs Outdated
Comment thread src/openhuman/agent/harness/memory_protocol.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/agent/harness/mod.rs`:
- Line 35: Move the new memory protocol wiring out of the flat root-level module
file and into a dedicated submodule directory. Update the `mod memory_protocol;`
declaration in `harness::mod` to point at the relocated module under
`memory_protocol/mod.rs`, and ensure any associated module files live within
that subdirectory rather than as a new top-level `memory_protocol.rs`.

In `@src/openhuman/tinyagents/mod.rs`:
- Around line 393-400: The memory-protocol enforcement is only added in
run_turn_via_tinyagents_shared, leaving run_turn_via_tinyagents without the same
harness middleware. Update run_turn_via_tinyagents to install
MemoryProtocolMiddleware on its harness too, matching the shared path so both
entrypoints enforce the read → dedupe → write → update-index flow consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 93e32ce0-9d78-4d65-8543-9504bab66fb2

📥 Commits

Reviewing files that changed from the base of the PR and between 4c98a31 and 1243ede.

📒 Files selected for processing (4)
  • src/openhuman/agent/harness/memory_protocol.rs
  • src/openhuman/agent/harness/mod.rs
  • src/openhuman/tinyagents/middleware.rs
  • src/openhuman/tinyagents/mod.rs

Comment thread src/openhuman/agent/harness/mod.rs
Comment thread src/openhuman/tinyagents/mod.rs
…oints

- Classify memory_tree(mode=ingest_document) as a Write and update_memory_md
  only as an index-update when file=MEMORY.md (a SKILL.md edit no longer masks
  a stale MEMORY.md index). Arguments are captured in the middleware's
  before_tool hook (keyed by call id) since the tool result carries none.
- Install MemoryProtocolMiddleware on the run_turn_via_tinyagents entrypoint
  too, so both harness-build paths enforce the cycle consistently.
- Extend unit + middleware tests for the SKILL.md and memory_tree-ingest cases.
@M3gA-Mind

Copy link
Copy Markdown
Collaborator Author

Review feedback addressed (e4a2ee8)

Fixed in code (3):

  • Codex P1 — memory_tree ingest is a write: classify_memory_op is now argument-aware. memory_tree with mode: "ingest_document" classifies as a Write (obliges update_memory_md, reports drift on the next unsynced write) instead of a read. Arguments are captured in the middleware's new before_tool hook (keyed by call id) since the tool result carries none.
  • Codex P2 — SKILL.md updates must not close the memory cycle: update_memory_md only counts as an index-update when file == "MEMORY.md"; a SKILL.md edit is Other and no longer clears pending_index_update, so the stale-index warning still fires on later writes and at run end.
  • CodeRabbit (functional) — enforce on both entrypoints: MemoryProtocolMiddleware is now installed on run_turn_via_tinyagents too, matching run_turn_via_tinyagents_shared.

Dismissed (1):

  • CodeRabbit (maintainability) — move to a submodule directory: agent/harness/ is an existing module whose parts are flat sibling files by convention (memory_context.rs, memory_context_safety.rs, fork_context.rs, parse.rs, …). memory_protocol.rs follows that layout; a lone memory_protocol/mod.rs dir would break local consistency. The 'no root-level *.rs' guideline targets new top-level src/openhuman/<domain> files.

New regression tests cover the SKILL.md and memory_tree ingest cases. cargo check + cargo fmt --check clean locally.

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
fd memory_protocol.rs
echo "---"
sed -n '1,120p' src/openhuman/agent/harness/memory_protocol.rs 2>/dev/null | head -200

Length of output: 6395


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "MemoryProtocolMiddleware" src/openhuman/tinyagents/mod.rs
echo "---"
rg -n "fn run_turn_via_tinyagents\b" -A 20 src/openhuman/tinyagents/mod.rs

Length of output: 1647


All three fixes check out against the code: classify_memory_op is now argument-aware for memory_tree/update_memory_md, SKILL.md edits correctly stay Other, and MemoryProtocolMiddleware is now installed on both run_turn_via_tinyagents (Line 236) and run_turn_via_tinyagents_shared (Line 404). I also agree the flat-file layout in agent/harness/ is a reasonable call given the existing sibling-file convention there.

Kicking off a full review now to go through the rest of the diff (including the new before_tool call-id correlation and regression tests) with fresh eyes.

✅ Action performed

Full review finished.

@M3gA-Mind

Copy link
Copy Markdown
Collaborator Author

Superseded by #4444 — a rework onto post-#4399 main. The turn loop now runs on the tinyagents crate, so the memory protocol is re-expressed as a crate middleware (MemoryProtocolMiddleware) in the src/openhuman/tinyagents/ seam instead of the (migrated) turn engine. #4444 keeps the full MemoryProtocolTracker state machine + all tests, and fixes a stale classification (memory_search isn't a real tool → memory_vector_search/memory_chunk_context/memory_hybrid_search). Closing in favor of #4444.

@M3gA-Mind M3gA-Mind closed this Jul 3, 2026
M3gA-Mind added a commit to M3gA-Mind/openhuman that referenced this pull request Jul 3, 2026
…dex protocol (tinyhumansai#4116)

Rework of tinyhumansai#4388 onto post-tinyhumansai#4399 code. tinyhumansai#4399 deleted the original home
(agent/harness/memory_protocol.rs did not exist yet; the enforcement was to
live in the turn engine); the turn loop now runs on the tinyagents crate, so
this re-expresses the protocol as a crate middleware.

- Ports the pure `MemoryProtocolTracker` state machine as
  src/openhuman/agent/harness/memory_protocol.rs: classifies each memory tool
  call (IndexRead / Write / IndexUpdate / Other) and, on a write, flags a
  missing dedupe read or a stale index (a prior write never followed by
  update_memory_md).
- Adds `MemoryProtocolMiddleware` in the tinyagents adapter seam: before_tool
  captures the classified op by call id; after_tool advances the tracker on
  success and appends a `[memory-protocol]` corrective note to the tool result
  so the model is nudged back onto the cycle; after_agent warns when the run
  ends with a stale index. Registered outermost in assemble_turn_harness so its
  after_tool runs after the byte-cap truncation, preserving the note.
- Fixes a stale classification from the original PR: `memory_search` is not a
  real tool — replaced with the actual dedupe-read search tools
  (memory_vector_search / memory_chunk_context / memory_hybrid_search).

9 unit tests (classification + tracker ladder) + 4 middleware integration
tests (corrective note, SKILL.md doesn't close the cycle, consolidated
memory_tree ingest = write, failed write doesn't advance). All green.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Harness] Memory protocol not followed — MEMORY.md not read for dedupe, update_memory_md skipped

2 participants