feat(tools): add chDB tools for in-process ClickHouse SQL#6533
feat(tools): add chDB tools for in-process ClickHouse SQL#6533ShawnChen-Sirius wants to merge 2 commits into
Conversation
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>
📝 WalkthroughWalkthroughAdds 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. ChangesChDB Tool Suite
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
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (8)
lib/crewai-tools/pyproject.tomllib/crewai-tools/src/crewai_tools/__init__.pylib/crewai-tools/src/crewai_tools/tools/__init__.pylib/crewai-tools/src/crewai_tools/tools/chdb_tool/README.mdlib/crewai-tools/src/crewai_tools/tools/chdb_tool/__init__.pylib/crewai-tools/src/crewai_tools/tools/chdb_tool/chdb_tool.pylib/crewai-tools/tests/tools/chdb_tool_test.pypyproject.toml
| 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 |
There was a problem hiding this comment.
🗄️ 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:
- 1: https://pypi.org/project/chdb/4.2.1/
- 2: Add chdb.agents.ChDBTool — canonical agent tool + cross-language contract chdb-io/chdb#594
- 3: chdb-io/chdb@fe93430
- 4: chdb-io/chdb@89ed79c
🌐 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:
- 1: Add chdb.agents.ChDBTool — canonical agent tool + cross-language contract chdb-io/chdb#594
- 2: chdb-io/chdb@89ed79c
- 3: agents: mark beta + accept (database, table) qualification (4.2.0 prep) chdb-io/chdb#597
🌐 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:
- 1: Add chdb.agents.ChDBTool — canonical agent tool + cross-language contract chdb-io/chdb#594
- 2: https://chdb.readthedocs.io/en/latest/session.html
- 3: https://github.com/clickhouse/agent-skills/blob/main/skills/chdb-sql/references/api-reference.md
- 4: https://chdb.readthedocs.io/en/latest/dbapi.html
- 5: chdb-io/chdb@fe93430
🌐 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:
- 1: Add chdb.agents.ChDBTool — canonical agent tool + cross-language contract chdb-io/chdb#594
- 2: chdb-io/chdb@fe93430
- 3: Does chdb supports orm? If supports, how to use? chdb-io/chdb#213
- 4: Conflict with multiple CHDB connections on a pytest session chdb-io/chdb#331
- 5: https://github.com/chdb-io/chdb/tree/refs/heads/main
- 6: agents: mark beta + accept (database, table) qualification (4.2.0 prep) chdb-io/chdb#597
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '168,180p' pyproject.toml
echo
sed -n '146,158p' lib/crewai-tools/pyproject.tomlRepository: 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:
- 1: Add chdb.agents.ChDBTool — canonical agent tool + cross-language contract chdb-io/chdb#594
- 2: chdb-io/chdb@fe93430
- 3: chdb-io/chdb@89ed79c
- 4: https://chdb.readthedocs.io/en/latest/session.html
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-L154pyproject.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.
| # --- integration tests against the real engine ------------------------------- | ||
|
|
||
| chdb = pytest.importorskip("chdb") |
There was a problem hiding this comment.
🎯 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.
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 thechdbpackage ships and conformance-tests):ChDBRunSelectQueryTool(run_select_query) — read-only ClickHouse SQL with{name:Type}parameter bindingChDBListDatabasesTool,ChDBListTablesTool,ChDBDescribeTableTool,ChDBGetSampleDataTool,ChDBListFunctionsTool— schema discovery, including describing table-function expressions likes3('…','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 othersWhy (vs existing SQL tools)
readonly=2(INSERT/CREATE/ALTER/DROP rejected by the engine while SELECT andfile()/s3()/url()keep working — same direction as the NL2SQLTool read-only hardening);max_rows/max_bytescap every payload with an explicittruncatedflag; optionalfile_allowlistconfines file-like sources to listed prefixes and refuses DSN-based sources.{"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
chdbis an optional dependency (crewai-tools[chdb]).import crewai_toolsworks without it; tools raise a descriptive ImportError at first use.exclude-newerwindow, so the second commit adds it to the existingexclude-newer-packageoverrides. From 2026-07-16 the entry is no longer needed and can be dropped whenever convenient.uv.lockis intentionally untouched (CI re-resolves; happy to include the regenerated lock if you prefer).tool.specs.jsonis intentionally untouched — the Generate Tool Specifications workflow doesn't run for fork PRs; happy to include the regenerated file instead._arundelegates to the engine'sacall()rather than blocking the loop.ChDBBaseToolis importable from the subpackage but not exported at the top level, mirroringDaytonaBaseTool.run_select_query, …); they can be renamed at construction if a crew combines multiple SQL suites.Testing
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 formatand strictmypy(repo config, pydantic plugin) clean.import crewai_toolssucceeds and tools construct with chdb absent (import blocked via a meta-path hook), with the lazy ImportError pointing atcrewai-tools[chdb].