LangChain and LangGraph integration for Wren AI Core — attach a CLI-prepared Wren project to your agent in three lines.
Project description
wren-langchain
LangChain and LangGraph integration for Wren AI Core.
Attach a CLI-prepared Wren project to a LangChain agent in three lines:
from wren_langchain import WrenToolkit
from langchain.agents import create_agent
toolkit = WrenToolkit.from_project("./analytics_db")
agent = create_agent(
model="openai:gpt-4o",
tools=toolkit.get_tools(),
system_prompt=toolkit.system_prompt(),
)
Complete runnable demos:
examples/langchain_demo.py— useslangchain.agents.create_agent, the high-level factory. Smallest amount of code; recommended starting point.examples/langgraph_demo.py— builds the ReAct loop from LangGraph primitives (StateGraph+ToolNode+ conditional edges). Use this when you need custom routing, state, or streaming.
Prerequisites
This package assumes you have already used the Wren CLI to prepare a project:
wren context init
wren context build
wren memory index # optional but recommended
wren profile add ...
If you haven't installed the CLI yet, install wren-engine first:
pip install "wren-engine[memory,postgres]"
Installation
wren-langchain exposes datasource and memory extras that pass through to
the matching wren-engine extras, so you only have to install once:
# Match the datasource your wren_project.yml uses (DuckDB needs no extra):
pip install "wren-langchain[mysql]"
pip install "wren-langchain[postgres,memory]"
pip install "wren-langchain[bigquery,memory]"
# Available datasource extras: postgres, mysql, bigquery, snowflake,
# clickhouse, trino, mssql, databricks, redshift, spark, athena, oracle.
# `memory` extra enables the three memory tools (wren_fetch_context,
# wren_recall_queries, wren_store_query). Without it the toolkit exposes
# only the three runtime tools.
# Install everything for experimentation:
pip install "wren-langchain[all,memory]"
If you prefer to install wren-engine separately (e.g. you already use the
CLI), the bare package is enough and your existing wren-engine extras carry
over:
pip install wren-langchain
What you get
WrenToolkit.from_project(path) exposes:
- 6 LLM-facing tools (3 runtime + 3 memory when
.wren/memory/exists):wren_query— execute SQL through Wren's context layer, returns rowswren_dry_plan— plan SQL without execution to verify it targets models correctlywren_list_models— list project models with column counts and descriptionswren_fetch_context— retrieve relevant schema/business context for a questionwren_recall_queries— surface similar past NL→SQL pairs as few-shot exampleswren_store_query— persist a confirmed NL→SQL pair for future recall
- Direct Python API:
toolkit.query("SELECT ...") # → pyarrow.Table toolkit.dry_plan("SELECT ...") # → str (target-dialect SQL) toolkit.dry_run("SELECT ...") # → None (validation only) toolkit.memory.fetch("revenue trends") toolkit.memory.recall("top customers") toolkit.memory.store(nl="...", sql="...", tags=["..."])
toolkit.system_prompt()— Wren-aware system prompt that adapts to enabled tools and includes your project'sinstructions.mdwhen present.
Configuration
WrenToolkit.from_project(
path, # required — path to your prepared Wren project
profile="prod", # optional — picks a named profile (default: active)
)
toolkit.get_tools(
include_memory_write=True, # set False to keep memory read-only
raise_on_error=False, # set True to surface exceptions to LangChain retry
)
Memory is auto-detected from the project: present <path>/.wren/memory/
exposes the 3 memory tools alongside the 3 runtime tools; absent → only the
runtime tools. To enable, run wren memory index from the project root; to
disable, delete the directory. There is no override kwarg.
include_memory_write=False removes wren_store_query from the returned
list while keeping wren_fetch_context and wren_recall_queries. Use this
when you want the agent to read curated past pairs but never persist new
ones (e.g., a shared / pinned memory). When memory is disabled, this flag
has no effect — no memory tools are returned regardless.
How path, profile, and .env interact
Three pieces of state combine to produce a connection. Understanding which one drives what avoids surprises:
| Source | Holds | Resolved by |
|---|---|---|
path/wren_project.yml + target/mdl.json |
MDL models, schema, data_source |
from_project(path) |
path/.env |
Secret values (MYSQL_HOST, MYSQL_PASSWORD, …) |
from_project(path) auto-loads it |
~/.wren/profiles.yml |
Connection template (host: ${MYSQL_HOST}, …) |
profile= kwarg or fallback chain |
profile= resolution chain (highest priority first):
- Explicit
profile="<name>"kwarg passed tofrom_project. - The
profile:field inside the project'swren_project.yml, e.g.:schema_version: 3 data_source: mysql profile: test-project3 # locks this project to a specific profile
- The globally active profile (
wren profile switch <name>).
When does profile= actually change which database you connect to?
This is subtle, because profile values are templates that resolve from the
project's .env, not standalone connection records. Three scenarios:
Scenario A — profile= is a no-op (most common)
Your ~/.wren/profiles.yml has multiple profiles that all use the same
placeholder names:
profiles:
test-project3:
datasource: mysql
host: ${MYSQL_HOST}
database: ${MYSQL_DATABASE}
test-project4:
datasource: mysql
host: ${MYSQL_HOST} # ← same placeholder
database: ${MYSQL_DATABASE}
Because from_project("/path/to/test-project3") loads test-project3/.env
into the environment, both profiles resolve to the same connection —
${MYSQL_HOST} reads from project3's .env regardless of which profile
name you picked. Profile selection is cosmetic in this layout.
Scenario B — profile= selects different placeholders
profiles:
dev:
host: ${DEV_HOST}
prod:
host: ${PROD_HOST}
Now profile="dev" and profile="prod" read different env vars from the
same .env, so the choice matters.
Scenario C — profile= selects hardcoded values or different datasources
profiles:
local:
datasource: duckdb
url: /tmp/local.duckdb
format: duckdb
remote:
datasource: postgres
host: prod-db.example.com # hardcoded
port: 5432
profile="local" vs profile="remote" connect to genuinely different
databases. Note: if wren_project.yml specifies data_source: and you
pick a profile with a different datasource:, the connection will fail —
the project's MDL is built against one specific dialect.
Recommendation: one project, one profile
If you follow the common pattern of one Wren project per database
(each project gets its own .env and points at its own DB), set the
profile inside wren_project.yml and stop passing profile=:
# wren_project.yml
schema_version: 3
name: test-project3
data_source: mysql
profile: test-project3
toolkit = WrenToolkit.from_project("/path/to/test-project3")
This pins the project to its intended profile, no more "is the active
profile what I think it is?" — and it survives wren profile switch
elsewhere on the same machine.
Compatibility matrix
wren-langchain |
wren-engine |
langchain |
langgraph |
|---|---|---|---|
| 0.1.0 | >= 0.5.0 | >= 1.0 | >= 1.0 |
Known limitations (v0.1)
- Synchronous tools only. LangChain auto-bridges to a thread pool when tools run in async LangGraph; multi-tenant servers serving > ~32 concurrent users may exhaust the default executor pool.
- One toolkit per agent. If you need to query multiple Wren projects, build separate agents.
- Memory is auto-detected from
.wren/memory/and there is no kwarg to override. To enable, runwren memory index; to disable, delete the directory. - No hot reload mechanism.
target/mdl.jsonis re-read on every tool call, sowren context buildupdates from CLI are picked up automatically. Profile changes require constructing a new toolkit. - Don't run
wren memory indexwhile an agent is using the same project. The index operation drops and recreates the LanceDB schema table; concurrent reads may transiently fail.
License
Apache License 2.0. See LICENSE for the full text, or the repository-level LICENSE for the path-to-license map.
The names "Wren", "WrenAI", and the project's logos are trademarks of Canner, Inc. and are not licensed under Apache 2.0; their use is governed separately.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wren_langchain-0.2.0rc1.tar.gz.
File metadata
- Download URL: wren_langchain-0.2.0rc1.tar.gz
- Upload date:
- Size: 39.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5da8b434b648d5eaf7e6096caeec2f6b7922d58985f502024e1204fdb934878
|
|
| MD5 |
e2fb20aef51ec81fdce70177220564de
|
|
| BLAKE2b-256 |
da430917218867a035778f73a17bfa5ca16f09a4a5613bde03ff42a2373572fe
|
File details
Details for the file wren_langchain-0.2.0rc1-py3-none-any.whl.
File metadata
- Download URL: wren_langchain-0.2.0rc1-py3-none-any.whl
- Upload date:
- Size: 28.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d84b7d28e19f6ec01bda49def11942ab02c4b092e38b05ca73a5811e635796fa
|
|
| MD5 |
36ab44d14e89dbc1dc56e0dbd44f832c
|
|
| BLAKE2b-256 |
d5348a2c484802bb4b9ae4b9d9775ba7455daf76a49f23a41deddc3c78ebfe22
|