Skip to content

feat(tool_falkordb): query FalkorDB graphs with Cypher as an agent tool#1251

Merged
kwit75 merged 6 commits into
developfrom
feat/tool-falkordb
Jun 12, 2026
Merged

feat(tool_falkordb): query FalkorDB graphs with Cypher as an agent tool#1251
kwit75 merged 6 commits into
developfrom
feat/tool-falkordb

Conversation

@kwit75

@kwit75 kwit75 commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

New tool_falkordb node — agents query a FalkorDB graph database directly with Cypher (Joe's integration list, #6). Deliberately a lightweight tool_* node (agent writes its own Cypher), not a db_* NL→Cypher pipeline component like db_neo4j — that heavier shape can come later if needed.

Tools

Tool What it does
falkordb.query run Cypher (params$name, injection-safe), rows serialized + capped
falkordb.list_graphs graph names on the server
falkordb.get_schema labels / relationship types / property keys

Safety

  • Read-only by default, enforced server-side: queries go through GRAPH.RO_QUERY unless allow_writes is on — write clauses are rejected by FalkorDB itself, not by a client-side regex.
  • Values travel as Cypher parameters, never spliced into query text.
  • Rows capped (max_rows, default 250, max 25000 per repo convention) with a truncated flag; server-side per-query timeout (ms).
  • Redis errors → error dicts; input validation client-side before any server call.

Live smoke (real server)

Ran the node code against falkordb/falkordb:latest in Docker — 6 scenarios, all green:
RO write rejection (server-side) ✓, parameterized CREATE + write stats ✓, Node/Edge serialization ✓, row cap + truncated ✓, schema + list_graphs ✓, bad-Cypher error dict ✓.

Dependency note

falkordb>=1.6,<2 requires redis>=7.1 (and pre-1.4 falkordb requires <6), so no falkordb version coexists with memory_persistent's redis>=6.4,<7 in the engine-wide constraints solve. This PR bumps memory_persistent to redis>=7.1,<8: the redis-py surface it uses (get/exists/hget/incrby/lrange/pexpire/pipeline/pttl/rpush/sadd/scard/sismember/smembers/srem) is identical across 6.x/7.x, and the <7 cap came from a conservative dependabot range (#949), not a compat need. Full-tree uv pip compile verified: redis==7.4.1, falkordb==1.6.1.

Tests

  • nodes/test/test_tool_falkordb.py — 10 network-free unit tests (serialization incl. temporals, header shaping, ro/write routing, row cap, error dicts, graph override, validation-before-call).
  • Mock client nodes/test/mocks/falkordb/ → keyless dynamic smoke runs; services.json test block; contracts 238 passed locally; ruff clean.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • FalkorDB Cypher query tool: run parameterized queries (read-only by default), optional write mode, schema inspection, graph listing, configurable default graph, max rows/truncation, query timeout, and structured results with optional write stats.
  • Documentation

    • Full FalkorDB tool docs and quickstart with usage, config fields, examples, and reference.
  • Chores

    • Updated Redis requirement to >=7.1,<8 and pinned FalkorDB client to >=1.6,<2.
  • Tests

    • Added unit tests and a mock FalkorDB client covering serialization, routing, errors, schema, and listing.

New tool node exposing query, list_graphs and get_schema. Queries run
read-only via GRAPH.RO_QUERY (the server itself rejects write clauses)
unless allow_writes is enabled in config; values go through Cypher
parameters so user data is never spliced into query text. Rows are
capped at a configurable max with a truncated flag; nodes/edges/paths
serialize to plain JSON; redis errors come back as error dicts.

memory_persistent moves to redis>=7.1,<8: falkordb requires redis>=7.1
(older falkordb requires <6), so the previous >=6.4,<7 pin made the
engine-wide uv constraints solve unsatisfiable. The redis-py surface
memory_persistent uses (get/exists/hget/incrby/lrange/pexpire/pipeline/
pttl/rpush/sadd/scard/sismember/smembers/srem) is identical across 6.x
and 7.x. Full-tree solve verified with uv pip compile: redis==7.4.1,
falkordb==1.6.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a FalkorDB Cypher tool node: dependency updates, global lifecycle (IGlobal), instance exposing query/list_graphs/get_schema with serialization and structured error handling, service/config wiring, docs, and unit tests.

Changes

FalkorDB Tool Node

Layer / File(s) Summary
Dependencies and mock test infrastructure
nodes/src/nodes/memory_persistent/requirements.txt, nodes/src/nodes/tool_falkordb/requirements.txt, nodes/test/mocks/falkordb/__init__.py
Redis constraint updated to >=7.1,<8; falkordb pinned to >=1.6,<2. Adds a mock FalkorDB client for isolated tests.
Global state lifecycle and configuration
nodes/src/nodes/tool_falkordb/IGlobal.py
IGlobal manages client construction (host/port/auth/TLS), coerces config values, verifies connectivity via list_graphs(), validates config, and closes the client safely.
Tool instance with query and schema operations
nodes/src/nodes/tool_falkordb/IInstance.py
IInstance implements query (Cypher with read-only-by-default, optional write stats, row truncation), list_graphs, and get_schema; includes JSON-safe serialization, header extraction, and structured Redis error handling.
Configuration, service definition, and module initialization
nodes/src/nodes/tool_falkordb/__init__.py, nodes/src/nodes/tool_falkordb/services.json
Module initializer registers dependencies and exports IGlobal/IInstance. services.json declares protocol, config fields (host/port/auth/TLS/default graph/allow_writes/max_rows/query_timeout_ms), a smoke test profile, and UI shape.
User-facing and implementation documentation
nodes/src/nodes/tool_falkordb/README.md, nodes/src/nodes/tool_falkordb/doc.md
README and doc.md describe tool capabilities, parameters/returns, configuration options (read-only default, optional writes, row limits, timeouts), Docker quickstart, and upstream references.
Comprehensive unit test suite
nodes/test/test_tool_falkordb.py
Tests include conditional import stubs, local fakes, and coverage for serialization, header extraction, query routing (ro_query vs query), write stats, truncation with truncated flag, param validation, Redis error handling, graph override behavior, list_graphs, and get_schema.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant IInstance
  participant IGlobal
  participant Graph
  participant FalkorDB
  User->>IInstance: query(cypher, params)
  IInstance->>IInstance: validate cypher and params
  IInstance->>IGlobal: select graph (or use default)
  IGlobal-->>IInstance: Graph client
  alt allow_writes is false
    IInstance->>Graph: ro_query(cypher, params, timeout)
  else allow_writes is true
    IInstance->>Graph: query(cypher, params, timeout)
  end
  Graph->>FalkorDB: execute command
  FalkorDB-->>Graph: rows, headers, optional stats
  Graph-->>IInstance: result
  IInstance->>IInstance: serialize rows, truncate to max_rows
  IInstance-->>User: {columns, rows, truncated, stats?, error?}
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • jmaionchi
  • Rod-Christensen
  • stepmikhaylov
  • asclearuc

Poem

🐰 A FalkorDB graph so bright,
Queries dance with Cypher's might,
Read-only shields from careless writes,
Schema whispers in the night,
Tests keep all the edges right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.60% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a new FalkorDB tool node for querying graphs with Cypher as an agent tool.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tool-falkordb

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added docs Documentation module:nodes Python pipeline nodes labels Jun 11, 2026
@github-actions

Copy link
Copy Markdown
🤖 Internal: Discord sync marker

Auto-managed by the Discord notification workflow. Stores the linked Discord message ID. Do not edit or delete.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
nodes/test/test_tool_falkordb.py (1)

275-282: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Strengthen get_schema contract coverage.

This test only checks labels. Add assertions for relationship_types and property_keys to lock the documented/runtime response shape and prevent partial regressions.

Proposed test assertion extension
 def test_get_schema_shapes_columns():
     graph = _FakeGraph(_FakeResult(result_set=[['Person'], ['City']], header=[[1, 'label']]))
     inst = _instance(_FakeGlobal(graph))
     out = inst.get_schema({})
     assert out['labels'] == ['Person', 'City']
+    assert 'relationship_types' in out
+    assert 'property_keys' in out
     # All three procedures run read-only.
     assert all(call[0] == 'ro_query' for call in graph.calls)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@nodes/test/test_tool_falkordb.py` around lines 275 - 282, Extend the
test_get_schema_shapes_columns to assert that inst.get_schema({}) returns the
full schema shape: verify out contains 'relationship_types' and 'property_keys'
keys and that their values match the expected lists (or at minimum are lists of
the expected length/contents) in addition to 'labels'; locate the test using
test_get_schema_shapes_columns and the helper fixtures (_FakeGraph, _FakeResult,
_instance, get_schema) and add assertions after the labels check, and keep the
existing check that all graph.calls are 'ro_query'.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@nodes/src/nodes/tool_falkordb/doc.md`:
- Line 9: Fix the typo in the intro sentence by replacing "Lets agents query a
FalkorDB..." with a grammatically correct form such as "Let's agents query..."
or better "Allows agents to query a FalkorDB..." in the documentation line that
mentions FalkorDB and GRAPH.RO_QUERY; ensure surrounding references like
"GRAPH.RO_QUERY" and the UI label "Allow Writes" remain unchanged.
- Line 27: Update the documented return contract in the "Returns" section to
explicitly include the error response shape used on Redis failures: document
that responses may include an "error" string and that in error cases "rows" and
"columns" are empty, "row_count" equals 0, and "truncated" is false; mention
that write "stats" will be absent or zero when an error occurs so consumers can
handle success vs error branches predictably.

---

Outside diff comments:
In `@nodes/test/test_tool_falkordb.py`:
- Around line 275-282: Extend the test_get_schema_shapes_columns to assert that
inst.get_schema({}) returns the full schema shape: verify out contains
'relationship_types' and 'property_keys' keys and that their values match the
expected lists (or at minimum are lists of the expected length/contents) in
addition to 'labels'; locate the test using test_get_schema_shapes_columns and
the helper fixtures (_FakeGraph, _FakeResult, _instance, get_schema) and add
assertions after the labels check, and keep the existing check that all
graph.calls are 'ro_query'.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 20f72337-6ade-433a-932f-57511b5c99fd

📥 Commits

Reviewing files that changed from the base of the PR and between 7bbe2b2 and 213f78e.

⛔ Files ignored due to path filters (1)
  • nodes/src/nodes/tool_falkordb/falkordb.svg is excluded by !**/*.svg
📒 Files selected for processing (10)
  • nodes/src/nodes/memory_persistent/requirements.txt
  • nodes/src/nodes/tool_falkordb/IGlobal.py
  • nodes/src/nodes/tool_falkordb/IInstance.py
  • nodes/src/nodes/tool_falkordb/README.md
  • nodes/src/nodes/tool_falkordb/__init__.py
  • nodes/src/nodes/tool_falkordb/doc.md
  • nodes/src/nodes/tool_falkordb/requirements.txt
  • nodes/src/nodes/tool_falkordb/services.json
  • nodes/test/mocks/falkordb/__init__.py
  • nodes/test/test_tool_falkordb.py

Comment thread nodes/src/nodes/tool_falkordb/doc.md
Comment thread nodes/src/nodes/tool_falkordb/doc.md Outdated
Dmitrii Kataraev and others added 2 commits June 11, 2026 16:59
…omment, README mirror

The error-path test raised a file-local stub exception while the module
under test binds RedisError at import — with real redis already in
sys.modules (the nodes:test-full condition) the except clause no longer
caught it. The fake now raises mod.RedisError, which is correct under
both stubbed and real imports (verified by running with real redis
preimported).

memory_persistent's requirements comment describes the current
constraint only; README mirrors doc.md per the tool_apify convention.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@nodes/src/nodes/tool_falkordb/doc.md`:
- Line 27: The Returns sections for falkordb.list_graphs and falkordb.get_schema
omit the error response shapes; update the docs for those two tools to
explicitly state the failure shape: for falkordb.list_graphs add a sentence like
"On failure, returns `error` instead (with empty `graphs`)." and for
falkordb.get_schema add "On failure, returns `error` instead (with empty
`labels`, `relationship_types`, and `property_keys`)." so they match the query
error documentation.

In `@nodes/src/nodes/tool_falkordb/README.md`:
- Line 27: Update the README entries for falkordb.list_graphs and
falkordb.get_schema to explicitly document their error response shapes (as
implemented in IInstance.py): in the falkordb.list_graphs "Returns" section add
"On failure, returns `error` instead (with empty `graphs`)." and in the
falkordb.get_schema "Returns" section add "On failure, returns `error` instead
(with empty `labels`, `relationship_types`, and `property_keys`)." Ensure the
wording matches the query error description style and references the same field
names used by the implementation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 551e7c49-77b4-430a-ba4c-878ab752bc49

📥 Commits

Reviewing files that changed from the base of the PR and between 617e257 and 293c4b2.

📒 Files selected for processing (2)
  • nodes/src/nodes/tool_falkordb/README.md
  • nodes/src/nodes/tool_falkordb/doc.md

| `params` | no | Values for the `$name` placeholders (injection-safe) |
| `graph` | no | Graph to query (default from config) |

Returns `columns`, `rows` (nodes/edges serialized to objects, capped at *Max Rows* with a `truncated` flag) and, when writes are enabled, non-zero write `stats`. On a query failure all three tools return `error` instead (with empty `rows`/`columns`, `row_count: 0`, `truncated: false` for `query`).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Explicitly document error response shapes for falkordb.list_graphs and falkordb.get_schema.

Lines 31 and 39 document success returns but omit error cases, while line 27 clarifies the query error shape. Per the implementation, both list_graphs and get_schema return error plus their respective empty fields on failure:

  • list_graphs error: {error, graphs: []}
  • get_schema error: {error, labels: [], relationship_types: [], property_keys: []}

Add explicit error documentation to the "Returns" sections for those two tools, matching the clarity provided for query.

✏️ Suggested updates

After line 31, add:

On failure, returns `error` instead (with empty `graphs`).

After line 39, add:

On failure, returns `error` instead (with empty `labels`, `relationship_types`, and `property_keys`).

Also applies to: 31-31, 39-39

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@nodes/src/nodes/tool_falkordb/doc.md` at line 27, The Returns sections for
falkordb.list_graphs and falkordb.get_schema omit the error response shapes;
update the docs for those two tools to explicitly state the failure shape: for
falkordb.list_graphs add a sentence like "On failure, returns `error` instead
(with empty `graphs`)." and for falkordb.get_schema add "On failure, returns
`error` instead (with empty `labels`, `relationship_types`, and
`property_keys`)." so they match the query error documentation.

| `params` | no | Values for the `$name` placeholders (injection-safe) |
| `graph` | no | Graph to query (default from config) |

Returns `columns`, `rows` (nodes/edges serialized to objects, capped at *Max Rows* with a `truncated` flag) and, when writes are enabled, non-zero write `stats`. On a query failure all three tools return `error` instead (with empty `rows`/`columns`, `row_count: 0`, `truncated: false` for `query`).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Explicitly document error response shapes for falkordb.list_graphs and falkordb.get_schema.

Line 27 clarifies the query error shape but leaves the error contracts for list_graphs and get_schema implicit. Per the implementation in IInstance.py, both tools return error plus their respective empty fields on failure:

  • list_graphs error: {error, graphs: []}
  • get_schema error: {error, labels: [], relationship_types: [], property_keys: []}

Expand the "Returns" sections for those tools to document their error cases explicitly, matching the clarity provided for query.

✏️ Suggested update

After line 31 (in the falkordb.list_graphs section), add:

On failure, returns `error` instead (with empty `graphs`).

After line 39 (in the falkordb.get_schema section), add:

On failure, returns `error` instead (with empty `labels`, `relationship_types`, and `property_keys`).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@nodes/src/nodes/tool_falkordb/README.md` at line 27, Update the README
entries for falkordb.list_graphs and falkordb.get_schema to explicitly document
their error response shapes (as implemented in IInstance.py): in the
falkordb.list_graphs "Returns" section add "On failure, returns `error` instead
(with empty `graphs`)." and in the falkordb.get_schema "Returns" section add "On
failure, returns `error` instead (with empty `labels`, `relationship_types`, and
`property_keys`)." Ensure the wording matches the query error description style
and references the same field names used by the implementation.

Dmitrii Kataraev and others added 3 commits June 11, 2026 18:04
IInstance catches redis.exceptions.RedisError (falkordb-py re-raises
redis-py exceptions verbatim and exports no error hierarchy of its
own), so the import gets an explicit requirement instead of leaning on
falkordb's transitive dependency. Same range the solve already pins.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kwit75 kwit75 enabled auto-merge (squash) June 12, 2026 03:43
@kwit75 kwit75 merged commit 052b2e7 into develop Jun 12, 2026
30 of 33 checks passed
@kwit75 kwit75 deleted the feat/tool-falkordb branch June 12, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation module:nodes Python pipeline nodes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants