A Pydantic AI capability for chDB, the in-process ClickHouse engine: give agents analytical SQL over local files, object storage, and remote databases — no server to start, no connection string, no credentials.
pip install pydantic-ai-chdbfrom pydantic_ai import Agent
from pydantic_ai_chdb import ChDBCapability
agent = Agent(
"openai:gpt-4o-mini",
capabilities=[ChDBCapability(attachments={"events": "data/events.parquet"})],
)
result = agent.run_sync("What are the top 5 event types by count?")
print(result.output)The capability registers the chDB tool suite — run_select_query (read-only ClickHouse SQL with {name:Type} parameter binding), list_databases, list_tables, describe_table, get_sample_data, list_functions, and (on writable sessions) attach_file — plus schema-first usage instructions for the system prompt. Tool names and descriptions come from the descriptors bundled with the chdb package, its single source of truth across bindings.
The capability's on_tool_execute_error hook maps typed chdb.agents.errors.ChDBError failures to ModelRetry, so the model sees the engine's error type, code, and message —
chDB UNKNOWN_IDENTIFIER (code 47): Unknown expression identifier `SELEC` ...
— and corrects the query within the agent's retry budget instead of the run dying on an exception. Non-chDB errors propagate unchanged.
- Read-only by default. Sessions are locked with the ClickHouse
readonly=2setting:INSERT/CREATE/ALTER/DROPare rejected by the engine whileSELECTand thefile()/s3()/url()table functions keep working. Passread_only=Falsefor a writable session (this also exposesattach_file). - Capped results.
max_rows(default 1000) andmax_bytes(default 1 MB) bound every payload; truncated results carry atruncatedflag.max_execution_timeadds 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.
To control the engine's lifecycle yourself — or to share one session across capabilities and other chDB bindings — create it explicitly and inject it:
from chdb.agents import ChDBTool
from pydantic_ai_chdb import ChDBCapability
engine = ChDBTool("analytics_dir", read_only=False)
capability = ChDBCapability(engine=engine)
...
engine.close()capability.close() closes only an engine the capability created itself.
Spec-based construction works out of the box: ChDBCapability.from_spec(path="analytics_dir", read_only=True).
Requires Pydantic AI V2. This package is maintained by the chDB team.