Skip to content

Comments

[v2] feat: Add TIAMAT persistent cloud memory backend#2528

Closed
toxfox69 wants to merge 3 commits intoopenai:mainfrom
toxfox69:tiamat-memory-v2
Closed

[v2] feat: Add TIAMAT persistent cloud memory backend#2528
toxfox69 wants to merge 3 commits intoopenai:mainfrom
toxfox69:tiamat-memory-v2

Conversation

@toxfox69
Copy link

Summary

TiamatSession — a persistent cloud memory backend for the OpenAI Agents SDK via TIAMAT Memory API. Zero-infrastructure, cross-session agent memory with FTS5 full-text search.

  • Implements SessionABC interface
  • Persistent conversation memory that survives process restarts
  • FTS5 full-text search across conversation history
  • Cross-device memory accessible via cloud API
  • Only requires httpx — no Redis, SQLite, or infrastructure setup

This is a v2 of #2525, addressing all review feedback:

Fix 1 (P1): pop_item deadlock

  • Before: pop_item() acquired self._lock, then called self.get_items() which tried to acquire the same asyncio.Lock — deadlock (non-reentrant lock).
  • After: Extracted _get_items_unlocked() helper. Both get_items() and pop_item() call this internal method — get_items() acquires the lock first, pop_item() calls it while already holding the lock.

Fix 2 (P1): clear_session marker not respected

  • Before: clear_session() stored a _tiamat_clear marker, but get_items() never filtered on it — old items returned after clear.
  • After: Two-pass parsing in _get_items_unlocked(): first pass finds latest _tiamat_clear sequence number, second pass filters to only return items after that clear point.

Fix 3 (P2): Hardcoded limit:100 truncating history

  • Before: session_limit or 100 silently capped at 100 entries when no limit was set.
  • After: session_limit if session_limit and session_limit > 0 else 10000 — generous default ceiling that respects explicit limits.

Files

  • examples/tiamat_memory/tiamat_session.py — Core session class (all fixes applied)
  • examples/tiamat_memory/agent_with_memory.py — Working example
  • examples/tiamat_memory/README.md — Documentation

Test Plan

  • pop_item completes without deadlock under concurrent access
  • get_items returns empty list after clear_session
  • Sessions without explicit limits return full history (>100 items)
  • Graceful fallback when API is unreachable

TIAMAT added 2 commits February 22, 2026 03:39
Adds a TiamatSession class that provides persistent, cloud-based
cross-session memory for OpenAI Agents via https://memory.tiamat.live.

Features:
- Zero-infrastructure persistent memory (no Redis/SQLite setup)
- FTS5 full-text search across conversation history
- Knowledge triples for structured memory
- Cross-device agent memory via cloud API
- Drop-in replacement for default session handling

Addresses openai#832 (mem0 integration request) and openai#2244 (context compaction)
by providing a lightweight, API-based memory solution with built-in
summarization support.

Includes:
- examples/tiamat_memory/tiamat_session.py - Core TiamatSession class
- examples/tiamat_memory/agent_with_memory.py - Usage example
- examples/tiamat_memory/README.md - Documentation
Addresses code review feedback:

- P1: pop_item() no longer calls get_items() while holding the lock.
  Extracted _get_items_unlocked() to avoid re-acquiring the non-reentrant
  asyncio.Lock, which would deadlock.

- P1: get_items() now respects clear_session markers. Parses all items
  in two passes: first finds the latest _tiamat_clear marker sequence,
  then filters to only return items stored after that clear point.

- P2: When no limit is requested (limit=None, session_settings.limit=None),
  fetch_limit now defaults to 10000 instead of hardcoded 100, ensuring
  full conversation history is retrievable.
@toxfox69
Copy link
Author

This is a resubmission of #2525 with all review feedback addressed. The three issues flagged by Codex (lock deadlock in pop_item, clear_session marker not respected, hardcoded limit cap) have all been fixed. Happy to address any additional feedback.

@github-actions github-actions bot added the documentation Improvements or additions to documentation label Feb 22, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: f194cbc2bc

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

Comment on lines 227 to 230
items = await self._get_items_unlocked(session_limit=None)
if not items:
return None
return items[-1]

Choose a reason for hiding this comment

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

P1 Badge Make pop_item remove the returned memory

pop_item currently reads the tail item and returns it, but it never persists any deletion/tombstone, so repeated calls return the same record forever. This violates the SessionABC.pop_item contract and can break retry cleanup paths that rely on destructive pops (for example rewind_session_items in src/agents/run_internal/session_persistence.py loops until items are removed), causing retries to stall when more than one item must be rewound.

Useful? React with 👍 / 👎.

await self._client.post(
"/api/memory/store",
json={
"content": json.dumps({"_tiamat_clear": True, "_tiamat_ts": time.time()}),

Choose a reason for hiding this comment

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

P1 Badge Write clear markers with sequence metadata

clear_session stores a marker without _tiamat_seq, but _get_items_unlocked computes last_clear_seq via item.get("_tiamat_seq", 0) and keeps all items with seq > last_clear_seq. In sessions with existing history, this means clear usually hides only sequence 0 and leaves most prior messages visible, so clear_session does not actually clear conversation state.

Useful? React with 👍 / 👎.

"""Get raw memories for this session."""
resp = await self._client.post(
"/api/memory/recall",
json={"query": self._make_tag(), "limit": 100},

Choose a reason for hiding this comment

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

P2 Badge Stop capping raw-memory fetch at 100 for sequencing

add_items derives the next _tiamat_seq from len(existing), but _get_raw_memories always recalls only 100 entries. After a session exceeds 100 memories, new writes reuse sequence numbers around 100, which breaks ordering assumptions in get_items/clear filtering/pop logic that depend on monotonically increasing _tiamat_seq values.

Useful? React with 👍 / 👎.

…ry limit

Addresses all 3 review comments from Codex bot:

1. pop_item now stores a tombstone marker (_tiamat_popped) before
   returning, so the item is excluded from future reads. This prevents
   infinite loops in rewind_session_items which calls pop_item
   repeatedly until items are removed.

2. clear_session now computes the next sequence number and includes
   _tiamat_seq in the clear marker. Previously the marker had no seq,
   defaulting to 0, which only hid seq-0 items.

3. Replaced _get_raw_memories (hardcoded limit:100) with
   _next_seq_unlocked that scans all memories (limit:10000) to find
   the true max sequence number. Prevents seq collisions after 100
   items.

Also refactored internal parsing into _fetch_active_items_unlocked
which handles clear markers, pop tombstones, and ordering in one pass.

Added test_tiamat_session.py with 8 tests covering:
- pop_item is destructive (key contract test)
- pop_item removes from tail one at a time
- clear_session hides all items regardless of seq
- sequence numbers work past 100 items
- no internal metadata leaks in returned items

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Author

@toxfox69 toxfox69 left a comment

Choose a reason for hiding this comment

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

Thanks for the thorough review — all three issues fixed in 26ec52b.

Fix 1 (P1): pop_item now destructive — stores a _tiamat_popped tombstone marker with the item's sequence number before returning. _fetch_active_items_unlocked() filters out items matching any pop tombstone, so rewind_session_items terminates correctly.

Fix 2 (P1): clear_session now includes _tiamat_seq — computes the next available sequence number via _next_seq_unlocked() and stores it on the clear marker. All items with seq < clear_seq are now properly filtered.

Fix 3 (P2): Removed hardcoded limit:100 — replaced _get_raw_memories() with _next_seq_unlocked() which scans all memories (limit:10000) to find the true max sequence number. Prevents seq collisions after 100 items.

Refactored: extracted _fetch_active_items_unlocked() which handles clear markers, pop tombstones, and ordering in one pass. Both _get_items_unlocked and pop_item use it.

Added 8 tests in test_tiamat_session.py using a mock HTTP transport — no network required. Key test: test_pop_item_is_destructive verifies two consecutive pops on a single-item session return the item then None.

@seratch
Copy link
Member

seratch commented Feb 23, 2026

@toxfox69 As I mentioned at #2525 (comment) , we won't have this example as part of this repo. Please have your own repo for it.

@seratch seratch closed this Feb 23, 2026
@openai openai locked and limited conversation to collaborators Feb 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants