Scroll
Type: ../types/agent-memory-system-review.md · Tags: trace-learning
Scroll is the QwenPaw research fork accompanying Context as an Environment: Programmatic Context Management for Long-Horizon Agents, by Yin Lin, Elaine Ang, Erkang Zhu, Bolin Ding, and Jingren Zhou. It turns an agent's interaction trajectory into an external SQLite environment, moves completed history out of the live prompt under pressure, and gives the agent structured and sandboxed-Python interfaces for recovering or computing over that history. The reviewed source is the scroll-research branch of the niceIrene/QwenPaw fork.
Repository: https://github.com/niceIrene/QwenPaw
Reviewed revision: 3db60c5975187fc7c549e16573567a7cd21fd51f
Source directory: related-systems/niceIrene--QwenPaw
Last checked: 2026-08-27
Core Ideas
The durable record is a write-through interaction log, not a fact store. ScrollContextManager.on_save() serializes live user, assistant, tool-call, and tool-result blocks into history.db; HistoryStore stores their natural-language content and structured fields in conversation_history, maintains FTS5 over content, and deduplicates reloads by (session_id, dedup_key) (src/qwenpaw/agents/context/scroll/manager.py, src/qwenpaw/agents/context/scroll/history.py, src/qwenpaw/agents/context/scroll/serialize.py). The record is append-oriented rather than strictly append-only: an assistant row is updated while its message accumulates later tool calls or a headline, and the default 30-day retention policy deletes old rows on startup and teardown (src/qwenpaw/config/config.py, src/qwenpaw/agents/react_agent.py).
Context becomes a bounded working set over a recoverable environment. Above 80% of the model context by default, Scroll first persists the live window, folds eligible old tool results to recall pointers, keeps the complete active turn under normal pressure, evicts a completed middle, and retains a recent raw tail targeting 10% of context with a 40,000-token cap. If the rebuilt context still exceeds the effective hard limit, it may fold older active-turn tool results already included in a successful model request; the current user request, pending or unread results, and the five newest results remain verbatim (src/qwenpaw/config/config.py, src/qwenpaw/agents/context/scroll/manager.py). A persistence failure blocks eviction, and a still-unfit context raises an explicit error rather than silently dropping the active request.
Two derived views divide navigation from task continuity. Assistant responses are instructed to emit hidden retrieval headlines. Code binds valid headlines to stable seq addresses and folds evicted spans into a tiered index whose older blocks retain endpoint headlines and exact ranges. Separately, an extra model call updates a fixed-schema continuation summary from bounded archived evidence; local checks enforce headings, status values, source endpoints, secret rejection, duplicate rejection, and opaque-identifier grounding, with one repair attempt and fallback to the previous valid summary (src/qwenpaw/agents/context/scroll/prompt.py, src/qwenpaw/agents/context/scroll/eviction_index.py, src/qwenpaw/agents/context/scroll/continuation_summary.py). The summary is explicitly injected as background, not as a user instruction or source of truth.
Recall has a safe common path and a programmable ceiling. recall_history exposes bound, read-only expand, keyword/date search, recall_tool, and calendar operations with explicit pagination, snapshot-bound cursors, byte caps, and a per-turn loop guard. recall_history_python adds arbitrary joins, aggregation, and writable persistent scratch tables through a MemorySpace whose hist database is attached read-only; it runs only in the governed sandbox unless both deployment and agent configuration opt into unsafe execution (src/qwenpaw/agents/context/scroll/recall_tool.py, src/qwenpaw/agents/context/scroll/memoryspace.py, src/qwenpaw/agents/context/scroll/repl.py). This is an adoption advantage for local QwenPaw/CodeAct users, but the advanced path depends on a working platform sandbox.
Context efficiency uses bounded lexical defaults with a programmable escape hatch. The manager sets the index-detail character budget to the numeric value of 5% of model context size, clamped to 512–16,000 characters; older index blocks collapse by temporal distance, while exact content stays addressable by seq. The default structured search path uses FTS5/BM25 with a bounded LIKE fallback, returns ten results unless asked otherwise, expands results to complete user-bounded turns under row/byte/time limits, and excludes the current turn and recall tools' own traces to reduce echo loops (src/qwenpaw/agents/context/scroll/manager.py, src/qwenpaw/agents/context/scroll/memoryspace.py). Volume is strongly bounded; complexity is agent-controlled because Python recall can perform arbitrary multi-step analysis. This describes the supplied interfaces, not the distribution of recall operations in deployed use; retrieval precision, summary fidelity, and actual context dilution are not verified from code.
Artifact analysis
- Storage substrate:
sqlitefiles—history.dbholds canonical interaction rows and FTS state; workspace tool-result files hold complete oversized outputs independently of their database previews;.scroll/repl/scratch.dbholds agent-computed tables; session JSON checkpoints retain the eviction index, continuation summary, and manager bookkeeping; source files define the prompt, tools, validators, and compression policy. - Representational form:
natural-languagesymbolic— Raw text, tool-output previews and full-output files, headlines, continuation summaries, and recall observations are natural-language; SQLite schemas and rows, FTS postings, sequence ranges, tier/block structures, summary status/source records, tool schemas, cursors, retention settings, and sandbox rules are symbolic. Scroll retains no embeddings, adapters, or model weights. - Lineage:
authoredimportedtrace-extractedother-compiled— Prompts, tool contracts, compression code, schemas, and validation rules are authored; startup sync imports pre-Scroll session JSON; history rows, saved tool outputs, headlines, summaries, eviction maps, and scratch derivations come from interaction traces; FTS and checkpoint views are compiled from retained rows or manager state. Changes to source rows require FTS/update maintenance, and expiry of a summary's source endpoints invalidates that summary. - Behavioral authority:
knowledgeinstructionenforcementroutingvalidationrankinglearning— Raw turns, summaries, headlines, and scratch results act as knowledge artifacts; the Scroll prompt is a system-definition artifact that instructs headline and recall behavior; persistence-before-eviction, read-only attachment, sandbox gating, and hard-limit failure enforce boundaries; sequence maps, tool schemas, scopes, and cursors route access; summary checks validate candidates; BM25 and temporal/index structure rank or prioritize what is seen; trace-derived state supplies the learning surface for later context. Retention values and the dual unsafe-recall opt-in are separately consumed through a configuration-authority path, which the review matrix's controlled authority tokens do not encode.
Raw interaction rows and FTS. The raw stage is SQLite-backed natural-language plus symbolic message/tool metadata. Its lineage is automatic trace extraction or startup import, and its authority is primarily knowledge. The rows are canonical for structured event identity and for the representation actually persisted, but an oversized tool result may be present there only as a bounded preview. In that case a separately retained workspace file is the full evidential source until its independent artifact-retention window expires; recall uses the row's metadata to find or report that file. FTS is a rebuildable symbolic access structure with ranking authority (src/qwenpaw/agents/context/scroll/history.py, src/qwenpaw/agents/context/scroll/sync.py, src/qwenpaw/agents/middlewares.py, src/qwenpaw/agents/context/scroll/memoryspace.py, src/qwenpaw/config/config.py).
Headlines, eviction index, and continuation summary. The distilled stage is checkpointed in session files and rendered into a synthetic model-facing memory message. Headlines and summary text are natural-language; sequence spans, tiers, status, and source records are symbolic. All are trace-extracted. Their authority is knowledge and routing: the index points back to evidence, while the summary is advisory task state and explicitly cannot override the live request (src/qwenpaw/agents/context/scroll/manager.py, src/qwenpaw/agents/react_agent.py).
Persistent Python scratch. MemorySpace attaches history read-only and lets model-authored code create tables in a file-backed scratch SQLite database across calls. A scratch table may contain natural-language projections or symbolic aggregates; its lineage is trace-extracted when computed from history, and its authority remains agent-created working knowledge. No path automatically promotes it into trusted instruction (src/qwenpaw/agents/context/scroll/repl.py, src/qwenpaw/agents/context/scroll/memoryspace.py).
Prompt, tool, validation, and sandbox contracts. These authored natural-language and symbolic source artifacts are system-definition artifacts. They instruct when to recall and how to write headlines, route common vs programmable queries, validate summary shape and coarse provenance, deny history mutation, and prevent eviction when durable recovery is unavailable (src/qwenpaw/agents/context/scroll/prompt.py, src/qwenpaw/agents/context/init.py).
Promotion path. A live event becomes a structured history row, searchable text, and possibly a hidden headline; an oversized tool result also produces a separately retained full-output file before its row preview is truncated. Eviction can then compile retained rows into the tiered map and continuation summary, which re-enter later prompts. Agent code can materialize further scratch tables. The path promotes traces into increasingly compact knowledge and routing artifacts, but not into reviewed rules, validators, skills, policies, or model weights.
Comparison with Our System
Scroll and Commonplace share a useful separation: canonical evidence stays outside the immediate context, while smaller routing and summary artifacts help an agent decide what to read. Both prefer inspectable local state, explicit addresses, progressive disclosure, and failure modes that preserve source material rather than letting a derived summary silently become authority.
Their retained units and trust models differ. Scroll captures high-volume operational traces automatically and lets the agent compute over them in SQLite; its summary and index exist to resume one conversation efficiently. Commonplace retains selected, typed knowledge and system-definition artifacts in git, with collection contracts, authored links, citations, validation, and semantic review. At the architectural-capability level, Scroll provides sequence-addressed recovery of retained episode representations and ad hoc computation; Commonplace provides typed, source-visible claim history and controlled promotion into binding behavior. This is not comparative performance evidence, and Scroll's recovery coverage ends with the configured history and tool-artifact retention boundaries.
The sharpest tradeoff is promotion. Scroll deliberately keeps the continuation summary advisory and the raw log authoritative, but its summary validation is mostly structural and its default retention eventually removes the supporting rows. Commonplace spends more effort before a claim enters the library, then keeps that claim and its lineage reviewable rather than aging it out as session state.
Borrowable Ideas
Refuse compaction when recovery is not runnable. Commonplace should adopt this as a ready design constraint for any future context compactor: never replace loaded evidence with pointers until both persistence and the corresponding read path have succeeded.
Make absence, partial results, and continuation explicit in retrieval output. Scroll's snapshot-bound cursor, complete/incomplete markers, duplicate-page guard, and distinction between execution failure and an empty result are ready to borrow for Commonplace search or review bundles.
Keep a source-addressed continuation cache outside the library. A long-running Commonplace workflow could retain a compact active-task state whose items point back to snapshots or files and which is discarded when those sources expire. This needs a concrete multi-session operator use case and belongs in the workshop or operational store, not in kb/notes/.
Pair a read-only canonical store with writable analytical scratch. Attaching the Commonplace store read-only while giving an agent a disposable or explicitly retained scratch database could support bounded joins and aggregate analysis without granting mutation rights. It needs a real analysis workflow before implementation.
Do not borrow whole-span provenance as claim grounding. Scroll attaches the entire covered sequence range to each generated summary item. That is enough to prevent dangling provenance, but Commonplace claims should continue to cite the specific source passage or artifact that supports them.
Write side
Write agency: automatic — Scroll has two non-human write paths. The runtime manages write-through capture, startup import, FTS maintenance, headline capture, checkpointing, compression-time summary updates, and retention purges. Separately, the model can deliberately write scratch SQLite through MemorySpace, but it cannot mutate canonical history. Both fall under automatic in the contract's human-versus-system split, while their triggers and authority remain distinct; Scroll exposes no human memory-entry authoring or curation interface.
Curation operations: consolidate evolve decay — The continuation summary digests groups of retained turns, later evictions update that existing summary in light of new trace evidence, and startup and teardown delete history older than the configured retention window. The eviction index also collapses older blocks, but that is access-structure upkeep rather than another curation operation. Idempotency keys prevent duplicate writes, but this is not semantic dedup, and the summary is constrained to restate supported state rather than synthesize novel cross-memory claims (src/qwenpaw/agents/context/scroll/manager.py, src/qwenpaw/agents/context/scroll/eviction_index.py).
Trace-learning
Trace source: session-logs tool-traces — Scroll consumes user/model turns, model tool calls, tool results, runtime message tags, and restored session files. Recall calls are retained as traces but excluded from keyword search to prevent a self-retrieval loop.
Learning scope: per-project cross-task — history.db is workspace-local, while the default search scope is the same agent across all its sessions; explicit arguments can narrow to a session or widen to other agents in the workspace. The eviction index and continuation summary remain session-specific.
Learning timing: online staged — Turn capture, headline extraction, index updates, and continuation-summary updates occur online during the agent loop; startup import and retention maintenance are staged lifecycle work.
Distilled form: natural-language symbolic — Distillation produces natural-language headlines and task-state summaries plus symbolic SQLite rows, FTS state, sequence maps, tier structures, summary status/source records, and optional scratch tables.
Extraction. Initial capture is deterministic serialization. The main model produces each headline under a system-prompt contract; a separate LLM call produces or updates the continuation summary from bounded trace evidence. The oracle is local structural validation, source-endpoint existence, secret detection, duplicate checks, and opaque-identifier presence, with one repair attempt. There is no outcome score, external judge, or semantic entailment check.
Survey placement. Scroll extends the local trace-to-recall branch with an owned event log, online source-backed working-state distillation, and executable queries. It strengthens the survey claim that trace-derived memory can change later work without embeddings or weight updates. It also splits readable artifact learning into two authority levels: a retention-bounded continuation cache for task resumption versus a promoted library artifact meant to survive and govern across projects.
Read-back
Read-back: both — The agent pulls exact spans, searches, tool results, or custom computations through recall_history and recall_history_python; after compression, Scroll pushes the current session's eviction index and available continuation summary into a synthetic memory message before the live tail.
Read-back signal: coarse identifier — The pushed view always includes the retained map/summary after a compression rebuild, which is coarse recall, but the state is selected by the current session and agent identifiers. The push path does not infer relevance from the new prompt; lexical inference belongs to the pull search path.
Faithfulness tested: no — The fork contains a scroll=False configuration switch described as an ablation arm, but benchmark adapters and run artifacts live outside this source tree, reported results are not recomputed by CI, and the accompanying design post says detailed ablations remain future work (src/qwenpaw/config/codeact.py, README.md, website/public/blog/qwenpaw-scroll-executable-memory.en.md). The inspected code therefore does not show a with/without test proving that a fired summary, index entry, or recall result changed behavior.
The push injection point is context rebuilding before a model invocation. The manager renders the index and summary inside a <system-info> envelope carried by a synthetic user-role message, then appends a positional banner and the live tail. The static Scroll system prompt is baseline documentation, not memory read-back. Writes after a turn, FTS upkeep, summary updates, folding, and retention are write-side maintenance.
Selection is bounded but layered. The index shows recent milestones in more detail and collapses older blocks to endpoints or one global span; the summary is a compact current-state projection; the active turn and a recent tail stay verbatim under normal pressure, with the hard-limit exception for already-consumed older active-turn results described above; pull search uses lexical/date/session filters and returns explicit bounded pages; Python recall can perform arbitrarily complex joins but only printed, capped output returns. Effective precision, context dilution, and whether the model obeys the advisory summary are not verified from code.
At consumption, recalled raw turns are advisory evidence, the summary is background task state, and the index is a router. Authored prompt/tool contracts carry instruction and routing authority, while sandbox and read-only database rules carry enforcement authority. Humans can also inspect history.db, use /compact and /compact_str, or query the same structured interfaces, though SQLite and checkpoint JSON are less naturally reviewable than Commonplace's Markdown/git surface.
Curiosity Pass
The repository's headline description is stronger than the default implementation:
Scroll stores an agent's complete interaction history outside the model prompt in a persistent Session Environment. The model writes Python to search, materialize, and compute over that state; only explicitly printed projections enter its next working context. --- README.md
By default, rows older than 30 days are purged, oversized tool outputs may persist in history.db only as bounded previews while their full files have an independent retention period, structured recall returns tool observations without Python print, and the index/summary are pushed automatically. The implementation is better described as a retention-bounded, mostly complete interaction environment with several deliberate projections (src/qwenpaw/config/config.py, src/qwenpaw/agents/middlewares.py, src/qwenpaw/agents/context/scroll/recall_tool.py).
The "append-only Event Log" phrase is also logical rather than literal. Rows are deduplicated by stable identity, but an assistant row is updated as the turn grows, old rows are deleted by retention, and a corrupt database is quarantined before a fresh store is created. Those are sensible operational choices, but they matter for claims about auditability and immutability (README.md, src/qwenpaw/agents/context/scroll/history.py).
Summary provenance is coarse. Model-emitted source markers are stripped and every factual item receives the trusted full covered range; validation proves that range endpoints exist and that opaque identifiers occur somewhere in the evidence, not that each natural-language claim follows from its cited turn. The summary should therefore remain exactly what the code calls it: a state cache beneath raw-history authority (src/qwenpaw/agents/context/scroll/continuation_summary.py).
The pushed memory uses a user-role placeholder because some provider formats cannot insert a system message mid-context. The explicit archived-index seam and live-turn banner acknowledge the resulting authority ambiguity; this is careful prompt engineering around a transport constraint, not a hard guarantee that every model will respect the distinction (src/qwenpaw/agents/context/scroll/manager.py, src/qwenpaw/agents/context/scroll/eviction_index.py).
What to Watch
- Whether AgentZero becomes inspectable with the reported runs and true Scroll-on/Scroll-off ablations; that would change the faithfulness verdict from structural capability to behavioral evidence.
- Whether the README and paper-facing language explicitly incorporate default history and tool-artifact retention; that would align the trust claim with deployed behavior.
- Whether continuation-summary items gain exact per-claim sequence pointers or an entailment check; that would strengthen the summary from coarse source-backed state toward reviewable knowledge.
- Whether programmable recall remains sandboxed and portable across supported platforms; loss of the sandbox currently removes the advanced query path and can force fallback to structured recall or native context management.
- Whether a semantic retriever is added to the push or pull path; that would change context complexity and, if used for automatic injection, the read-back signal classification.
Relevant Notes:
- Knowledge storage does not imply contextual activation - distinguishes Scroll's retained log from pull recall and pushed index/summary context.
- Axes of artifact analysis - separates raw rows, FTS, headlines, summaries, scratch tables, and authored contracts by substrate, form, lineage, and authority.
- Trace-learning techniques in related systems - places Scroll in trace-to-recall and readable working-state distillation rather than trace-to-policy or weight learning.
- Context efficiency is the central design concern in agent systems - frames Scroll's bounded live tail, tiered index, summaries, result folding, and programmable recall.
- Knowledge artifact - classifies raw history, retrieved evidence, headlines, summaries, and scratch results when they advise later work.
- System-definition artifact - classifies Scroll's prompt, tool schemas, validation rules, sandbox policy, and compaction manager.
- Rule-based context selection needs a pre-existing signal - explains why Scroll's pushed state is coarse or session-identifier-scoped rather than content-inferred.
- A context-operation interface bounds the projections its policy can realize - is-evidence-for: Scroll combines a bounded automatic projection with structured and programmable pull interfaces over the same retained trace.