Optional integration with the ellmer package. Given an ellmer
Chat object and one or more oRm models (or an Engine),
register_db_tools() registers a small set of generic CRUD tools onto
the chat so the LLM can read, create, update, and delete rows. The chat is
modified in place (ellmer Chat objects are reference objects) and returned
invisibly.
Arguments
- chat
An ellmer
Chatobject (e.g. fromellmer::chat_anthropic()).- ...
One or more
TableModelobjects to expose, and/or a singleEnginewhose tables are reflected automatically viaEngine'sreflect_schema().- tables
Optional character vector limiting which tables to reflect when an
Engineis supplied. Ignored for explicitTableModels.- exclude
Optional character vector of table names to skip when an
Engineis supplied.- max_rows
Integer. Maximum number of rows
db_readreturns to the LLM. Defaults to 100.
Details
The registered tools are table-parameterised rather than model-specific:
db_read(table, filter)Read rows.
filteris an optional dplyr-style filter expression supplied as a string, e.g."age > 30 & name == 'Kent'". Results are returned as JSON.db_create(table, values)Insert a row.
valuesis a JSON object of column/value pairs, e.g.'{"name":"Kent","age":35}'.db_update(table, filter, values)Update matching rows. A
filteris required.db_delete(table, filter)Delete matching rows. A
filteris required.
The schema (tables and their columns) is embedded in each tool's description so the LLM can discover what is available without an extra round-trip.
Filter expressions are translated to SQL by dbplyr via oRm's existing
read/update/delete machinery, so the LLM can lean on its familiarity with
dplyr. Filters are parsed and evaluated in a minimal environment (a child of
baseenv()) so they cannot reach objects in the caller's workspace.
Write permissions are governed entirely by the Engine: open it with
.read_only = TRUE to make db_create/db_update/
db_delete fail with the engine's read-only error (which is returned to
the LLM). There is no separate permission layer here. Because the agent acts
with the caller's database privileges, prefer a read-only engine when exposing
a chat to untrusted input.
Examples
if (FALSE) { # \dontrun{
library(ellmer)
engine <- Engine$new(RSQLite::SQLite(), dbname = ":memory:", persist = TRUE)
User <- engine$model(
"users",
id = Column("INTEGER", primary_key = TRUE),
name = Column("TEXT"),
age = Column("INTEGER")
)
User$create_table()
chat <- chat_anthropic()
register_db_tools(chat, User)
chat$chat("Add a user named Kent who is 35, then list everyone over 30.")
} # }