-
Notifications
You must be signed in to change notification settings - Fork 76
feat(api): add graph visualization API endpoints #26
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
Conversation
Add /graph/* API blueprint for memory visualization:
- /graph/snapshot: Return full graph with nodes, edges, and visual properties
- /graph/neighbors/{id}: Get graph and semantic neighbors for a node
- /graph/stats: Return graph statistics for dashboard
- /graph/types: Available memory types with colors
- /graph/relations: Available relationship types with colors
Visual properties include:
- Type-based colors for nodes
- Importance-based radius scaling
- Confidence-based opacity
- Relationship strength for edge thickness
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughA new graph visualization API blueprint is introduced and wired into the Flask application. The module provides five RESTful endpoints for querying and visualizing memory graphs: snapshot view with optional filtering and layout, neighbor traversal up to configurable depth with optional semantic augmentation from Qdrant, and endpoints returning graph statistics and metadata. Visual properties (colors, sizes, opacity) are computed from node types and importance values. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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.
Actionable comments posted: 2
🧹 Nitpick comments (3)
automem/api/graph.py (3)
8-18: Remove unused imports.Several imports are not used in this module:
json(line 8)defaultdictfrom collections (line 11)datetime,timezonefrom datetime (line 12)_serialize_nodefrom automem.utils.graph (line 18) — the function is passed as a parameter tocreate_graph_blueprint-import json -import logging +import logging import time -from collections import defaultdict -from datetime import datetime, timezone from typing import Any, Callable, Dict, List, Optional, Set from flask import Blueprint, abort, jsonify, request from automem.config import ALLOWED_RELATIONS, MEMORY_TYPES -from automem.utils.graph import _serialize_node
202-204: Uselogger.exceptionto capture stack traces.Per static analysis (TRY400), use
logger.exception()instead oflogger.error()to automatically include the stack trace for debugging.except Exception as e: - logger.error(f"graph/snapshot failed: {e}") + logger.exception("graph/snapshot failed: %s", e) abort(500, description=str(e))
450-452: Uselogger.exceptionto capture stack traces.Per static analysis (TRY400), use
logger.exception()for better debugging.except Exception as e: - logger.error(f"graph/stats failed: {e}") + logger.exception("graph/stats failed: %s", e) abort(500, description=str(e))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
app.py(2 hunks)automem/api/graph.py(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
automem/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
automem/**/*.py: Ensure graph writes always succeed even if vector storage fails by implementing graceful degradation in embedding and vector store operations
Normalize all timestamps to UTC ISO format for storage and retrieval
Implement graph operations as atomic transactions with automatic rollback on errors
Log vector store errors but do not block graph writes when vector storage fails
Files:
automem/api/graph.py
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Run 'black .' to format Python code before committing
Run 'flake8' to lint Python code for quality issues
**/*.py: Use type hints in Python code
Use 4-space indentation in Python code
Enforce maximum line length of 100 characters (Black configuration)
Format Python code with Black
Sort imports with Isort using profile=black
Lint Python code with Flake8
Use snake_case for module and function names in Python
Use PascalCase for class names in Python
Use UPPER_SNAKE_CASE for constant names in Python
Files:
automem/api/graph.pyapp.py
🧠 Learnings (1)
📚 Learning: 2025-12-09T02:15:22.291Z
Learnt from: CR
Repo: verygoodplugins/automem PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-09T02:15:22.291Z
Learning: Applies to automem/models/**/*.py : Use UUID for memory IDs and store in both graph (FalkorDB) and vector (Qdrant) databases for cross-referencing
Applied to files:
automem/api/graph.py
🧬 Code graph analysis (2)
automem/api/graph.py (3)
automem/utils/graph.py (1)
_serialize_node(8-20)app.py (2)
get_memory_graph(1383-1385)get_qdrant_client(1388-1390)tests/test_api_endpoints.py (1)
retrieve(195-204)
app.py (3)
automem/api/graph.py (1)
create_graph_blueprint(50-474)scripts/reembed_embeddings.py (1)
get_qdrant_client(64-71)automem/utils/graph.py (1)
_serialize_node(8-20)
🪛 Ruff (0.14.8)
automem/api/graph.py
202-202: Do not catch blind exception: Exception
(BLE001)
203-203: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
338-338: Do not catch blind exception: Exception
(BLE001)
415-415: Do not catch blind exception: Exception
(BLE001)
450-450: Do not catch blind exception: Exception
(BLE001)
451-451: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
🔇 Additional comments (7)
automem/api/graph.py (4)
22-47: LGTM!Color constants are well-organized with appropriate fallback defaults and follow naming conventions.
50-58: LGTM!The factory function follows a clean dependency injection pattern, making it testable. The parameter
logger: Anycould be more specific (e.g.,logging.Logger), butAnyis acceptable for flexibility.
295-339: Good graceful degradation for semantic search.The semantic neighbor search correctly handles failures by logging a warning and continuing without blocking the graph response. This aligns with the coding guidelines for vector storage operations.
454-472: LGTM!Simple configuration endpoints that return static data. Clean implementation with no error handling needed.
app.py (3)
3427-3427: LGTM!Import follows the established pattern for blueprint imports.
3523-3529: LGTM!Blueprint creation follows the established pattern with correct dependency injection.
3537-3537: LGTM!Blueprint registration completes the wiring of the new graph visualization API.
| limit = min(int(request.args.get("limit", 500)), 2000) | ||
| min_importance = float(request.args.get("min_importance", 0.0)) | ||
| types_filter = ( | ||
| request.args.get("types", "").split(",") if request.args.get("types") else None | ||
| ) | ||
| since = request.args.get("since") |
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.
Add input validation for query parameters.
Parsing limit and min_importance with int()/float() directly will raise a ValueError and return a 500 error if the user provides non-numeric values. Wrap these in try/except for user-friendly 400 errors.
- limit = min(int(request.args.get("limit", 500)), 2000)
- min_importance = float(request.args.get("min_importance", 0.0))
+ try:
+ limit = min(int(request.args.get("limit", 500)), 2000)
+ except (TypeError, ValueError):
+ limit = 500
+
+ try:
+ min_importance = float(request.args.get("min_importance", 0.0))
+ except (TypeError, ValueError):
+ min_importance = 0.0| depth = min(int(request.args.get("depth", 1)), 3) | ||
| include_semantic = request.args.get("include_semantic", "true").lower() == "true" | ||
| semantic_limit = min(int(request.args.get("semantic_limit", 5)), 20) |
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.
Add input validation for query parameters.
Same issue as /snapshot - non-numeric values will cause 500 errors instead of user-friendly 400 responses.
- depth = min(int(request.args.get("depth", 1)), 3)
- include_semantic = request.args.get("include_semantic", "true").lower() == "true"
- semantic_limit = min(int(request.args.get("semantic_limit", 5)), 20)
+ try:
+ depth = min(max(int(request.args.get("depth", 1)), 1), 3)
+ except (TypeError, ValueError):
+ depth = 1
+
+ include_semantic = request.args.get("include_semantic", "true").lower() == "true"
+
+ try:
+ semantic_limit = min(int(request.args.get("semantic_limit", 5)), 20)
+ except (TypeError, ValueError):
+ semantic_limit = 5📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| depth = min(int(request.args.get("depth", 1)), 3) | |
| include_semantic = request.args.get("include_semantic", "true").lower() == "true" | |
| semantic_limit = min(int(request.args.get("semantic_limit", 5)), 20) | |
| try: | |
| depth = min(max(int(request.args.get("depth", 1)), 1), 3) | |
| except (TypeError, ValueError): | |
| depth = 1 | |
| include_semantic = request.args.get("include_semantic", "true").lower() == "true" | |
| try: | |
| semantic_limit = min(int(request.args.get("semantic_limit", 5)), 20) | |
| except (TypeError, ValueError): | |
| semantic_limit = 5 |
🤖 Prompt for AI Agents
In automem/api/graph.py around lines 219 to 221, the request.args int
conversions for depth and semantic_limit and the boolean parsing for
include_semantic are not validated and will raise exceptions on non-numeric or
malformed inputs; wrap the parsing in validation logic that catches conversion
errors and range violations, returning a 400 Bad Request with a clear error
message for invalid values (e.g., non-integer depth/semantic_limit or
out-of-range values) and normalize boolean parsing safely (allow only
"true"/"false" or use a helper), ensuring default fallbacks remain but invalid
inputs produce user-friendly 400 responses instead of 500s.
🤖 I have created a release *beep* *boop* --- ## [0.10.0](v0.9.3...v0.10.0) (2026-02-06) ### Features * Add `exclude_tags` parameter to recall API ([#58](#58)) ([8aeca2e](8aeca2e)) * add memory content size governance with auto-summarization ([e24a86b](e24a86b)) * add memory content size governance with auto-summarization ([876aabf](876aabf)) * Add real-time observability with SSE streaming and TUI monitor ([54d2701](54d2701)) * Add real-time observability with SSE streaming and TUI monitor ([c5f6370](c5f6370)) * Add real-time observability with SSE streaming and TUI monitor ([944168e](944168e)) * **api:** add graph visualization API endpoints ([#26](#26)) ([a0d0dd3](a0d0dd3)) * **api:** add time-based sorting to recall API ([c063845](c063845)) * **api:** add time-based sorting to recall API ([a511f0c](a511f0c)) * create coderabbit.yml ([e05811f](e05811f)) * **embedding:** add Ollama embedding provider and expand docs ([#56](#56)) ([b506a90](b506a90)) * **mcp-sse:** agent-friendly recall output + tests ([71201d3](71201d3)) * **mcp-sse:** improve recall tool output and options ([97c4f72](97c4f72)) ### Bug Fixes * Add TTL cleanup to InMemoryEventStore ([0631af6](0631af6)) * Address CodeRabbit security and lint issues ([a701c57](a701c57)) * **backup:** Fix GitHub Actions backup failing with connection error ([19ed1e8](19ed1e8)) * **backup:** Fix GitHub Actions backup failing with connection error ([10b37d0](10b37d0)) * **consolidation:** prevent accidental forgetting ([4330c20](4330c20)) * **consolidation:** prevent accidental forgetting ([39dee3e](39dee3e)) * Correct token parameter for gpt-5 models (max_output_tokens) ([0786705](0786705)) * **enrichment:** sync tags/tag_prefixes to Qdrant ([3ccf874](3ccf874)) * **enrichment:** sync tags/tag_prefixes to Qdrant ([7ba9d76](7ba9d76)) * Handle streamable HTTP client disconnects ([f15a7ee](f15a7ee)) * **mcp-sse:** update test for SDK 1.20+ Accept header behavior ([597909e](597909e)) * **mcp:** close transport/server on sweep and update Accept header test ([ce7f6fa](ce7f6fa)) * **mcp:** replace broken res.on('close') with TTL sweep for Streamable HTTP sessions ([3d53263](3d53263)) * **mcp:** replace broken res.on('close') with TTL sweep for Streamable HTTP sessions ([#59](#59)) ([d4d3259](d4d3259)) * **mcp:** use Promise.resolve().catch() for async close() in session sweep ([a8cc589](a8cc589)) * Production bugs - datetime tz, OpenAI tokens, Qdrant race ([14491c4](14491c4)) * Production bugs - datetime tz, OpenAI tokens, Qdrant race ([0771360](0771360)) * Refactor tests to use double quotes for consistency ([21da453](21da453)) * Refine summarization token limit and improve tests ([6cab145](6cab145)) * Update test for POST /mcp Accept header error ([67a5a10](67a5a10)) * YAML indentation in backup workflow and update docs ([a606b3e](a606b3e)) ### Documentation * add mermaid diagrams for architecture visualization ([0d70a2a](0d70a2a)) * Add Qdrant setup guide and update docs for AUTOMEM_API_URL ([5c440aa](5c440aa)) * Add Qdrant setup guide and update docs for AUTOMEM_API_URL ([123ff28](123ff28)) * Enhance README.md with formatted NPM bridge link ([09ac4ac](09ac4ac)) * merge mermaid diagrams from docs/add-mermaid-diagrams ([4e9ae4f](4e9ae4f)) * Update API documentation and configuration settings ([9281149](9281149)) * Update API documentation and configuration settings ([#51](#51)) ([ad9500f](ad9500f)) * Update API endpoint count and project description ([9e71299](9e71299)) * update diagrams for Streamable HTTP transport ([1a2ce22](1a2ce22)) * Update docs to clarify MCP bridge and improve formatting ([af69a2f](af69a2f)) * Update MCP documentation and server implementation for Streamable HTTP support ([8fdef09](8fdef09)) * Update MCP documentation and server implementation for Streamable HTTP support ([335a78d](335a78d)) * update MCP_SSE.md to reflect MCP bridge terminology ([940a776](940a776)) * Update Railway deployment docs and improve README ([5480eb5](5480eb5)) * Update Railway deployment docs and improve README ([82c33b0](82c33b0)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Jack Arturo <info@verygoodplugins.com>
Summary
Add
/graph/*API blueprint for memory visualization:/graph/snapshot: Return full graph with nodes, edges, and visual properties/graph/neighbors/{id}: Get graph and semantic neighbors for a node/graph/stats: Return graph statistics for dashboard/graph/types: Available memory types with colors/graph/relations: Available relationship types with colorsVisual Properties
Testing
Test plan
🤖 Generated with Claude Code