951 Commits

Author SHA1 Message Date
Yatharth Anand 993e081a6d fix(attributes): preserve prior node attributes when no entity type applies
`extract_attributes_from_nodes` assigns `node.attributes = attributes`
unconditionally, and `_extract_entity_attributes` returned a bare `{}` whenever
no entity type applied to the node. Because a deduplicated node is the node
hydrated from the database (`_promote_resolved_node` returns the existing
candidate, and `get_entity_node_from_record` populates `attributes`), and the
entity save queries replace attributes wholesale, that `{}` silently cleared
attributes a previous typed pass had stored.

Two paths reach it:

- `entity_types=None` on a later episode for a node whose attributes were
  written by an earlier call that did pass `entity_types`.
- `entity_types` supplied but missing the node's label, since
  `entity_types.get(...)` then resolves to None. A node whose only label is
  `Entity` resolves the lookup key to `''` and takes the same path.

The typed path already preserves prior values via
`apply_capped_attributes(..., merge_mode='overlay')`; only the
no-applicable-type early return bypassed it. Returning the node's prior
attributes makes the documented contract at the call site ("returns the
already-merged attribute dict, so direct assignment is the merge") true on both
paths, so no call-site guard is needed.

This matches the invariant `add_triplet` already enforces ("Update attributes
dictionary (merge rather than replace)"), covered by
`test_add_triplet_empty_attributes_preserved`. That test depends on the
`graph_driver` fixture, which parametrizes to zero drivers when all backends are
disabled, so it does not run in the default unit-test CI job. The two tests added
here need no database and do run there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ax326xYkRzfFiZZu9n3Fjz
2026-08-20 18:52:19 -07:00
mehulp93 502054ac3c Remove Claude PR triage workflow (#1788)
Remove Claude PR triage workflow to close pull_request_target prompt-injection risk.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-20 13:39:38 -07:00
zep-cla-assistant[bot] c406932767 @Ftgn-dpA has signed the CLA in getzep/graphiti#1786 2026-08-20 10:37:44 +00:00
zep-cla-assistant[bot] 10374d6044 @crajah has signed the CLA in getzep/graphiti#1777 2026-08-18 13:27:29 +00:00
zep-cla-assistant[bot] 96ef997b26 @fabiosiqueira has signed the CLA in getzep/graphiti#1773 2026-08-16 17:36:42 +00:00
zep-cla-assistant[bot] a3596b8bc1 @Deepnar has signed the CLA in getzep/graphiti#1772 2026-08-16 12:51:09 +00:00
zep-cla-assistant[bot] 203b792af4 @connectsudhindra-gif has signed the CLA in getzep/graphiti#1770 2026-08-15 17:52:10 +00:00
zep-cla-assistant[bot] b2ff2eadd9 @noamsiegel has signed the CLA in getzep/graphiti#1765 2026-08-13 21:59:46 +00:00
zep-cla-assistant[bot] 09c7e2c6ef @openbiocure has signed the CLA in getzep/graphiti#1766 2026-08-13 20:34:06 +00:00
zep-cla-assistant[bot] 8cfcbe811a @yatharth-anand-2410 has signed the CLA in getzep/graphiti#1764 2026-08-13 16:35:21 +00:00
zep-cla-assistant[bot] b48a9fdd03 @icn5381 has signed the CLA in getzep/graphiti#1761 2026-08-13 06:36:07 +00:00
mehulp93 d40da88f20 fix edge cross-encoder shortlist via balanced merge (#1642) (#1754)
* fix edge cross-encoder shortlist via balanced merge (#1642)

Round-robin merge retrieval result sets before CE ranking so BM25 insertion order cannot crowd out cosine/BFS candidates.

Co-authored-by: Cursor <cursoragent@cursor.com>

* use RRF with 2x limit for edge cross-encoder shortlist (#1642)

Replace balanced_merge with RRF fusion and a 2*limit CE candidate cap so multi-method hits reach ranking without unbounded cost.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 13:16:14 -07:00
mehulp93 401c59a65b feat: add source_node_uuid, target_node_uuid, and episodes to FactResult model and edge processing (#1750) 2026-08-10 14:03:54 -07:00
zep-cla-assistant[bot] cf1954bd7a @mehulp93 has signed the CLA in getzep/graphiti#1750 2026-08-10 21:00:22 +00:00
zep-cla-assistant[bot] f17526d93e @uuzzrm has signed the CLA in getzep/graphiti#1749 2026-08-10 18:27:42 +00:00
zep-cla-assistant[bot] 425bf2481b @Sicatho has signed the CLA in getzep/graphiti#1733 2026-08-05 07:38:12 +00:00
zep-cla-assistant[bot] aab852df94 @brentkearney has signed the CLA in getzep/graphiti#1726 2026-08-03 21:49:32 +00:00
zep-cla-assistant[bot] 899cb40d04 @adnanbasil10 has signed the CLA in getzep/graphiti#1719 2026-08-03 11:44:40 +00:00
zep-cla-assistant[bot] f9bd84e956 @zrh805 has signed the CLA in getzep/graphiti#1715 2026-08-03 08:14:11 +00:00
zep-cla-assistant[bot] 85c16a25f5 @Anai-Guo has signed the CLA in getzep/graphiti#1713 2026-08-03 07:14:46 +00:00
zep-cla-assistant[bot] 7cf0cab4b4 @trevor-sykes has signed the CLA in getzep/graphiti#1711 2026-08-01 18:57:42 +00:00
Jack Ryan 4f62cfe7a2 docs: remove Discord mentions, use GitHub for discussion (#1708)
docs: remove Discord mentions and point community to GitHub

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 19:41:36 -04:00
zep-cla-assistant[bot] 2645dee20f @d3f4w2 has signed the CLA in getzep/graphiti#1703 2026-07-30 08:24:29 +00:00
zep-cla-assistant[bot] 71a719be48 @ozdemirsarman has signed the CLA in getzep/graphiti#1699 2026-07-29 08:55:49 +00:00
zep-cla-assistant[bot] 00b0130bab @jatinder14 has signed the CLA in getzep/graphiti#1691
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Lint with Ruff / ruff (push) Has been cancelled
MCP Server Tests / live-mcp-tests (push) Has been cancelled
Server Tests / live-server-tests (push) Has been cancelled
Socket Firewall Wrapper Check / connectivity (push) Has been cancelled
Socket Firewall Wrapper Check / docker-guard (push) Has been cancelled
Pyright Type Check / pyright (push) Has been cancelled
Tests / unit-tests (push) Has been cancelled
Tests / database-integration-tests (push) Has been cancelled
2026-07-28 02:47:36 +00:00
Preston Rasmussen 021d3a57d5 Bump graphiti-core to 0.29.3 (#1696)
Release to PyPI / release (push) Has been cancelled
bump graphiti-core patch version
v0.29.3
2026-07-27 16:55:45 -04:00
Preston Rasmussen d9a2db9dd2 Consolidate overlapping backend fixes (#1695)
consolidate overlapping backend fixes
2026-07-27 15:16:32 -04:00
Cloud b0ec6d9303 fix: preserve relationship direction in get_by_node_uuid and BFS edge search (#1663)
* fix: preserve relationship direction in get_by_node_uuid and BFS edge search

Switch get_entity_edge_return_query to use startNode(e)/endNode(e) for
NEO4J/FALKORDB/NEPTUNE so source/target reflect the stored relationship
direction regardless of MATCH directionality. Fixes direction reversal
in EntityEdge.get_by_node_uuid and edge_bfs_search when the queried
node is the relationship target.

KUZU is unchanged: its 'e' is a RelatesToNode_ intermediate node, not
a relationship, and its MATCH is already directed.

Adds unit tests for the return-query builder and a regression assertion
in test_entity_edge for the target-side get_by_node_uuid case.

Fixes #1662

* update BFS query shape expectation

---------

Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
Co-authored-by: prestonrasmussen <prasmuss15@gmail.com>
2026-07-27 13:12:47 -04:00
Pavlo Paliychuk c926fbacdb Add Socket Firewall enforcement to CI and releases (#1681)
* add Socket Firewall enforcement to CI

Route dependency installs and official image builds through Socket while preserving fork PR and public Docker fallbacks.

Co-authored-by: Cursor <cursoragent@cursor.com>

* bypass build caches when Socket Firewall is enforced

sfw can only inspect packages that are actually downloaded, so a release
image could ship a package flagged after its layer was first built. Two
caches hid dependencies from enforced builds: the BuildKit layer cache
skipped the install step outright, and the uv cache mount let uv resolve
wheels from disk without contacting PyPI even when the step did run.

Enforced builds now set a per-run SOCKET_SCAN_ID to invalidate the install
layer and export UV_NO_CACHE=1. Community builds leave SOCKET_SCAN_ID empty
and keep both caches.

The connectivity smoke test compares a stamp written inside the install
layer rather than grepping the build log, since BuildKit echoes instruction
text for CACHED steps too, and asserts an unchanged scan id still hits the
cache so the check cannot pass vacuously.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 13:02:08 -04:00
kramerica-inc-dev 245320997d fix(search): consume bfs relationship hits directly in edge_bfs_search (#1653)
Completes #1500 on the generic edge_bfs_search path in search_utils.py,
which is what executes today for FalkorDB and Neo4j: driver.search_interface
is never assigned, so the driver-level operations modules #1500 patches are
not reached at runtime.

Mirrors the exact transform #1500 applies to the FalkorDB driver copy of
this query: replace the per-row re-MATCH by uuid
(MATCH (n:Entity)-[e:RELATES_TO {uuid: rel.uuid}]-(m:Entity)) with a direct
WITH over the relationship already produced by UNWIND relationships(path),
deriving endpoints via startNode/endNode. The explicit
type(e) = 'RELATES_TO' guard is required because the BFS pattern traverses
RELATES_TO|MENTIONS and the old re-MATCH filtered MENTIONS out implicitly.

As a side effect this also removes the duplicated/swapped source-target rows
on this path (the old undirected re-MATCH matched each edge twice; see #789
and PR #1436): startNode/endNode yields one row per relationship in its
original orientation. #789 also flags get_embeddings_for_edges, which is out
of scope here.

Refs #1272, #1500. Related to #789, #1436.

Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-27 12:55:44 -04:00
ly-wang19 a96309bf0c fix(edges): return reference_time in entity edge read query (#1605)
EntityEdge.save() persists reference_time on every provider and the record
parsers read it from the top-level record, but get_entity_edge_return_query()
never aliased `e.reference_time AS reference_time`. The field was therefore
silently dropped on every read-back (get_by_uuid/get_by_uuids/get_between_nodes/
get_by_node_uuid/get_by_group_ids), so a saved reference_time always came back
None. Add the alias to both query branches, matching the existing
expired_at/valid_at/invalid_at aliases.

Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-27 12:53:23 -04:00
小妍儿 ✨ 94e0d7830a fix(mcp): expose generic structured output mode (#1619)
Co-authored-by: 千乘妍 (Xiaoyaner) <xiaoyaner0201@users.noreply.github.com>
Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-27 12:47:57 -04:00
Saltasm 784782c085 fix(communities): scope remove_communities to the group_ids being rebuilt (#1658)
build_communities(group_ids=[...]) documents 'Create communities only for
the listed group_ids', but its clear step called remove_communities with no
group filter — deleting EVERY Community node in the database before
recreating only the selected groups. A scoped rebuild therefore silently
destroyed all other groups' communities.

Thread group_ids through remove_communities and all four driver
implementations (neo4j, falkordb, kuzu, neptune) plus the
GraphOperationsInterface signature: scoped DETACH DELETE with
WHERE c.group_id IN $group_ids when group_ids is provided, unchanged
full wipe when it is not (blank/None keeps the documented
whole-graph behavior).

Fixes #1657

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-27 12:32:55 -04:00
Madan kumar 3d7b3686b9 fix(mcp): configure cross-encoder from providers instead of hardcoded OpenAI (#1637)
* fix(mcp): configure cross-encoder from providers instead of hardcoded OpenAI

The MCP server never passed a cross_encoder to Graphiti(), so it fell back to OpenAIRerankerClient and required OPENAI_API_KEY even on fully non-OpenAI setups.

Add a CrossEncoderFactory that picks a reranker from the LLM provider, then the embedder provider, and falls back to the local BGE reranker, and wire it into both Graphiti() construction sites.

Fixes #1393

* fix(mcp): fail when local reranker is unavailable

---------

Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-27 12:27:12 -04:00
zep-cla-assistant[bot] 3966b1af14 @RitwijParmar has signed the CLA in getzep/graphiti#1519 2026-07-27 16:02:21 +00:00
zep-cla-assistant[bot] 20ce7d27b2 @prasmussen15 has signed the CLA in getzep/graphiti#1619 2026-07-27 15:59:48 +00:00
Nandana Dileep abc0017526 fix: capture init task ref + cancel on close for Neo4jDriver and FalkorDriver (#1636)
* fix: capture init task ref + cancel on close for Neo4jDriver and FalkorDriver

Both Neo4jDriver and FalkorDriver __init__ scheduled
build_indices_and_constraints() via loop.create_task() without
capturing the task reference. The orphan task could:

1. Race with explicit build_indices_and_constraints() calls
2. Produce 'Task exception was never retrieved' warnings on failure
3. Leave the connection in a mid-transaction state when the driver
   is closed concurrently

Now captures the task in self._init_task and cancels it in close(),
with suppress(CancelledError) to handle the cancellation cleanly.

Closes #1513

* fix: retrieve exception from already-done init tasks in close()

Previously, close() only cancelled and awaited tasks that were
still running, but skipped already-done tasks. If a done task
failed with an exception, the exception was never retrieved,
causing 'Task exception was never retrieved' warnings.

Now calls task.exception() on done tasks to consume any pending
exception and complete the task's lifecycle.

* fix: guard exception() against cancelled init tasks in close()

Task.exception() raises CancelledError if the task finished in a
cancelled state. If the init task was cancelled externally before
close() ran, the else branch would re-raise CancelledError out of
close(), breaking driver cleanup.

Skip exception retrieval for cancelled tasks; only call exception()
on tasks that completed normally or failed.

---------

Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-27 11:50:24 -04:00
Husni Adil Makmur fd2832919b fix(mcp): search returns empty results after container restart (#1105)
fix: read FALKORDB_DATABASE from environment variable in FalkorDB driver factory

Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-27 11:43:17 -04:00
zep-cla-assistant[bot] 7430d6f96d @prasmussen15 has signed the CLA in getzep/graphiti#1105 2026-07-27 15:38:50 +00:00
zep-cla-assistant[bot] 9140123a72 @Naseem77 has signed the CLA in getzep/graphiti#1686
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Lint with Ruff / ruff (push) Has been cancelled
Pyright Type Check / pyright (push) Has been cancelled
Tests / unit-tests (push) Has been cancelled
Tests / database-integration-tests (push) Has been cancelled
2026-07-26 12:42:42 +00:00
zep-cla-assistant[bot] 448e57c584 @vvivekranjan has signed the CLA in getzep/graphiti#1673
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Lint with Ruff / ruff (push) Has been cancelled
Pyright Type Check / pyright (push) Has been cancelled
Tests / unit-tests (push) Has been cancelled
Tests / database-integration-tests (push) Has been cancelled
2026-07-25 14:53:59 +00:00
Spencer Fuller 3bb2d0bba5 fix(falkordb): route namespace/ops get_by_group_ids reads to the group's graph (#1675)
Lint with Ruff / ruff (push) Has been cancelled
MCP Server Tests / live-mcp-tests (push) Has been cancelled
Pyright Type Check / pyright (push) Has been cancelled
Tests / unit-tests (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Tests / database-integration-tests (push) Has been cancelled
fix: route FalkorDB namespace/ops get_by_group_ids to correct graph

The classmethod get_by_group_ids paths were routed to the right FalkorDB
graph, but the namespace/ops read path (e.g. graphiti.nodes.episode.
get_by_group_ids) delegates to the Falkor *Operations classes with the base
driver (default_db) and never cloned to the group's graph, so a single
group_id read returned 0 rows.

Apply the same single-group clone + multi-group fan-out routing to all nine
FalkorDB operations get_by_group_ids methods (episode/entity/community/saga
nodes and episodic/entity/community/has_episode/next_episode edges), guarded
by isinstance(executor, GraphDriver) so the QueryExecutor param narrows to a
clone-capable driver. Adds a package-free routing regression test.

Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-23 19:03:23 -04:00
Daniel Chalef e72427ae6d disable Claude GitHub Actions workflows (#1678)
Remove claude.yml, claude-code-review.yml, and claude-code-review-manual.yml
so @claude invocations and automated/manual Claude PR reviews no longer run.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Daniel Chalef <danielchalef@users.noreply.github.com>
2026-07-23 12:40:47 -07:00
Daniel Chalef 40dae46040 docs: add Cursor Cloud dev environment setup instructions (#1677)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Daniel Chalef <danielchalef@users.noreply.github.com>
2026-07-23 12:00:34 -07:00
Jack Ryan 533ec53d95 docs: note Zep's proprietary Context Graph Engine in README (#1665)
Clarify that Zep is powered by a proprietary graph database (the Context
Graph Engine) built for millions of context graphs with low-latency
retrieval, so production deployments don't require a third-party graph
database. Adds a paragraph to the Zep section and a "Graph database" row
to the Zep vs. Graphiti comparison table.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-23 14:45:57 -04:00
zep-cla-assistant[bot] 0d6bb062a9 @kramerica-inc-dev has signed the CLA in getzep/graphiti#1653 2026-07-23 18:11:09 +00:00
zep-cla-assistant[bot] 2fc108d6e5 @spencer2211 has signed the CLA in getzep/graphiti#1675 2026-07-23 04:41:25 +00:00
Solaris-star 4674e1ed83 fix(falkordb): route single group_id search to the matching graph (#1670)
* fix(falkordb): route single group_id search to the matching graph

handle_multiple_group_ids only cloned the driver when len(group_ids) > 1.
add_episode re-binds self.driver for writes, so a fresh process searching
one group_id hit the driver's default database and returned empty results.

Clone call-scoped for a single differing group_id as well; do not reassign
the shared driver.

Fixes #1659

* test: drop unused MagicMock import (ruff F401)

---------

Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-22 20:24:48 -04:00
Maanik Garg 7db40315a3 fix: handle backtick tokens and empty queries in FalkorDB fulltext search (#1475)
The FalkorDB fulltext query builder had two bugs that caused
RediSearch syntax errors during entity dedup-search:

1. Backtick characters were missing from the separator map, so they
   leaked through to RediSearch and broke query parsing. This is
   common when LLMs extract entity names from code-fenced text.

2. When stopword filtering removed all tokens (or input was purely
   punctuation), the builder still constructed a query with empty
   parentheses, which RediSearch rejects with a syntax error.

Fix applied to both copies of the query builder:
- graphiti_core/driver/falkordb/operations/search_ops.py
- graphiti_core/driver/falkordb_driver.py

Closes #1440

Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-22 20:13:47 -04:00
Yufeng He d43bb19128 fix(mcp): preserve FalkorDB URI username (#1530)
Co-authored-by: Preston Rasmussen <109292228+prasmussen15@users.noreply.github.com>
2026-07-22 20:07:38 -04:00