Skip to content

feat(tools): add chDB tools for in-process ClickHouse SQL#6533

Open
ShawnChen-Sirius wants to merge 2 commits into
crewAIInc:mainfrom
ShawnChen-Sirius:feat/chdb-tools
Open

feat(tools): add chDB tools for in-process ClickHouse SQL#6533
ShawnChen-Sirius wants to merge 2 commits into
crewAIInc:mainfrom
ShawnChen-Sirius:feat/chdb-tools

Conversation

@ShawnChen-Sirius

Copy link
Copy Markdown

AI disclosure: this PR was authored with AI assistance (Claude Code), per the contributing guide it should carry the llm-generated label — I don't have permission to add labels on this repo, so please apply it. The design, testing, and review of every line were done by a ClickHouse engineer (chDB team).

What

Seven tools that give agents analytical SQL over local and remote data with chDB, the in-process ClickHouse engine, wrapping chdb.agents.ChDBTool (the agent-tool surface the chdb package ships and conformance-tests):

  • ChDBRunSelectQueryTool (run_select_query) — read-only ClickHouse SQL with {name:Type} parameter binding
  • ChDBListDatabasesTool, ChDBListTablesTool, ChDBDescribeTableTool, ChDBGetSampleDataTool, ChDBListFunctionsTool — schema discovery, including describing table-function expressions like s3('…','Parquet')
  • ChDBAttachFileTool (attach_file) — register a local file as a named table (writable sessions only)
  • chdb_tools() — builds the suite over one shared engine, so a table one tool attaches is visible to the others

Why (vs existing SQL tools)

  • In-process: no server, no connection string, no credentials, no env vars — the engine runs inside the Python process and reads Parquet/CSV/JSON files, S3/URLs, and remote databases through ClickHouse table functions.
  • Engine-level safety, not prompt-level: sessions default to ClickHouse readonly=2 (INSERT/CREATE/ALTER/DROP rejected by the engine while SELECT and file()/s3()/url() keep working — same direction as the NL2SQLTool read-only hardening); max_rows/max_bytes cap every payload with an explicit truncated flag; optional file_allowlist confines file-like sources to listed prefixes and refuses DSN-based sources.
  • Errors feed the model: every call returns a JSON envelope ({"ok": true, "result": …} / {"ok": false, "error": {code, type, message}}), so a wrong query becomes feedback the agent corrects instead of an exception that kills the crew run.

Notes for reviewers

  • chdb is an optional dependency (crewai-tools[chdb]). import crewai_tools works without it; tools raise a descriptive ImportError at first use.
  • chdb 4.2.1 (the extra's minimum) was released 2026-07-13, inside the rolling 3-day exclude-newer window, so the second commit adds it to the existing exclude-newer-package overrides. From 2026-07-16 the entry is no longer needed and can be dropped whenever convenient. uv.lock is intentionally untouched (CI re-resolves; happy to include the regenerated lock if you prefer).
  • tool.specs.json is intentionally untouched — the Generate Tool Specifications workflow doesn't run for fork PRs; happy to include the regenerated file instead.
  • Async is native: _arun delegates to the engine's acall() rather than blocking the loop.
  • ChDBBaseTool is importable from the subpackage but not exported at the top level, mirroring DaytonaBaseTool.
  • Tool names default to chDB's agent-tool names (run_select_query, …); they can be renamed at construction if a crew combines multiple SQL suites.

Testing

  • 19 tests in tests/tools/chdb_tool_test.py: unit tests against a mocked engine (no chdb needed) plus integration tests (pytest.importorskip("chdb")) covering parameter binding, the readonly=2 write rejection envelope, attach-then-query engine sharing, read-only attachments, and the introspection tools.
  • ruff check / ruff format and strict mypy (repo config, pydantic plugin) clean.
  • Verified import crewai_tools succeeds and tools construct with chdb absent (import blocked via a meta-path hook), with the lazy ImportError pointing at crewai-tools[chdb].

ShawnChen-Sirius and others added 2 commits July 14, 2026 11:51
Seven tools over chdb.agents.ChDBTool, the agent-tool surface the chdb
package ships: run_select_query (read-only ClickHouse SQL with parameter
binding), list_databases, list_tables, describe_table, get_sample_data,
list_functions, and attach_file, plus a chdb_tools() factory that builds
the suite over one shared engine so attached tables are visible across
tools.

The engine runs inside the Python process, so unlike server-backed SQL
tools there is no connection string, credential, or env var. Safety is
engine-level rather than prompt-level: sessions default to the ClickHouse
readonly=2 setting, results are capped by max_rows/max_bytes with a
truncated flag, and every call returns a JSON envelope (ok/result or
ok/error) so the agent can read engine errors and self-correct instead
of crashing the run.

chdb is an optional dependency (crewai-tools[chdb]): importing
crewai_tools works without it, and tools raise a descriptive ImportError
at first use. Unit tests run against a mocked engine; integration tests
skip when chdb is not installed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
chdb 4.2.1 is the minimum for the new crewai-tools chdb extra and was
released 2026-07-13, inside the rolling 3-day exclude-newer window; add
it to the per-package overrides so resolution succeeds, following the
existing entries.

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

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an optional chDB dependency and a CrewAI tool suite for queries, introspection, file attachments, shared engine lifecycle, JSON responses, and read-only enforcement. Public exports, documentation, package configuration, unit tests, and integration tests are included.

Changes

ChDB Tool Suite

Layer / File(s) Summary
Package dependency and public exports
lib/crewai-tools/pyproject.toml, lib/crewai-tools/src/crewai_tools/__init__.py, lib/crewai-tools/src/crewai_tools/tools/__init__.py, lib/crewai-tools/src/crewai_tools/tools/chdb_tool/__init__.py, pyproject.toml
Adds the chdb optional dependency, exposes ChDB tools through package APIs, and configures the uv package cutoff.
Shared engine and tool implementations
lib/crewai-tools/src/crewai_tools/tools/chdb_tool/chdb_tool.py
Implements lazy dependency loading, shared engine lifecycle, sync/async dispatch, query and introspection tools, file attachment, and read-only suite composition.
Behavior validation and usage documentation
lib/crewai-tools/src/crewai_tools/tools/chdb_tool/README.md, lib/crewai-tools/tests/tools/chdb_tool_test.py
Documents installation, safety behavior, lifecycle, and usage while testing dispatch, JSON envelopes, async calls, attachments, read-only enforcement, and integrations.

Sequence Diagram(s)

sequenceDiagram
  participant Agent
  participant ChDBRunSelectQueryTool
  participant ChDBTool
  participant ChDBEngine
  Agent->>ChDBRunSelectQueryTool: submit SQL and params
  ChDBRunSelectQueryTool->>ChDBTool: dispatch run_select_query
  ChDBTool->>ChDBEngine: call or acall
  ChDBEngine-->>ChDBTool: JSON success or error envelope
  ChDBTool-->>Agent: return serialized response
Loading

Suggested reviewers: lorenzejay, joaomdmoura, greysonlalonde, vinibrsl, theishangoswami

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.11% 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
Title check ✅ Passed The title accurately summarizes the main change: adding chDB tools for in-process ClickHouse SQL.
Description check ✅ Passed The description matches the change set and explains the new chDB tools, shared engine, safety defaults, and tests.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@lib/crewai-tools/src/crewai_tools/tools/chdb_tool/chdb_tool.py`:
- Around line 11-20: Update ChDBBaseTool.close in
lib/crewai-tools/src/crewai_tools/tools/chdb_tool/chdb_tool.py:11-20 to close
the underlying session or guard the cleanup so it does not unconditionally call
the unsupported ChDBTool.close method. The references in
lib/crewai-tools/pyproject.toml:151-154 and pyproject.toml:175-176 require no
direct changes.

In `@lib/crewai-tools/tests/tools/chdb_tool_test.py`:
- Around line 169-171: Scope the chdb dependency skip to only the real-engine
integration tests, not the mocked unit tests in chdb_tool_test.py. Move those
integration tests and the pytest.importorskip("chdb") call into a separate test
module, or apply per-test/class-level skipping to the integration-test symbols
while keeping the mocked tests runnable without chdb.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 484a1f90-3612-4e88-b17f-964e8d233d72

📥 Commits

Reviewing files that changed from the base of the PR and between 9d72e26 and 66e5345.

📒 Files selected for processing (8)
  • lib/crewai-tools/pyproject.toml
  • lib/crewai-tools/src/crewai_tools/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/chdb_tool/README.md
  • lib/crewai-tools/src/crewai_tools/tools/chdb_tool/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/chdb_tool/chdb_tool.py
  • lib/crewai-tools/tests/tools/chdb_tool_test.py
  • pyproject.toml

Comment on lines +11 to +20
def _import_chdb_tool_class() -> Any:
"""Import chdb.agents.ChDBTool lazily so crewai-tools imports without chdb."""
try:
from chdb.agents import ChDBTool
except ImportError as exc:
raise ImportError(
"The 'chdb' package is required for the chDB tools. "
"Install it with: uv add chdb (or) pip install 'crewai-tools[chdb]'"
) from exc
return ChDBTool

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does chdb 4.2.1 exist on PyPI, and does it include a chdb.agents.ChDBTool class with call/acall methods?

💡 Result:

Yes, chdb version 4.2.1 exists on PyPI [1]. It includes a chdb.agents.ChDBTool class [2][3], which provides both call and acall methods for interacting with the database in synchronous and asynchronous contexts, respectively [2]. This class is designed as a canonical agent tool for LLM frameworks [2][4].

Citations:


🌐 Web query:

chdb 4.2.1 ChDBTool constructor path read_only max_rows max_bytes max_execution_time file_allowlist attachments close read_only

💡 Result:

The ChDBTool, introduced in chdb 4.2.x, is a session-backed tool designed for use in AI agent frameworks [1][2]. It is located in the chdb.agents subpackage [1]. The ChDBTool constructor accepts several parameters to configure the session and restrict its capabilities, typically for safety in agent environments: - read_only (bool): If set to True (default), it enables read-only mode by setting the underlying engine session to readonly=2, which allows reads and file-access functions (like file, s3, url) but blocks write operations such as INSERT, CREATE, ALTER, and DROP [1]. - max_execution_time (int): Configures an engine-side query timeout (in seconds) to prevent long-running or hanging queries [2]. - file_allowlist (list): A list of allowed file paths or patterns; if configured, the engine will reject file/s3/url operations that attempt to access paths outside this allowlist [2]. - attachments (dict): Allows registering local files as views in the session. For read-only tools, these are materialized before the read-only lock is applied [2]. Other parameters like max_rows and max_bytes are also supported to apply constraints on query results (e.g., for truncation) [1]. Note: The chdb.agents module is currently marked as beta, meaning the API may evolve in future minor releases [3]. Top results: [1], [2]

Citations:


🌐 Web query:

chdb.agents.ChDBTool close read_only attribute source

💡 Result:

The read_only attribute in chdb.agents.ChDBTool is a configuration parameter used during tool construction to control the safety constraints of the underlying chDB session [1]. When initialized (e.g., tool = ChDBTool(read_only=True)), it sets the internal chDB session to a specific read-only mode [1]. Specifically, it configures the engine with SET readonly=2 [1]. This mode is intentionally chosen over the standard readonly=1, as readonly=1 would block essential file functions like file, s3, and url [1]. By using readonly=2, the tool allows read operations and necessary file access while effectively blocking destructive actions such as INSERT, CREATE, ALTER, and DROP [1]. This safety lock is designed to be robust and cannot be easily bypassed (e.g., executing SET readonly=0 or attempting multi-statement writes will fail) [1]. Users can opt out of this behavior by initializing the tool with read_only=False [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the relevant usage sites in chdb_tool.py
file="lib/crewai-tools/src/crewai_tools/tools/chdb_tool/chdb_tool.py"

echo "== outline =="
ast-grep outline "$file" --view expanded || true

echo
echo "== member usage =="
rg -n "\.close\b|\.call\b|\.acall\b|read_only\b|max_rows\b|max_bytes\b|max_execution_time\b|file_allowlist\b|attachments\b" "$file"

Repository: crewAIInc/crewAI

Length of output: 5800


🌐 Web query:

chdb.agents.ChDBTool close method source or docs

💡 Result:

The chdb.agents.ChDBTool is a component designed for LLM agent frameworks [1]. While specific method-level documentation for its source code is evolving as part of the chdb.agents subpackage, it functions as a session-backed tool [1]. In the broader chDB ecosystem, including the standard Session and DB-API implementations, the close method is used to close the connection or session and release resources [2][3][4]. For chDB Session and Connection objects: - The close method closes the underlying connection and releases associated resources [2][4]. - Once called, the session or connection becomes invalid, and further operations will typically raise an error [2][4]. - It is often recommended to use context managers (the with statement) to ensure resources are cleaned up automatically [2][4]. If you are working specifically with the ChDBTool class, it wraps these underlying mechanisms to provide a consistent interface for agent tasks [1]. You can inspect the source code directly in the chdb/agents/tool.py file within the official chdb repository to see the specific implementation details for the ChDBTool class [5].

Citations:


🌐 Web query:

site:github.com/chdb-io/chdb "class ChDBTool" "def close" "read_only"

💡 Result:

The ChDBTool class is a component of the chdb Python library, specifically found under the chdb.agents module [1][2]. It is designed as a tool for LLM agents to interact with chDB in a controlled manner [1]. Regarding your specific query about its initialization and methods: Initialization (read_only parameter): When instantiating ChDBTool, you can set a read_only parameter [1]. - When read_only=True (the default), the underlying chDB session is configured with SET readonly=2 [1]. This level restricts DDL, INSERT, and other write operations while still allowing essential read-heavy operations like file or s3 table functions [1]. - To allow write operations, you must explicitly set read_only=False [1]. Methods: The ChDBTool class provides methods for interacting with the database, such as: - query: Executes SQL queries [1]. - describe: Used for table introspection [1]. - call: Dispatches specific tool actions [1]. Regarding close: While ChDBTool is a specialized agent tool, standard chDB sessions and connections in the library generally require manual closure if not used within a context manager [3][4][5]. If you are working with the underlying session or connection objects associated with or used by a tool, it is best practice to ensure they are properly closed to avoid resource leaks or conflicts, especially in environments like testing [4][5]. Always verify if the specific version of ChDBTool you are using exposes a close method or requires you to manage the lifecycle of the underlying session separately, as the library's agent module is currently marked as beta [6]. [1][6]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '168,180p' pyproject.toml
echo
sed -n '146,158p' lib/crewai-tools/pyproject.toml

Repository: crewAIInc/crewAI

Length of output: 1086


🌐 Web query:

chdb.agents.tool.py ChDBTool close method source

💡 Result:

The chdb.agents.ChDBTool class is part of the chDB Python library, specifically designed as a tool for LLM agents [1][2]. While ChDBTool provides methods like query, describe, call, and attach_file [1][3], it does not implement a dedicated close method in its public API [1][2]. Instead, ChDBTool acts as a wrapper around the underlying chDB session management [1]. In the chDB library, session cleanup is typically handled via: 1. The underlying chdb.Session object, which does provide a close() method to explicitly close the session and clean up resources [4]. 2. Python's context manager protocol (the with statement), which automatically manages the lifecycle of the session [4]. If you are working with an instance of ChDBTool and need to ensure resource cleanup, you should manage the lifecycle of the internal session object (if exposed) or rely on the host application's environment management for the tool instance [1]. The source code for this tool is located in the chdb-io/chdb repository at chdb/agents/tool.py [1][2].

Citations:


Guard the cleanup call

ChDBTool doesn’t expose close(), so ChDBBaseTool.close() can raise on shutdown when it unconditionally calls engine.close(). Close the underlying session instead or guard this call.

📍 Affects 3 files
  • lib/crewai-tools/src/crewai_tools/tools/chdb_tool/chdb_tool.py#L11-L20 (this comment)
  • lib/crewai-tools/pyproject.toml#L151-L154
  • pyproject.toml#L175-L176
🤖 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 `@lib/crewai-tools/src/crewai_tools/tools/chdb_tool/chdb_tool.py` around lines
11 - 20, Update ChDBBaseTool.close in
lib/crewai-tools/src/crewai_tools/tools/chdb_tool/chdb_tool.py:11-20 to close
the underlying session or guard the cleanup so it does not unconditionally call
the unsupported ChDBTool.close method. The references in
lib/crewai-tools/pyproject.toml:151-154 and pyproject.toml:175-176 require no
direct changes.

Comment on lines +169 to +171
# --- integration tests against the real engine -------------------------------

chdb = pytest.importorskip("chdb")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Module-level importorskip here skips the mocked unit tests too, not just the integration tests below.

pytest.importorskip raises a module-level skip regardless of where it's placed in the file — it doesn't only affect tests defined after it. When chdb isn't installed, this skips the entire file, including the 12 mocked-engine unit tests above (Lines 44-166) that are explicitly designed to run without chdb installed. That defeats the stated purpose of the "unit tests against a mocked engine (no chdb install required)" section.

Split the integration tests into their own file with the importorskip, or scope the skip to just those tests (e.g. a nested class with pytestmark, or per-test skipif).

🤖 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 `@lib/crewai-tools/tests/tools/chdb_tool_test.py` around lines 169 - 171, Scope
the chdb dependency skip to only the real-engine integration tests, not the
mocked unit tests in chdb_tool_test.py. Move those integration tests and the
pytest.importorskip("chdb") call into a separate test module, or apply
per-test/class-level skipping to the integration-test symbols while keeping the
mocked tests runnable without chdb.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant