Skip to content

Python: memory lines starting with backslash hash gain a backslash on every round trip #9727

Open

Description

Description

_escape_markdown_line prepends one backslash to any line starting with # or \#, but _unescape_markdown_line only strips a backslash when the body starts with exactly \#. Escaping a line that already starts with \# therefore produces a \\# prefix the reader never matches, and the added backslash is never removed.

The result is silent corruption on every round trip: a memory or summary line beginning with a single backslash hash gains one extra backslash each time the topic is persisted and reparsed, and the corruption compounds across the auto loaded topic files and consolidation passes that reread these files.

Reproduced on current main: _unescape_markdown_line(_escape_markdown_line("\\# literal fact")) returns "\\\\# literal fact", and a memory round tripped through MemoryTopicRecord.to_markdown and from_markdown comes back with the doubled prefix. A plain # prefixed line round trips correctly, which is why only the already escaped spelling is affected.

Expected Behavior

Escape and unescape must be inverses for every accepted input: a line starting with #, a line starting with \#, and longer backslash runs should all read back exactly as written.

Steps to Reproduce

  1. Write a topic record whose memory begins with \#.
  2. Read the record back from its markdown.

Minimal Reproduction

record = MemoryTopicRecord(topic="t", summary="s", memories=["\\# literal fact"], updated_at=...)
MemoryTopicRecord.from_markdown(record.to_markdown()).memories  # ["\\\\# literal fact"] on main

Package Versions

agent_framework core from main.

Python Version

3.11

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 26, 2026
  2. eavanvalkenburg commented on Nov 2, 2026

    @eavanvalkenburg
    Member

    /plan Joint persisted-memory fidelity/compatibility plan for distinct bugs #9727 (backslash/hash escape inverse) and #9725 (literal none-yet memory versus empty placeholder). Current main still corrupts accepted content, but lossless forward encoding and legacy-file interpretation are persisted-format decisions, not minor-ready filters. Reuse latest closed #9728/#9726 prototypes and review history as input; they remain closed pending issue agreement. In particular, the author reports header-only escape-marker detection fixed in c4a3e00 and literal-marker/provenance handling fixed in 4d0416d: verify those current candidates rather than repeat older review defects as unresolved. Choose one coordinated, unambiguous forward-format/provenance policy and retain exact legacy semantics without guessing information already lost. Treat marker-shaped summary/memory text as content, scope metadata detection to standalone header lines, and preserve distinct literal values. Test zero/one/many backslashes with indentation, legacy odd runs, empty/sole/mixed placeholder-valued memories, literal markers and both values together, repeated full write/read/auto-load/consolidation cycles. One shared plan covers both issues to avoid competing format migrations; do not reopen PRs or authorize new implementation yet. Retain each triage label, stay unassigned and do not mark ready until compatibility direction is agreed.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    pythonUsage: [Issues, PRs], Target: PythontriageUsage: [Issues], Target: All issues that still need to be triaged

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions