* Add Azure OpenAI example with Neo4j
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Convert Azure OpenAI example to use uv
- Remove requirements.txt (uv uses pyproject.toml)
- Update README to use 'uv sync' and 'uv run'
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update Azure OpenAI example to use gpt-4.1
- Change default deployment from gpt-4 to gpt-4.1
- Update README recommendations to prioritize gpt-4.1 models
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove model recommendations from Azure OpenAI example
Model recommendations quickly become outdated.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add default Neo4j credentials to docker-compose
Set sensible defaults (neo4j/password) to prevent NEO4J_AUTH error
when .env file is not present.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update Azure OpenAI documentation to use v1 API
- Simplified Azure OpenAI setup using AsyncOpenAI with v1 endpoint
- Updated main README with clearer Quick Start example
- Removed outdated API version configuration
- Updated example deployment to gpt-5-mini
- Added note about v1 API endpoint format
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update LLMConfig to include both model and small_model
Both parameters are needed for proper LLM configuration.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Address PR review feedback
- Remove flawed validation check in azure_openai_neo4j.py
- Remove unused azure-identity dependency
- Update docstrings to reflect dual client support (AsyncAzureOpenAI and AsyncOpenAI)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Fix MCP server telemetry and update graphiti-core to v0.23.0
- Regenerate uv.lock in Docker builds to ensure posthog dependency is included
- Update graphiti-core version to 0.23.0 across all configurations
- Fix Python 3.11 compatibility for Pydantic TypedDict import
- Add FalkorDB Browser UI access information to startup logs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add typing-extensions as explicit dependency
Required for Python 3.11 compatibility with Pydantic 2.11.7,
which mandates typing_extensions.TypedDict on Python < 3.12.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use built-in TypedDict from typing module
Python 3.10+ includes TypedDict in the standard library.
Removed typing-extensions dependency as it's unnecessary.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Revert to typing_extensions.TypedDict for Pydantic compatibility
Pydantic requires typing_extensions.TypedDict on Python < 3.12.
Docker container uses Python 3.11, so this is necessary.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add Ruff linter rule to prevent typing.TypedDict usage
Adds banned-api configuration to both main and MCP server pyproject.toml
files to enforce typing_extensions.TypedDict usage, required for
Pydantic compatibility on Python < 3.12.
Also includes Ruff auto-formatting changes to quote styles.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Bump MCP server version to 1.0.1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Separate unit and integration tests to allow external contributors
This change addresses the issue where external contributor PRs fail unit
tests because GitHub secrets (API keys) are unavailable to external PRs
for security reasons.
Changes:
- Split GitHub Actions workflow into two jobs:
- unit-tests: Runs without API keys or database connections (all PRs)
- integration-tests: Runs only for internal contributors with API keys
- Renamed test_bge_reranker_client.py to test_bge_reranker_client_int.py
to follow naming convention for integration tests
- Unit tests now skip all tests requiring databases or API keys
- Integration tests properly separated into:
- Database integration tests (no API keys)
- API integration tests (requires OPENAI_API_KEY, etc.)
The unit-tests job now:
- Runs for all PRs (internal and external)
- Requires no GitHub secrets
- Disables all database drivers
- Excludes all integration test files
- Passes 93 tests successfully
The integration-tests job:
- Only runs for internal contributors (same repo PRs or pushes to main)
- Has access to GitHub secrets
- Tests database operations and API integrations
- Uses conditional: github.event.pull_request.head.repo.full_name == github.repository
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Separate database tests from API integration tests
Restructured the workflow into three distinct jobs:
1. unit-tests: Runs on all PRs, no external dependencies (93 tests)
- No API keys required
- No database connections required
- Fast execution
2. database-integration-tests: Runs on all PRs with databases (NEW)
- Requires Neo4j and FalkorDB services
- No API keys required
- Tests database operations without external API calls
- Includes: test_graphiti_mock.py, test_falkordb_driver.py,
and utils/maintenance tests
3. api-integration-tests: Runs only for internal contributors
- Requires API keys (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.)
- Conditional execution for same-repo PRs only
- Tests that make actual API calls to LLM providers
This ensures external contributor PRs can run both unit tests and
database integration tests successfully, while API integration tests
requiring secrets only run for internal contributors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Disable Kuzu in CI database integration tests
Kuzu requires downloading extensions from external URLs which fails in CI
environment due to network restrictions. Disable Kuzu for database and API
integration tests.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use pytest -k filter to skip Kuzu tests instead of DISABLE_KUZU
The original workflow used -k "neo4j" to filter tests. Kuzu requires
downloading FTS extensions from external URLs which fails in CI. Use
-k "neo4j or falkordb" to run tests against available databases while
skipping Kuzu parametrized tests.
This maintains the same test coverage as the original workflow while
properly separating unit, database, and API integration tests.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Upgrade Kuzu to v0.11.3+ to fix FTS extension download issue
Kuzu v0.11.3+ has FTS extension pre-installed, eliminating the need to
download it from external URLs. This fixes the "Could not establish
connection" error when trying to download libfts.kuzu_extension in CI.
Changes:
- Upgrade kuzu dependency from >=0.11.2 to >=0.11.3
- Remove pytest -k filters to run all database tests (Neo4j, FalkorDB, Kuzu)
- FTS extension is now available immediately without network calls
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Move pure unit tests from database integration to unit test job
The reviewer correctly identified that test_bulk_utils.py,
test_edge_operations.py, and test_node_operations.py are pure unit tests
using only mocks - they don't require database connections.
Changes:
- Removed tests/utils/maintenance/ from ignore list (too broad)
- Added specific ignore for test_temporal_operations_int.py (true integration test)
- Moved test_bulk_utils.py, test_edge_operations.py, test_node_operations.py to unit tests
- Kept test_graphiti_mock.py in database integration (uses real graph_driver fixture)
This reduces database integration test time and properly categorizes tests.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Skip flaky LLM-based tests in test_temporal_operations_int.py
- test_get_edge_contradictions_multiple_existing
- test_invalidate_edges_partial_update
These tests rely on OpenAI LLM responses for edge contradiction detection and produce non-deterministic results.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use pytest -k filter for API integration tests
Replace explicit file listing with `pytest tests/ -k "_int"` to automatically discover all integration tests in any subdirectory. This improves maintainability by eliminating the need to manually update the workflow when adding new integration test files.
Excludes:
- tests/driver/ (runs separately in database-integration-tests)
- tests/test_graphiti_mock.py (runs separately in database-integration-tests)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Rename workflow from "Unit Tests" to "Tests"
The workflow now runs multiple test types (unit, database integration, and API integration), so "Tests" is a more accurate name.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add OpenTelemetry distributed tracing support
- Add tracer abstraction with no-op and OpenTelemetry implementations
- Instrument add_episode and add_episode_bulk with tracing spans
- Instrument LLM client with cache-aware tracing
- Add configurable span name prefix support
- Refactor add_episode methods to improve code quality
- Add OTEL_TRACING.md documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix linting errors in tracing implementation
- Remove unused episodes_by_uuid variable
- Fix tracer type annotations for context manager support
- Replace isinstance tuple with union syntax
- Use contextlib.suppress for exception handling
- Fix import ordering and use AbstractContextManager
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Address PR review feedback on tracing implementation
Critical fixes:
- Remove flawed error span creation in graphiti.py that created orphaned spans
- Restructure LLM client tracing to create span once at start, eliminating code duplication
- Initialize LLM client tracer to NoOpTracer by default to fix type checking
Enhancements:
- Add comprehensive span attributes to add_episode: reference_time, entity/edge type counts, previous episodes count, invalidated edge count, community count
- Optimize isinstance check for better performance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add prompt name tracking to OpenTelemetry tracing spans
Add prompt_name parameter to all LLM client generate_response() methods
and set it as a span attribute in the llm.generate span. This enables
better observability by identifying which prompt template was used for
each LLM call.
Changes:
- Add prompt_name parameter to LLMClient.generate_response() base method
- Add prompt_name parameter and tracing to OpenAIBaseClient,
AnthropicClient, GeminiClient, and OpenAIGenericClient
- Update all 14 LLM call sites across maintenance operations to include
prompt_name:
- edge_operations.py: 4 calls
- node_operations.py: 6 calls (note: 7 listed but only 6 unique)
- temporal_operations.py: 2 calls
- community_operations.py: 2 calls
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix exception handling in add_episode to record errors in OpenTelemetry span
Moved try-except block inside the OpenTelemetry span context and added
proper error recording with span.set_status() and span.record_exception().
This ensures exceptions are captured in the distributed trace, matching
the pattern used in add_episode_bulk.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Refactor prompt structure: move MESSAGES after instructions
Reordered prompt structure in extract_nodes.py to place MESSAGES section
after instructions/guidelines in both extract_attributes and extract_summary
functions for improved prompt clarity.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add sentence-aware text truncator for entity summaries
- Created truncate_at_sentence() utility function that truncates text at
sentence boundaries while respecting max character limits
- Added MAX_SUMMARY_CHARS constant (250 chars) for entity summaries
- Applied truncator to entity summaries in prompts (extract_nodes.py)
- Applied truncator to LLM-generated summaries (node_operations.py)
- Added comprehensive test suite for truncation logic
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Clean up formatting in extract_attributes prompt
- Remove extra blank lines
- Fix indentation of MESSAGES tag
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Bump version to 0.22.0pre3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Refactor summary prompts to use character limit and prevent meta-commentary
- Changed summary length constraint from "8 sentences" to "250 characters" for more predictable output
- Created reusable summary_instructions snippet in snippets.py with clear BAD/GOOD examples
- Added explicit instruction to output only factual content without meta-commentary
- Applied consistent formatting across extract_nodes.py and summarize_nodes.py
- Bumped version to 0.22.0pre2
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add copyright header to snippets.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Enforce shorter summaries with 8 sentence limit
Replace 250-word limit with 8 sentence limit for node summaries to improve conciseness. Also update prompt system message for summarize_context to better reflect its dual purpose of generating summaries and attributes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update graphiti_core/prompts/summarize_nodes.py
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
* Bump version to 0.22.0pre1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update graphiti_core/prompts/summarize_nodes.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
* Refactor node extraction for better maintainability
- Extract helper functions from extract_attributes_from_node to improve code organization
- Add _extract_entity_attributes, _extract_entity_summary, and _build_episode_context helpers
- Apply consistent formatting (double quotes per ruff configuration)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Apply consistent single quote style throughout node_operations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* cleanup
* cleanup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Bump version to 0.22.0pre0
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* chore: Update dependencies and enhance edge resolution logic
- Add new dependencies: boto3, opensearch-py, and langchain-aws to pyproject.toml.
- Modify Graphiti class to handle additional parameters in edge resolution.
- Improve edge type handling in deduplication logic by introducing custom edge type names.
- Enhance tests for edge resolution to cover new scenarios and ensure correct behavior.
This update improves the flexibility and functionality of edge operations while ensuring compatibility with new libraries.
* refactor: Clean up test_edge_operations.py and format response returns
- Remove unnecessary stubs for opensearchpy module.
- Format return values in llm_client.generate_response for consistency.
- Enhance readability by ensuring proper indentation and structure in test cases.
This refactor improves the clarity and maintainability of the test suite for edge operations.
* bump version to 0.30.0pre5 and enhance docstring for resolve_extracted_edge function
- Update version in pyproject.toml to 0.30.0pre5.
- Add detailed docstring to resolve_extracted_edge function in edge_operations.py, clarifying parameters and return values.
This update improves documentation clarity for the edge resolution process.
* fix: Add edge type validation based on node labels
- Add DEFAULT_EDGE_NAME constant for 'RELATES_TO'
- Implement pre-resolution validation to reset invalid edge names
- Add post-resolution validation for LLM-returned fact types
- Rename parameter from edge_types to edge_type_candidates for clarity
- Add comprehensive tests for validation scenarios
This ensures edges conform to edge_type_map constraints and prevents
misclassification when edge types don't match node label pairs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: Bump version to 0.30.0pre4
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* gpt-5-mini and gpt-5-nano default
* bump version
* remove unused imports
* linter
* update
* disable neptune errors while we get a fixture in place
* update pyright
* revert non-structured completions
* fix typo