-
Notifications
You must be signed in to change notification settings - Fork 343
proposal(environments): SupportsPersistence Protocol for multi-turn sessions #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal(environments): SupportsPersistence Protocol for multi-turn sessions #40
Conversation
Add persistent=True option to RLM that reuses the environment across completion() calls instead of creating/destroying for each call. This enables multi-turn conversations where variables and contexts persist. - Add persistent parameter to RLM constructor - Reuse environment when persistent=True, store as _persistent_env - Add close() method and context manager support (__enter__/__exit__) - Environment cleanup only on explicit close() when persistent
…sions Add context_count parameter to build_user_prompt() so the model knows when multiple contexts are available (context_0, context_1, etc.) during persistent REPL sessions.
Add validation to prevent AttributeError when persistent=True is used with environments that don't implement the required methods (update_handler_address, add_context, get_context_count). - Add _validate_persistent_environment_support() called at init time - Add _env_supports_persistence() for runtime capability checking - Add defensive runtime check before calling persistence methods - Raise clear ValueError if unsupported environment is configured
Store conversation histories as versioned variables (history_0, history_1, etc.) in the REPL environment, making them accessible for subsequent queries. This enables models to reference prior conversation context in persistent sessions.
|
@thoriqakbar0 Can you separate out one test file for testing local repl without persistence (and add an explicit test to show that it's not persistent, so you do 2 fake RLM calls so the env gets reset, but it tries to use a variable that existed before) and one for local_repl_with_persistence to check that persistence is working? Thanks! |
|
Also one more thing, let's update the abstract class to support "persistent: bool". For Docker, Modal, etc. add the flag, but if the user turns it on, throw an error that says "Persistent REPLs are currently not supported for environment: {env}". |
alexzhang13
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments above:
- Update test_local_repl.py to be no persistence, then add a new test file with persistent test cases.
- Update base env class, and add persistent flag to all. But for now in Docker, etc. throw an error and say not supported currently.
|
on itt |
Add persistent parameter to BaseEnv, IsolatedEnv, and NonIsolatedEnv. DockerREPL, ModalREPL, and PrimeREPL raise NotImplementedError when persistent=True since they don't yet support it. LocalREPL passes the parameter through to the base class. Also makes DockerREPL cleanup more defensive with hasattr checks.
…ulation tests Replace TestLocalREPLMultiContext and TestLocalREPLHistory with TestLocalREPLSimulatingRLMNoPersistence. New tests verify that environments reset between RLM completions when persistent=False.
Add TestLocalREPLMultiContext, TestLocalREPLHistory, and TestLocalREPLPersistentState test classes for LocalREPL's persistent mode features including multi-context versioning and message history storage.
Add comprehensive integration tests for persistent RLM sessions: - Environment reuse across completion calls - Context and history accumulation - Variable persistence between completions - Prompt awareness of contexts/histories - Resource cleanup on close - Validation of unsupported environments
Remove custom ScriptedMockLM class (58 lines) and replace with create_mock_lm() helper (14 lines) using standard Mock patterns.
Replace scattered hasattr checks with a runtime-checkable Protocol that defines the persistence capability contract. This provides type checker enforcement and IDE autocomplete support.
Document expected behavior to implement persistence: - Versioning behavior (context_0, context_1, ...) - Aliasing behavior (context -> context_0) - Method contracts with detailed docstrings - References to tests and example implementation
Updated PR scopeUpdated the title and description to better reflect what this PR actually delivers. Before: Focused on LocalREPL persistence implementation After: Focused on the Why the change?While implementing persistence for LocalREPL, I realized the main thing that I was trying to do is protocol pattern itself. it gives other environment authors (Docker, Modal, Cloudflare, Daytona, E2B, etc.) a clear path to add persistence:
The implementation for persistence already exists in most environments (Docker uses dill, Modal uses sandbox state). They just need to implement the 5 Protocol methods on top. would love feedback on this. tq! |
|
It looks good! Will merge after linting stuff, but also @thoriqakbar0 feel free to integrate persistence into the other REPLs (e.g. Docker, Modal, etc.) We will likely also just need to integrate the other sandboxes. I don't have any keys to test them though, which is why I haven't merged these PRs in yet. |
Align E2BREPL with other environments (DockerREPL, ModalREPL, PrimeREPL) by adding the persistent parameter introduced in PR alexzhang13#40. Raises NotImplementedError when persistent=True since E2BREPL doesn't yet implement the SupportsPersistence protocol. Co-Authored-By: Claude Opus 4.5 <[email protected]>
Summary
This PR introduces a
SupportsPersistenceProtocol that defines how environments can support multi-turn sessions. LocalREPL is provided as the reference implementation.The Problem
Every
completion()call spawns a fresh environment that gets destroyed afterward. Variables, computed results, loaded contexts — all gone.The Solution
A
SupportsPersistenceProtocol that any environment can implement:Usage
What's Included
SupportsPersistenceProtocol with comprehensive documentationcontext_0,context_1, ... (withcontextaliasingcontext_0)history_0,history_1, ... (withhistoryaliasinghistory_0)isinstance(env, SupportsPersistence)NotImplementedErrorwith guidanceFor Other Environments (Docker, Modal, , etc.)
The Protocol docstrings explain exactly how to implement persistence. See:
rlm/environments/base_env.py— Protocol definitionrlm/environments/local_repl.py— Reference implementationtests/test_local_repl_persistent.py— Expected behaviorTests
tests/test_local_repl.py— Non-persistent behavior (env resets between calls)tests/test_local_repl_persistent.py— Persistence unit teststests/test_multi_turn_integration.py— End-to-end multi-turn testsNot Included
acompletion()support