Skip to content

Commit 1c27721

Browse files
ryaneggzclaude
andauthored
FROM feat/743-update-wiki-for-memories TO development (#744)
* feat: US-001 - Initialize wiki submodule and add Memories entries to sidebar Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: ryaneggz <kre8mymedia@gmail.com> * feat: US-002 - Write main Memories documentation page (API reference) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: ryaneggz <kre8mymedia@gmail.com> * feat: US-004 - Write Memories tutorial page (UI walkthrough with screenshots) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: ryaneggz <kre8mymedia@gmail.com> * feat: US-005 - Update llm.txt with memories documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: ryaneggz <kre8mymedia@gmail.com> * feat: US-003 - Capture full workflow screenshots with agent-browser Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: ryaneggz <kre8mymedia@gmail.com> * add task prd --------- Signed-off-by: ryaneggz <kre8mymedia@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d0e6a4a commit 1c27721

5 files changed

Lines changed: 269 additions & 138 deletions

File tree

.ralph/prd.json

Lines changed: 51 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,91 @@
11
{
22
"project": "Orchestra",
3-
"branchName": "feat/738-native-deepagents-memory",
4-
"description": "Native DeepAgents Memory - Standardize user memory injection using MemoryMiddleware pattern instead of ad-hoc string concatenation",
3+
"branchName": "feat/743-update-wiki-for-memories",
4+
"description": "Wiki Documentation for Memories Feature - Document the Memories feature with API reference, UI tutorial with screenshots, and llm.txt update",
55
"userStories": [
66
{
77
"id": "US-001",
8-
"title": "Add prepare_memory_files() helper to agents module",
9-
"description": "As a developer, I need a reusable async helper that fetches user memories and formats them as a file for the StateBackend, so all entry points can share the same memory loading logic.",
8+
"title": "Initialize wiki submodule and add Memories entries to sidebar",
9+
"description": "As a documentation reader, I want to find 'Memories' in the wiki navigation so I can learn about the feature.",
1010
"acceptanceCriteria": [
11-
"New async function prepare_memory_files(user_id, memory_svc) in backend/src/agents/__init__.py",
12-
"Imports create_file_data from deepagents.backends.utils",
13-
"Returns tuple[dict, list[str] | None] — a files_map entry and a memory sources list (or empty dict / None)",
14-
"Returns ({}, None) when user_id is falsy",
15-
"Returns ({}, None) when MemoryService.search() returns empty list",
16-
"Catches exceptions from MemoryService.search(), logs a warning, and returns ({}, None)",
17-
"Formats memories as markdown bullet list under path /memories.md using create_file_data()",
18-
"Typecheck passes (make format)"
11+
"Run 'git submodule update --init wiki' in the worktree to initialize the wiki submodule",
12+
"Add 'memories/index' to the 'Core Features' items array in wiki/sidebars.ts (after 'storage/index')",
13+
"Add 'memories/tutorial' to the 'Tutorials' items array in wiki/sidebars.ts",
14+
"Create empty placeholder files wiki/docs/memories/index.md and wiki/docs/memories/tutorial.md with basic frontmatter so the sidebar does not break",
15+
"Typecheck passes"
1916
],
2017
"priority": 1,
2118
"passes": true,
22-
"notes": "Read backend/src/agents/__init__.py for the existing add_memories_to_system() function and understand the current pattern. Import create_file_data from deepagents.backends.utils. Do NOT remove add_memories_to_system() — it stays for backward compatibility."
19+
"notes": "The wiki is a git submodule. In this worktree it is not yet initialized — run 'git submodule update --init wiki' first. Read wiki/sidebars.ts for the current structure. The existing sidebar has: Core Features [assistants/index, threads/index, storage/index] and Tutorials [tools/sandbox-tutorial]. Add memories/index to Core Features and memories/tutorial to Tutorials."
2320
},
2421
{
2522
"id": "US-002",
26-
"title": "Thread memory parameter through init_graph, Orchestra, and construct_agent",
27-
"description": "As a developer, I need the memory parameter plumbed through the agent construction chain so that create_deep_agent() receives it and activates MemoryMiddleware.",
23+
"title": "Write main Memories documentation page (API reference)",
24+
"description": "As a developer or API consumer, I want a reference page explaining how memories work and how to interact with them via the API so I can integrate memories into my workflow.",
2825
"acceptanceCriteria": [
29-
"init_graph() accepts memory: list[str] | None = None and passes it to create_deep_agent()",
30-
"Orchestra.__init__() accepts memory: list[str] | None = None and passes it to init_graph()",
31-
"construct_agent() accepts memory: list[str] | None = None and passes it to Orchestra()",
32-
"When memory=None, create_deep_agent() does not add MemoryMiddleware (existing behavior preserved)",
33-
"When memory=[\"/memories.md\"], MemoryMiddleware is added to the middleware stack",
34-
"Typecheck passes (make format)"
26+
"Create wiki/docs/memories/index.md with Docusaurus frontmatter: title 'Memories', slug '/memories', sidebar_position 4",
27+
"Include 'Overview' section explaining: memories are persistent per-user context stored via LangGraph BaseStore, namespaced by user ID, automatically injected into agent context as /memories.md",
28+
"Include 'How It Works' section describing the lifecycle: create memory -> stored in LangGraph BaseStore -> automatically retrieved via prepare_memory_files() -> injected as markdown into streaming/worker/invoke entry points",
29+
"Include 'API Reference' section with curl examples for all 5 endpoints: GET /api/memories (list with limit, offset, query params), GET /api/memories/{memory_id}, POST /api/memories (body: {content, metadata?}), PUT /api/memories/{memory_id} (body: {content, metadata?}), DELETE /api/memories/{memory_id}",
30+
"Each curl example uses localhost base URL and includes Authorization: Bearer <token> header",
31+
"Each curl example includes an example JSON response matching the backend schemas (Memory: {id, content, metadata, created_at, updated_at}, MemoryListResponse: {memories[], total, limit, offset})",
32+
"Include a 'Configuration via UI' section at the bottom linking to the tutorial page at ./tutorial",
33+
"Follow the same markdown structure as wiki/docs/assistants/index.md (heading hierarchy, bullet lists, code blocks)",
34+
"Typecheck passes"
3535
],
3636
"priority": 2,
3737
"passes": true,
38-
"notes": "Read backend/src/agents/__init__.py to find init_graph(), Orchestra class, and construct_agent(). The memory parameter on create_deep_agent() already exists in the DeepAgents library — you just need to pass it through. Check deepagents source or docs to confirm the parameter name."
38+
"notes": "Read wiki/docs/assistants/index.md and wiki/docs/storage/index.md from the main repo at /home/ryaneggz/ruska-ai/orchestra/wiki/ for the exact Docusaurus page pattern (frontmatter, heading style, admonitions). The API endpoints are defined in backend/src/routes/v0/memory.py. Schemas are in backend/src/schemas/entities/memory.py: Memory(id, content, metadata?, created_at?, updated_at?), MemoryCreate(content, metadata?), MemoryUpdate(content, metadata?), MemoryListResponse(memories, total, limit, offset). Query params for list: limit(default=10, max=100), offset(default=0), query(default=''). Auth uses Bearer token. Use localhost URLs since docs target local dev."
3939
},
4040
{
4141
"id": "US-003",
42-
"title": "Wire memory into streaming entry point (stream.py)",
43-
"description": "As an end user chatting via the streaming API, I want the agent to automatically recall my stored memories so responses are personalized without me needing to repeat context.",
42+
"title": "Capture full workflow screenshots with agent-browser",
43+
"description": "As a documentation author, I need screenshots of the memories workflow captured in light mode to include in the tutorial page.",
4444
"acceptanceCriteria": [
45-
"stream_generator() in backend/src/utils/stream.py calls prepare_memory_files() before creating ToolRuntime",
46-
"Memory files are merged into files_map with user-provided files taking precedence ({**memory_files, **files_map})",
47-
"memory_sources is passed to construct_agent() via the memory kwarg",
48-
"Agent works normally when no memories exist",
49-
"Typecheck passes (make format)"
45+
"Create directory wiki/static/img/memories/",
46+
"Use agent-browser skill to navigate to local dev environment Settings page",
47+
"Set browser to light mode",
48+
"Capture screenshot of Settings page showing the Memories section (empty state) and save as wiki/static/img/memories/settings-memories-empty.png",
49+
"Use agent-browser to click 'Add Memory' and fill in example content like 'I prefer Python for backend development and TypeScript for frontend. My timezone is America/Chicago.'",
50+
"Capture screenshot of the Add Memory dialog with content filled in and save as wiki/static/img/memories/settings-add-memory-dialog.png",
51+
"Save the memory, then capture screenshot of Settings page showing the created memory in the list and save as wiki/static/img/memories/settings-memories-list.png",
52+
"Navigate to chat, send a message that triggers memory recall (e.g., 'What programming languages do I prefer?'), and capture screenshot showing personalized response as wiki/static/img/memories/chat-memory-recall.png"
5053
],
5154
"priority": 3,
5255
"passes": true,
53-
"notes": "Read backend/src/utils/stream.py to find stream_generator(). Import prepare_memory_files locally to avoid circular imports. The user_id and memory service should be available from the request context."
56+
"notes": "The local dev environment must be running: 'make dev' for backend (port 8000) and 'cd frontend && npm run dev' for frontend (port 5173). The Settings page is at http://localhost:5173/settings. You must log in first. The agent-browser skill handles browser automation. Use light mode for all screenshots. The MemorySettings component is in frontend/src/components/settings/MemorySettings.tsx. The settings page is at frontend/src/pages/settings/index.tsx."
5457
},
5558
{
5659
"id": "US-004",
57-
"title": "Wire memory into worker entry point (tasks.py)",
58-
"description": "As an end user with scheduled or distributed agent tasks, I want those background agents to also have access to my memories for consistent personalized behavior.",
60+
"title": "Write Memories tutorial page (UI walkthrough with screenshots)",
61+
"description": "As a user, I want a step-by-step visual tutorial showing me how to add memories through the Settings page and see them working in chat.",
5962
"acceptanceCriteria": [
60-
"_execute_agent_stream() in backend/src/workers/tasks.py calls prepare_memory_files() before creating ToolRuntime",
61-
"Memory files are merged into files_map with user-provided files taking precedence",
62-
"memory_sources is passed to construct_agent() via the memory kwarg",
63-
"Typecheck passes (make format)"
63+
"Create wiki/docs/memories/tutorial.md with frontmatter: title 'Tutorial: Configuring Memories', sidebar_label 'Memory Tutorial', sidebar_position 1",
64+
"Step 1 'Navigate to Settings': describe how to reach the Settings page, include screenshot reference ![Settings Memories Empty](/img/memories/settings-memories-empty.png)",
65+
"Step 2 'Add a Memory': describe clicking Add Memory button, entering content, saving; include screenshot ![Add Memory Dialog](/img/memories/settings-add-memory-dialog.png)",
66+
"Step 3 'Verify Memory Created': describe seeing the memory in the list; include screenshot ![Memories List](/img/memories/settings-memories-list.png)",
67+
"Step 4 'Test in Chat': describe navigating to chat, sending a message, seeing personalized response; include screenshot ![Memory Recall](/img/memories/chat-memory-recall.png)",
68+
"Step 5 'Managing Memories': brief section describing edit (pencil icon) and delete (trash icon with confirmation dialog) actions",
69+
"Include a link back to the main Memories page: 'For API reference and programmatic access, see [Memories](/docs/memories)'",
70+
"Typecheck passes"
6471
],
6572
"priority": 4,
6673
"passes": true,
67-
"notes": "Read backend/src/workers/tasks.py to find _execute_agent_stream(). Follow same pattern as US-003 for stream.py."
74+
"notes": "Screenshots should already exist in wiki/static/img/memories/ from US-003. Reference them with Docusaurus-compatible image syntax: ![alt text](/img/memories/filename.png). Follow the same tutorial structure as wiki/docs/tools/sandbox-tutorial.md. The MemorySettings component has: search bar, Add Memory button, memory list with edit/delete icons, and MemoryEditDialog for create/edit. Delete shows an AlertDialog confirmation."
6875
},
6976
{
7077
"id": "US-005",
71-
"title": "Wire memory into direct invoke entry point (llm.py)",
72-
"description": "As an API consumer using the direct invoke endpoint, I want the agent to have access to my memories for personalized responses.",
78+
"title": "Update llm.txt with memories documentation",
79+
"description": "As an external AI agent or search engine, I need the public llm.txt to reflect the memories feature so LLM search engines provide accurate information about Orchestra.",
7380
"acceptanceCriteria": [
74-
"llm_invoke() in backend/src/controllers/llm.py calls prepare_memory_files() before init_backend()",
75-
"Memory files are merged into params.input.files with existing files taking precedence",
76-
"memory_sources is passed to construct_agent() via the memory kwarg",
77-
"Typecheck passes (make format)"
81+
"Read website/public/llm.txt to understand the current structure and style",
82+
"Add a 'Memories' subsection under '## Core Features' (after the existing Prompts or Tools section) with: one-line description of what memories are, that they persist per-user, that they are automatically injected into agent context during conversations, the 5 API endpoints (GET list, GET single, POST create, PUT update, DELETE), and that configuration is available via the Settings UI",
83+
"Keep the addition concise (5-10 lines) and consistent with the existing llm.txt bullet-point style",
84+
"Typecheck passes"
7885
],
7986
"priority": 5,
8087
"passes": true,
81-
"notes": "Read backend/src/controllers/llm.py to find llm_invoke(). Follow same pattern as US-003 and US-004."
82-
},
83-
{
84-
"id": "US-006",
85-
"title": "Add unit tests for prepare_memory_files()",
86-
"description": "As a developer, I need tests covering the new helper function to ensure correctness and prevent regressions.",
87-
"acceptanceCriteria": [
88-
"Test file at backend/tests/unit/agents/test_prepare_memory_files.py",
89-
"Test: returns ({}, None) when user_id is None",
90-
"Test: returns ({}, None) when user_id is empty string",
91-
"Test: returns ({}, None) when MemoryService.search() returns empty list",
92-
"Test: returns ({}, None) and logs warning when MemoryService.search() raises exception",
93-
"Test: returns correctly formatted files_map and [\"/memories.md\"] when memories exist",
94-
"Test: verifies markdown bullet format of memory content",
95-
"All tests pass (make test)"
96-
],
97-
"priority": 6,
98-
"passes": true,
99-
"notes": "Read existing test patterns in backend/tests/unit/ for conventions. Mock MemoryService.search() for all test cases. Use pytest and pytest-asyncio since prepare_memory_files is async."
100-
},
101-
{
102-
"id": "US-007",
103-
"title": "Update API documentation with memory behavior",
104-
"description": "As an API consumer, I want the documentation to describe that agents now automatically load user memories, so I understand the personalization behavior.",
105-
"acceptanceCriteria": [
106-
"Update docstrings in stream_generator(), _execute_agent_stream(), and llm_invoke() to mention memory loading",
107-
"Add a note to the construct_agent() docstring about the memory parameter",
108-
"Typecheck passes (make format)"
109-
],
110-
"priority": 7,
111-
"passes": true,
112-
"notes": "This is a documentation-only story. Read the functions modified in US-003, US-004, US-005 and add/update their docstrings. Keep docstrings concise."
113-
},
114-
{
115-
"id": "US-008",
116-
"title": "Use service_context.memory_service instead of singleton memory_service",
117-
"description": "As a developer, I need all three entry points to use the MemoryService instance from ServiceContext (backed by AsyncPostgresStore) instead of the module-level singleton (backed by InMemoryStore), so that memories persisted through the Settings UI are found at agent runtime.",
118-
"acceptanceCriteria": [
119-
"In stream_generator() (backend/src/utils/stream.py): replace memory_service singleton with service_context.memory_service when calling prepare_memory_files()",
120-
"In _execute_agent_stream() (backend/src/workers/tasks.py): replace memory_service singleton with service_context.memory_service when calling prepare_memory_files()",
121-
"In llm_invoke() (backend/src/controllers/llm.py): replace memory_service singleton with self.service_context.memory_service when calling prepare_memory_files()",
122-
"Remove the now-unnecessary 'from src.services.memory import memory_service' import from stream.py, tasks.py (inside _execute_agent_stream), and llm.py",
123-
"Remove the memory_svc.user_id = user_id mutation in prepare_memory_files() — ServiceContext already initialises MemoryService with the correct user_id",
124-
"Agent correctly retrieves memories that were created through the Settings UI",
125-
"Typecheck passes (make format)"
126-
],
127-
"priority": 8,
128-
"passes": true,
129-
"notes": "ServiceContext already creates self.memory_service = MemoryService(user_id=self.user_id, store=store) at backend/src/contexts/service.py:35 with the correct AsyncPostgresStore. The module-level singleton at backend/src/services/memory.py:31 defaults to get_store_in_memory() which returns InMemoryStore — this is why searches return empty. In stream.py, service_context is already a function parameter. In tasks.py, service_context is already a parameter. In llm.py, use self.service_context. The add_memories_to_system() function still uses the singleton — that is legacy and not part of this fix."
130-
},
131-
{
132-
"id": "US-009",
133-
"title": "Fix memory value parsing to use content key from MemoryRepo",
134-
"description": "As a developer, I need prepare_memory_files() to correctly extract memory text from the data structure used by MemoryRepo, so that memory content is properly formatted in the markdown file.",
135-
"acceptanceCriteria": [
136-
"In prepare_memory_files() (backend/src/agents/__init__.py): change value.get('memory', str(value)) to value.get('content', str(value)) to match MemoryRepo storage format",
137-
"Update existing unit tests in backend/tests/unit/agents/test_prepare_memory_files.py to use {'content': 'text'} instead of {'memory': 'text'} in mock SearchItem values",
138-
"Add a test case that uses the full MemoryRepo value structure: {'id': 'memory_xxx', 'content': '...', 'metadata': {}, 'created_at': '...', 'updated_at': '...'}",
139-
"Verify that bullet lines correctly extract the content field value",
140-
"All tests pass (make test)",
141-
"Typecheck passes (make format)"
142-
],
143-
"priority": 9,
144-
"passes": true,
145-
"notes": "MemoryRepo.create() stores Memory(id=..., content=..., metadata=..., created_at=..., updated_at=...) via BaseRepo._set() which calls value.model_dump(exclude_none=True, mode='json') — the resulting dict has a 'content' key, NOT a 'memory' key. SearchItem.dict() returns {'key': '...', 'value': {'id': '...', 'content': '...', ...}}. Existing tests mock SearchItem with MagicMock() whose .dict() returns {'key': '...', 'value': {'memory': 'text'}} — these need updating to {'key': '...', 'value': {'content': 'text'}}. The fallback str(value) for non-dict values should remain for safety."
88+
"notes": "Read website/public/llm.txt at /home/ryaneggz/ruska-ai/orchestra/website/public/llm.txt (or the worktree copy). The existing structure has ## Core Features with subsections like ### Projects, ### Assistants, ### Threads, ### Schedules, ### Prompts, ### Tools. Add ### Memories following the same pattern. Also check if there is a worktree copy at /home/ryaneggz/ruska-ai/orchestra/.worktrees/feat-743/website/public/llm.txt."
14689
}
14790
]
14891
}

0 commit comments

Comments
 (0)