Skip to content

fix(agent-server): propagate load_memory preference to all launch paths - #4566

Open
vnktadithya wants to merge 4 commits into
OpenHands:mainfrom
vnktadithya:fix/agent-server-load-memory-4542
Open

fix(agent-server): propagate load_memory preference to all launch paths#4566
vnktadithya wants to merge 4 commits into
OpenHands:mainfrom
vnktadithya:fix/agent-server-load-memory-4542

Conversation

@vnktadithya

Copy link
Copy Markdown
Contributor

HUMAN:

Resolves #4542 - The memory preferences weren't propagating through two of the three existing paths (agent and agent_settings).


AGENT:

Why

agent_settings.agent_context.load_memory is a global user preference, but it was only ever applied when a conversation launched via agent_profile_id. Conversations started with a concrete agent or an agent_settings payload silently lost the setting — no error, no warning, just a missing <MEMORY_CONTEXT> block, while MemorySection rendered its other variant so the transcript still looked healthy.

Root cause: _resolve_agent_from_profile was the only place the stored preference got stamped onto the agent, and that function is only reachable via the agent_profile_id branch. The other two request shapes (agent, and agent_settings — converted to agent by a mode="before" validator before _start_conversation even runs) never touched it.

Summary

  • Hoisted the settings-store read above the agent_profile_id branch in _start_conversation, so the load_memory stamp applies once, after all three request shapes converge on request.agent, instead of only on the profile path.
  • Added _with_load_memory() next to _append_system_message_suffix, using the same two-level model_copy pattern (required because AgentBase is frozen).
  • Removed the now-dead load_memory parameter from _resolve_agent_from_profile (signature, docstring, and inline body).

Issue Number

Fixes #4542

How to Test

Unit tests:

uv run pytest tests/agent_server/test_agent_profile_conv_start.py -q

Result: All 39 passed.

New coverage added:

  • test_direct_agent_launch_inherits_the_stored_memory_preference
  • test_direct_agent_launch_leaves_memory_off_without_the_preference (parametrized)
  • test_agent_settings_launch_inherits_the_stored_memory_preference
  • test_agent_settings_launch_leaves_memory_off_without_the_preference (parametrized)
  • test_agent_launch_preserves_context_when_load_memory_already_true

Existing test_profile_launch_inherits_the_stored_memory_preference and test_profile_launch_leaves_memory_off_without_the_preference pass unchanged — they now exercise the post-branch stamp instead of the in-helper one.

Unit tests alone rely on mocked stores, so I also ran an end-to-end pass against a real (non-mocked) settings store and a real MEMORY.md:

uv run python .pr/verify_load_memory_all_paths.py

Output:

Persisted load_memory=True for real at C:\temp\memory-check-settings\settings.json

=== Part A: does load_memory() read the file back? ===
# Project memory (.openhands/memory/MEMORY.md)
# Verification note
load_memory propagated correctly if you can read this.
PASS

=== Part B: does the real settings store reach the launched agent? ===
agent  -> agent_context.load_memory = True
agent_settings  -> agent_context.load_memory = True
All checks passed.

Acceptance criteria (from #4542)

  • With load_memory: true stored, a conversation started with a concrete agent has agent_context.load_memory is Truetest_direct_agent_launch_inherits_the_stored_memory_preference
  • Same for an agent_settings payload — test_agent_settings_launch_inherits_the_stored_memory_preference
  • Same for agent_profile_id (existing behaviour preserved) — test_profile_launch_inherits_the_stored_memory_preference (unchanged)
  • With the preference off, or with agent_context absent from stored settings, all three paths leave load_memory at Falsetest_profile_launch_leaves_memory_off_without_the_preference (unchanged), test_direct_agent_launch_leaves_memory_off_without_the_preference and test_agent_settings_launch_leaves_memory_off_without_the_preference
  • An agent that already sets load_memory=True itself is unaffected — test_agent_launch_preserves_context_when_load_memory_already_true
  • _resolve_agent_from_profile no longer takes a load_memory parameter — confirmed in the diff (signature, docstring, and body)
  • Existing tests in tests/agent_server/test_agent_profile_conv_start.py pass unchanged — confirmed, all 39 passed

Video/Screenshots

No video — this is a backend-only change with no UI. The script above is the functional evidence: it exercises the real settings store and a real MEMORY.md on disk rather than pytest mocks, and its output is included in How to Test section above.

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

Notes

  • User-facing: the global "load persistent memory" preference now applies to every conversation launch (agent, agent_settings, agent_profile_id), not only ones started from a named agent profile.

  • _with_load_memory operates on AgentBase generically, so it isn't kind-specific — the existing profile tests already cover the openhands/acp split, and since this fix's logic doesn't branch on agent kind, that split doesn't need re-testing for the new shapes.

  • load_skills_from_agent_server() also discards a caller-supplied AgentContext outright — noted in the issue as an optional companion change. Filing that separately rather than bundling it here, since it's an independent code path.

Copilot AI lite review requested due to automatic review settings August 21, 2026 02:47
@github-actions

Copy link
Copy Markdown
Contributor

📁 PR Artifacts Notice

This PR contains a .pr/ directory with temporary PR-specific documents. Because this is a fork PR, the directory will be automatically removed from main immediately after merge.

Copilot AI 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.

Pull request overview

Fixes propagation of the persisted load_memory preference across all conversation launch paths.

Changes:

  • Centralizes memory-preference application after agent resolution.
  • Removes the obsolete profile-resolution parameter.
  • Adds regression tests and real-store verification.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Review notes
tests/agent_server/test_agent_profile_conv_start.py Adds coverage for direct-agent and agent_settings launches.
openhands-agent-server/openhands/agent_server/conversation_service.py Nit (2 votes): maintainer evaluation and prompt-impact review are requested.
.pr/verify_load_memory_all_paths.py Critical (1 vote): verification can overwrite an existing settings.json; isolate or restore the settings store.
Suppressed comments (1)

openhands-agent-server/openhands/agent_server/conversation_service.py:1470

  • FileSettingsStore.load() performs synchronous file I/O and full settings validation, but this call now runs on the event loop for every concrete-agent launch (not just profile launches). A slow or large settings file can therefore block unrelated requests while conversations start; move the load to the worker thread, as the surrounding profile resolution already does.
        settings = get_settings_store().load() or PersistedSettings()

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .pr/verify_load_memory_all_paths.py Outdated
@all-hands-bot

all-hands-bot commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

🚦 CI is currently failing on this PR's latest commit.

Please fix the failing checks before OpenHands reviews it - this is re-checked automatically once you push a new commit. (A maintainer can also request @all-hands-bot as a reviewer to have it reviewed regardless of CI status.)

This is an automated check - no AI was used to generate this comment.

- Wrap the settings-store read in asyncio.to_thread so it no longer blocks the event loop on every launch, not just profile launches.
- .pr/verify_load_memory_all_paths.py now creates and owns its own temporary OH_PERSISTENCE_DIR instead of depending on the caller to isolate it, so running it can no longer overwrite a real settings.json.

Addresses Copilot review feedback on OpenHands#4566.
@all-hands-bot

Copy link
Copy Markdown
Collaborator

🚦 CI is currently failing on this PR's latest commit.

Please fix the failing checks before OpenHands reviews it - this is re-checked automatically once you push a new commit. (A maintainer can also request @all-hands-bot as a reviewer to have it reviewed regardless of CI status.)

This is an automated check - no AI was used to generate this comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Global agent_context.load_memory preference is ignored unless the conversation is launched from an agent profile

3 participants