Datastores (SQL, MongoDB, Redis, Firestore, DynamoDB)
Skip the API. Point appctl at a datastore URL and it gives the agent CRUD
tools directly against tables, collections, keys, or documents.
Prerequisites
Section titled “Prerequisites”- A datastore connection string.
appctlinstalled.
Run it
Section titled “Run it”appctl sync --db "postgres://reader:pass@db.acme.com:5432/shop" --force
# orappctl sync --db "mysql://reader:pass@db.acme.com:3306/shop" --force
# orappctl sync --db "sqlite:///Users/you/dev/shop.db" --force
# orappctl sync --db "mongodb://127.0.0.1:27017/shop" --force
# orappctl sync --db "redis://127.0.0.1:6379" --force
# orappctl sync --db "firestore://my-gcp-project" --force
# orappctl sync --db "dynamodb://us-east-1" --forceFor every supported backend, the sync produces the same five logical tools:
list_*, get_*, create_*, update_*, and delete_*.
- SQL sources generate typed CRUD tools per table and execute them as prepared statements. Table and column names that clash with reserved words (for example SQLite’s
order,user, orgroup) are quoted in generated SQL solist_orderand similar tools work. - MongoDB generates CRUD tools per collection, keyed by
_id. - Redis generates a generic
redis_keyresource backed by key/value operations. - Firestore generates CRUD tools per top-level collection and uses Google ADC at runtime.
- DynamoDB generates CRUD tools per table and uses the normal AWS credential chain.
The local demo in this repo
Section titled “The local demo in this repo”examples/demos/db-postgres/ starts Postgres 16 in Docker with a single widgets table and a seed row.
1. Start it
Section titled “1. Start it”cd examples/demos/db-postgresdocker compose up -dsleep 4docker exec db-postgres-db-1 psql -U appctl -d appctl_demo -c "SELECT * FROM widgets;"Real output:
id | name | created_at----+------+------------------------------- 1 | demo | 2026-04-21 11:34:11.526835+00(1 row)2. Sync
Section titled “2. Sync”appctl sync --db "postgres://appctl:appctl@127.0.0.1:5433/appctl_demo" --forceReal output:
Synced Db: 1 resources, 5 tools written to .appctlGenerated tools:
widget: list_widgets, get_widget, create_widget, update_widget, delete_widget3. Inspect a generated tool
Section titled “3. Inspect a generated tool”{ "name": "list_widgets", "verb": "list", "transport": { "kind": "sql", "database_kind": "postgres", "table": "widgets", "operation": "select", "primary_key": "id" }, "safety": "read_only", "provenance": "declared"}4. Stop
Section titled “4. Stop”docker compose down -vAuth notes
Section titled “Auth notes”- Firestore: run
gcloud auth application-default loginfirst.appctluses Google ADC to call the Firestore REST API. - DynamoDB: export AWS credentials, use an AWS profile, or point at local DynamoDB with
dynamodb://us-east-1?endpoint=http://127.0.0.1:8000. - MongoDB / Redis: standard URI auth works through the connection string.
Staying safe
Section titled “Staying safe”- Use a read-only account. Create a Postgres role with only
SELECTon the tables you want to expose. - SQLite is local by nature. Prefer a copy of the DB for experiments if you do not want agent mutations to hit your live file.
- Or run with
--read-only. That flag blocks thecreate_*,update_*, anddelete_*tools at theappctllayer even if your DB role could perform them.
Known limits
Section titled “Known limits”- The SQL tools use prepared statements against the table and primary key. There is no free-form raw SQL tool in this source.
- Only single-column primary keys are modeled today.
- Views and materialized views are not introspected.
- Stored procedures are not auto-registered.
- Multi-schema databases only expose the default schema unless the connection string selects one.
- Redis support is generic key/value access, not a schema-aware hash/stream model.
- Firestore and DynamoDB use document/item payloads rather than per-column typing.