LlamaIndex Tools Integration: chDB

July 14, 2026 · View on GitHub

Give agents analytical SQL over local and remote data with chDB, the in-process ClickHouse engine. The engine runs inside the Python process — no server to start, no connection string, no credentials — and queries local files (Parquet/CSV/JSON), object storage, and remote databases through ClickHouse table functions.

Installation

pip install llama-index-tools-chdb

Usage

from llama_index.tools.chdb import ChDBToolSpec
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI

spec = ChDBToolSpec(attachments={"events": "data/events.parquet"})

agent = FunctionAgent(
    tools=spec.to_tool_list(),
    llm=OpenAI(model="gpt-4o-mini"),
)

print(await agent.run("What are the top 5 event types by count?"))

The spec exposes seven tools, mirroring the tool surface chDB ships for agents (chdb.agents):

  • run_select_query — read-only ClickHouse SQL with {name:Type} parameter binding (full dialect: 1000+ functions, window functions, arrays, JSON)
  • list_databases, list_tables, describe_table, get_sample_data, list_functions — schema discovery, including describing table-function expressions such as s3('https://bucket/f.parquet','Parquet')
  • attach_file — register a local file as a named table (writable sessions only; on read-only sessions declare files via the attachments argument instead)

Every tool has an async twin (arun_select_query, …) backed by the engine's native async path, so to_tool_list() produces tools usable in both sync and async agents.

Safety defaults

  • Read-only by default. Sessions are locked with the ClickHouse readonly=2 setting: INSERT/CREATE/ALTER/DROP are rejected by the engine (not by prompt), while SELECT and the file()/s3()/url() table functions keep working. Pass read_only=False for a writable session.
  • Capped results. max_rows (default 1000) and max_bytes (default 1 MB) bound every payload; truncated results carry a truncated flag the agent can react to. max_execution_time adds an engine-side wall-clock limit.
  • Optional source allowlist. With file_allowlist=["/data/"], file-like sources may only read under the listed prefixes and DSN-based sources (postgresql(), mysql(), remote(), …) are refused.
  • Errors go to the model, not the run. Every call returns a JSON envelope — {"ok": true, "result": …} or {"ok": false, "error": {"code", "type", "message"}} — so a bad query becomes feedback the agent corrects instead of an exception.

Querying remote data

spec = ChDBToolSpec()
spec.run_select_query(
    "SELECT status, count() FROM url('https://example.com/logs.ndjson', 'JSONEachRow') GROUP BY status"
)

s3(...), postgresql(...), mysql(...), mongodb(...), remoteSecure(...), iceberg(...), and deltaLake(...) work the same way, subject to the read-only lock and allowlist.

Sharing and lifecycle

To control the engine's lifecycle yourself — or to share one session across several specs — create the engine explicitly and inject it:

from chdb.agents import ChDBTool
from llama_index.tools.chdb import ChDBToolSpec

engine = ChDBTool("analytics_dir", read_only=False)
spec = ChDBToolSpec(engine=engine)
...
engine.close()

spec.close() closes only an engine the spec created itself.

This package is maintained by the chDB team.