Skip to content

feat(agent-harness): memory read→dedupe→write→update-index protocol — rework of #4388 - #4444

Merged
senamakel merged 2 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/GH-4116-memory-protocol-rework
Jul 3, 2026
Merged

feat(agent-harness): memory read→dedupe→write→update-index protocol — rework of #4388#4444
senamakel merged 2 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/GH-4116-memory-protocol-rework

Conversation

@M3gA-Mind

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

Copy link
Copy Markdown
Collaborator

Summary

Rework of #4388 onto post-#4399 main. Enforces the read-index → dedupe → write → update-index memory protocol: on each successful memory write the agent gets a [memory-protocol] corrective note if it skipped the dedupe read or left MEMORY.md stale, and the run warns at the end if an index update was never issued.

Why a rework

The turn loop now runs on the tinyagents crate (#4399), so the protocol is re-expressed as a crate middleware in the adapter seam rather than in the turn engine.

Changes

  • New src/openhuman/agent/harness/memory_protocol.rs — pure MemoryProtocolTracker state machine: classify_memory_op(name, args)IndexRead / Write / IndexUpdate / Other, and the ladder that flags missing_index_read / index_drift on writes. No harness deps → fully unit-testable.
  • MemoryProtocolMiddleware (src/openhuman/tinyagents/middleware.rs) — before_tool captures the op by call id, after_tool advances the tracker on success and appends the corrective note, after_agent warns on a stale index. Registered outermost in assemble_turn_harness so its after_tool runs after the byte-cap truncation (note survives).
  • Fix vs. the original PR: memory_search is not a registered tool — replaced with the real dedupe-read search tools (memory_vector_search / memory_chunk_context / memory_hybrid_search).

Tests

9 unit tests (classification + tracker) + 4 middleware integration tests (corrective note appears; SKILL.md update does not close the memory cycle; consolidated memory_tree ingest treated as a write; a failed write does not advance the protocol). All green.

Related

Summary by CodeRabbit

  • New Features
    • Added automatic memory-use guidance during tool runs to help keep memory updates consistent.
    • The app now tracks memory-related actions and can append corrective notes when the expected read/write/update sequence is skipped.
    • Memory updates are now monitored end-to-end, with a warning if the index may be left stale after a write.
  • Tests
    • Added coverage for memory action sequencing, stale-index detection, and failed-write handling.

@M3gA-Mind
M3gA-Mind requested a review from a team July 3, 2026 14:32
@coderabbitai

coderabbitai Bot commented Jul 3, 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: 12 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: e2b03e43-ae26-4bcb-9457-d6d567343da4

📥 Commits

Reviewing files that changed from the base of the PR and between b17780c and b4da65e.

📒 Files selected for processing (1)
  • src/openhuman/tinyagents/tests.rs
📝 Walkthrough

Walkthrough

Introduces a new memory-protocol enforcement module that classifies memory-related tool calls and tracks a read→write→update-index cycle. Wires a new MemoryProtocolMiddleware into the tinyagents harness to annotate tool results with corrective guidance and warn on stale MEMORY.md at run end.

Changes

Memory Protocol Enforcement

Layer / File(s) Summary
Protocol classification and cycle tracker
src/openhuman/agent/harness/memory_protocol.rs, src/openhuman/agent/harness/mod.rs
Adds MemoryOp classification, MemoryProtocolObservation guidance text generation, and MemoryProtocolTracker per-session cycle state machine, wired via a new pub(crate) module declaration, with unit tests for classification and cycle/violation behavior.
Middleware integration and harness wiring
src/openhuman/tinyagents/middleware.rs, src/openhuman/tinyagents/mod.rs
Adds MemoryProtocolMiddleware implementing before_tool/after_tool/after_agent to track pending ops, append corrective annotations to tool results, and warn about stale MEMORY.md; installs it in assemble_turn_harness before the repeated-tool-failure breaker, with expanded async tests.

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

Sequence Diagram(s)

sequenceDiagram
  participant Harness as Turn Harness
  participant Middleware as MemoryProtocolMiddleware
  participant Tracker as MemoryProtocolTracker
  participant ToolResult as Tool Result

  Harness->>Middleware: before_tool(call_id, tool_name, args)
  Middleware->>Middleware: classify_memory_op, store pending
  Harness->>ToolResult: execute tool
  ToolResult-->>Harness: result
  Harness->>Middleware: after_tool(call_id, result)
  Middleware->>Tracker: observe(op) if no error
  Tracker-->>Middleware: observation (missing_index_read, index_drift)
  Middleware->>ToolResult: append guidance text
  Harness->>Middleware: after_agent()
  Middleware->>Tracker: pending_index_update()
  Tracker-->>Middleware: true/false
  Middleware-->>Harness: emit warning if stale
Loading

Suggested labels: feature, agent

Poem

A rabbit tracks the memory trail,
Read then write, don't let it fail~
🐇 hop, hop through IndexUpdate's door,
Guidance whispered, drift no more,
MEMORY.md stays fresh and true,
Thanks to burrows built anew!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR does not fix the #4442 build break; it adds memory-protocol middleware instead of the required orchestration checkpoint and graph_fn fixes. Implement the #4442 mechanical build fix: remove the stale SqlRunLedgerCheckpointer reference, wrap graph_fn in Some(...), and switch checkpointing to SqliteCheckpointer.
Out of Scope Changes check ⚠️ Warning The diff is entirely about memory protocol enforcement, which is unrelated to the linked #4442 orchestration build-fix scope. Remove the memory-protocol changes or retarget the PR to the linked orchestration build-fix issue.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the added memory protocol middleware and tracker, matching the main changeset.
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.

@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: fa69e393b1

ℹ️ 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".

}
// The always-on closing-step reminder: keep the index in sync.
parts.push(
"After mutating memory, call `update_memory_md` to keep the MEMORY.md index in sync."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Register update_memory_md before requiring it

When a successful memory write occurs, this guidance tells the model to call update_memory_md, and that is the only operation that clears pending_index_update. In the current shared tool registry (all_tools_with_runtime), UpdateMemoryMdTool is only defined/re-exported and is never inserted into the tool vector, so normal agent turns are directed to an unavailable tool and will keep accumulating stale-index warnings after memory writes. Register the tool in the shared tool set or only emit this protocol when the tool is actually exposed.

Useful? React with 👍 / 👎.

// update-index cycle and append a corrective note when a write skips the
// dedupe read or leaves the index stale. Pushed first / outermost so its
// `after_tool` runs *after* the byte-cap truncation, keeping the note.
harness.push_middleware(Arc::new(middleware::MemoryProtocolMiddleware::new()));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Register the memory note after output capping

This middleware is pushed before context_mw.install(...), so its after_tool runs before the existing tool-output cap/summarization middleware in the same registration-order stack used by HandoffMiddleware and ToolOutcomeCaptureMiddleware. For memory writes with oversized results, ToolOutputMiddleware can then replace or truncate result.content after the memory-protocol note is appended, dropping the corrective note this comment says should survive; push this after the output-budget middleware (while still before outcome capture) or protect the note from capping.

Useful? React with 👍 / 👎.

…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.
@M3gA-Mind
M3gA-Mind force-pushed the fix/GH-4116-memory-protocol-rework branch from fa69e39 to b17780c Compare July 3, 2026 15:15
@coderabbitai coderabbitai Bot added agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. labels Jul 3, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 3, 2026
…entory

The memory-protocol enforcement middleware adds one lifecycle middleware
(registered outermost), so the adapter-inventory counts move 12→13 (window
present) and 10→11 (no window). Updates the registration-order comment too.
@senamakel
senamakel merged commit 19bf3aa into tinyhumansai:main Jul 3, 2026
15 checks passed
senamakel added a commit to senamakel/openhuman that referenced this pull request Jul 3, 2026
…t to the model (tinyhumansai#4116)

The memory-protocol enforcement middleware (tinyhumansai#4444) corrects violations
*after* they happen (a duplicate write, a drifted index), but the
read→dedupe→write→update-index contract was never actually stated to the
model in the live prompt — `memory_protocol.rs`'s "agents are instructed
to follow…" doc was aspirational; no prompt text described the sequence.
So dedupe was only ever nudged *after* a duplicate write landed, never
prevented.

State it up front in the two durable-write tools' descriptions:
- `memory_store`: recall existing memory (e.g. `memory_recall`) to check
  for a near-duplicate before storing; call `update_memory_md` after.
- `memory_forget`: call `update_memory_md` after removing an entry.

Test: `memory_store`'s `name_and_schema` asserts the description carries
the contract, so the up-front instruction can't silently regress.

The run-end stale-index case remains a `tracing::warn!` (the issue's
"correct or warn"); surfacing it model-visibly needs consistent
`final_response` + `messages` mutation and is left as follow-up.

Claude-Session: https://claude.ai/code/session_01KcmdqJVpjmnH31HqTHRLwG
senamakel added a commit to senamakel/openhuman that referenced this pull request Jul 4, 2026
…teering

Six Rust test failures surfaced by clean CI (merged without test parity):

- middleware (production regression, tinyhumansai#4473): the no-progress ladder's Nudge
  sent SteeringCommand::Redirect, which is NOT in the Interactive steering
  allowlist (InjectMessage + Pause only). Every interactive turn where a tool
  failed twice with identical args or four times with varied errors aborted the
  whole turn with a Steering error instead of nudging then halting gracefully.
  Switch the nudge to InjectMessage(system) — equivalent (append + Continue) but
  within the interactive policy. Fixes the three agent *_raw_coverage_e2e panics
  (turn_xml_failures…, bus_turn_halts_on_repeated_tool_error…,
  no_progress_guard_uses_default_iteration_fallback_when_zero).

- config schema catalog test: privacy-mode controllers (config_get/set_privacy_mode,
  added by tinyhumansai#4435/tinyhumansai#4446) were registered but the hand-maintained golden list in
  config_auth_app_state_connectivity_e2e.rs wasn't updated. Add the two entries.

- api::config backend_url test: tinyhumansai#4153 intentionally made a bare `/v1` base on an
  unknown host classify as an OpenAI-compatible inference base (with its own
  passing sibling test); the older contradictory assertion wasn't updated. Align
  it to expect the fallback.

- tinyagents middleware inventory tests: tinyhumansai#4444 added MemoryProtocolMiddleware
  (+1) and tinyhumansai#4473 removed CacheAlignMiddleware (-1), but the count literals were
  left at 13/11. Correct to 12/10 and drop cache-align from the comment.

Claude-Session: https://claude.ai/code/session_014RLnG2QbdL3n9TLtfomdhB
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/. feature Net-new user-facing capability or product behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants