DEV Community

Herbert
Herbert

Posted on • Originally published at puppyone.ai

How a Logistics Team Plugged AI Into Their Warehouse DB

How to plug AI into a database safely (without touching the DB)


Their shipment data had lived in Postgres for ten years. The board wanted AI on it by Q3. Their first instinct was also the thing keeping the data lead awake at night: give the model the connection string.

The 3 a.m. question every logistics digital lead asks in 2026

We met them as a 50-truck freight forwarder with a very ordinary warehouse stack—an ai for logistics database story if there ever was one.

One Postgres instance. Ten years of habits. Four tables everyone knew by name: shipments, customers, fleet, billing.

The business request sounded simple:

  • Customer service wanted faster “where is my shipment?” answers.
  • Dispatch wanted post-mortems that didn’t take a day.
  • Ops wanted SLA warnings before a missed ETA became a phone call.

The data lead had two problems, and neither was theoretical.

  1. “I don’t know how to connect AI to a database.”
  2. “I’m not handing an LLM a connection string.”

So we did what teams do when the stakes are high. We listed the obvious options, then ruled them out one by one.

The three things we ruled out — and the exact reason

1) Just give the agent a DB CLI

What it looks like: create a read-only database user, point an agent at psql, and let it write SQL.

How it fails:

  • “Read-only” is a role concept. The model doesn’t feel the risk. It will happily generate a query that’s logically wrong even if it can’t write.
  • Restricting to SELECT doesn’t prevent an outage. A Cartesian join or a bad filter can still torch performance.
  • Prompt injection is real. Security researchers have documented “prompt-to-SQL injection attacks in LLM-integrated applications” in the wild (ICSE/ACM, 2025). A malicious instruction that slips into the agent’s context can steer it toward unsafe output.

Verdict: reads safely until it doesn’t.

2) Build a custom API in front of the DB

What it looks like: create endpoints per table or query (/shipments/{id}, /customers/search), write an OpenAPI spec, and let the model call the API instead of SQL.

How it fails:

  • The spec becomes a product. Somebody owns it. Somebody maintains it.
  • Schema changes now touch three places: tables, endpoints, and the descriptions the agent depends on.
  • Every new agent (support agent, dispatch agent, compliance agent) pushes you toward another round of endpoints.

Verdict: you don’t have a logistics product anymore. You have an API team.

3) Bolt on yet another DB → MCP server

What it looks like: deploy middleware that exposes the database through an MCP server. The agent talks MCP; the server talks to Postgres.

How it fails:

  • It’s another layer to buy or build: SSO, monitoring, audit, patching.
  • The MCP server still holds production credentials. If that layer is compromised, the database is still exposed.
  • It doesn’t solve schema drift. It just changes where the drift shows up.

Verdict: another vendor in the path. The risk is still on the database.

Key takeaway: All three “obvious” solutions change the middle layer. None of them change the blast radius. They still let the AI touch the database.

How to plug AI into database safely: a DB sandbox + a CSV folder

A DB sandbox on your warehouse DB — sync views to CSV in a folder, AI stays in the sandbox.

“Sandbox” is overloaded, and that matters here.

  • One meaning is infrastructure: where code runs (Docker vs Cloudflare and so on). If you want that layer, see puppyone sandbox: Docker vs Cloudflare.
  • The other meaning is data blast radius. That’s the sandbox this post is about.

The pattern that shipped had three layers. It’s the same idea behind the warehouse database ai integration phrase people keep searching for, just implemented with a smaller blast radius.

Some teams call this a db sandbox for ai. The label matters less than the boundary.

Three-layer pattern: views → CSV folder → agent reads files (no DB credentials)

Layer 1 — In the database: read-only views

They didn’t expose tables. They exposed views—specifically read-only views for ai agents.

In Postgres, that meant an analytics schema with a small set of curated surfaces. One example:

CREATE VIEW analytics.shipments_recent AS
  SELECT id, status, origin, destination, eta, updated_at
  FROM shipments
  WHERE updated_at >= now() - interval '90 days';
Enter fullscreen mode Exit fullscreen mode

Two design rules made these views act like a contract:

  • If a column was PII, it didn’t enter the view.
  • If a column was “prod-only” (useful to humans, dangerous to leak), it didn’t enter the view either.

This isn’t a novel idea; it’s a boring one, and boring is good. Many database security guides recommend least privilege, and views are a common way to restrict surface area and abstract underlying tables. Some systems even support explicit column restrictions at the view/table level (see Teradata’s docs on restricting access by column in a table or view).

One more boundary mattered: the customer’s DBA owned this layer. The workspace never touched the DB.

Layer 2 — Nightly ingest: views → CSV → workspace folder

A small ingest script was the only thing allowed to talk to Postgres. That’s the whole point of ai without database credentials.

It ran on their side (on-prem cron or CI). It used the read-only user to export each view, then pushed the output into a folder—a csv folder ai agent contract, not an API surface.

Illustrative skeleton:

set -euo pipefail

OUT=out
mkdir -p "$OUT"

for view in shipments_recent shipments_late fleet_status customer_billing; do
  psql -U ai_readonly -c "\\copy analytics.$view TO '$OUT/$view.csv' CSV HEADER"
  # write into the workspace folder (illustrative)
  puppyone fs write /warehouse/views/$view.csv --from $OUT/$view.csv
done

puppyone fs write /warehouse/index.md --from $OUT/index.md
Enter fullscreen mode Exit fullscreen mode

Two guardrails are doing most of the work:

  • The script is a single, auditable integration point. If they ever want to stop the flow, they stop the cron.
  • The write permission is scoped. The ingest can write to /warehouse/views/. It can’t spray files elsewhere.

If you’ve lived through “RAG sprawl,” this will feel familiar. The point is to make the contract boring.

Layer 3 — The agent: reads a folder, not a database

The agent never sees a host, a port, a password, or even the fact that Postgres exists.

It only sees:

  • a folder of CSV snapshots (your shipment data ai context snapshot)
  • an index.md that explains what’s in the folder
  • a scoped Access Point that allows read operations and nothing else

When the agent needs to access the workspace, it does so through an explicit interface (MCP is one of them; see MCP).

What it looks like inside the workspace

The folder

Inside their workspace, the contract looked like this:

/warehouse/
├── views/
│   ├── shipments_recent.csv      # last 90 days, 12 cols, ~40k rows
│   ├── shipments_late.csv        # SLA breach > 0, refreshed nightly
│   ├── fleet_status.csv          # truck_id → last_seen, fuel, status
│   └── customer_billing.csv      # invoice header, NO line items
├── index.md                      # what each CSV is, schema, freshness
└── CHANGELOG.md                  # version history auto-fills
Enter fullscreen mode Exit fullscreen mode

The reason this is a folder and not “another database” is that agents need something humans can inspect, diff, and roll back.

A folder plus Markdown gives you an agent-readable map. That’s the argument in Why agents need a workspace (not another filesystem trick).

The index.md (the map)

The index.md did what database introspection never does for an LLM: it explained intent.

A minimal example:

# Warehouse views

## shipments_recent.csv
Purpose: Customer-service lookups and weekly SLA review.
Freshness: nightly at 02:00 local time.
Schema:
- id (uuid)
- status (text)
- origin (text)
- destination (text)
- eta (timestamp)
- updated_at (timestamp)
Caveats:
- excludes cancelled shipments
- origin/destination are normalized codes, not raw addresses
Enter fullscreen mode Exit fullscreen mode

Agents don’t need more tables. They need a map.

The Access Point

The agent got an Access Point scoped to /warehouse/views/ with read-only mode.

If you want the mechanics of that boundary—what tools can be allowed, what “scope” really means—start at Agent auth.

The important part is what the agent did not get:

  • no Postgres URI
  • no SSH key
  • no VPN creds
  • no “just this once” admin token

Why this answers both pains — at once

They didn’t “connect AI to the DB.” They moved the problem.

  • The integration problem became: “export views to files.”
  • The safety problem became: “the agent can’t touch the database.”
Original pain Layer that resolves it
“We don’t know how to connect AI to a DB” Layer 2 — there’s no connection. The agent reads files.
“I’m terrified the agent will drop a table” Layer 1 + Layer 3 — the agent has no DB credential at all.
“We don’t want a fragile API team” The CSV folder is the contract. Schema change = re-run ingest.
“We can’t trust audit on this” Workspace access can be logged; context changes can be versioned and rolled back.

That last row is where this starts to feel like a real production pattern.

If you’re running multiple agents, audit and rollback aren’t “nice-to-haves.” They’re how you sleep.

The longer read is From isolated team agents to a unified enterprise agent harness.

Side-by-side: the four options

This is the table the data lead saved. It’s the fastest way to explain the logistics ai use case to security and operations in one page.

Direct DB CLI Custom API DB → MCP DB sandbox + CSV folder
Agent holds DB credential yes no no (MCP does) no
Risk of destructive SQL high low low none
Effort to add a new agent re-grant DB role new endpoints new MCP scope re-use folder, new Access Point
Schema drift handling breaks queries breaks contract breaks tools re-run ingest
Audit trail DB logs only API logs MCP logs workspace version + audit
Rollback bad context DB restore n/a n/a workspace rollback
Real-time freshness yes yes yes nightly / hourly (trade-off)
Setup time 1 day, scary 4–8 weeks 1–2 weeks a weekend

When this pattern does NOT fit

This isn’t “always do this.” It’s “ship safely when you’re scared.”

It’s the wrong pattern when:

  • You need sub-minute freshness. That’s a streaming / materialized view problem.
  • Your data is TB-scale. CSV stops being kind. Move to Parquet or a warehouse-native approach.
  • The agent must write back into the database. Write-back should be a different door with explicit approvals.
  • You only have one or two stable queries. A dashboard might be the right tool.

The point of this post isn’t that a CSV folder beats a database. It’s that when you’re scared of plugging AI into your DB, you can change the blast radius and ship anyway.

The template: tpl-logistics-db template

They packaged the pattern as a small template they could copy between environments:

  • views.sql — a recommended Postgres view skeleton
  • ingest.sh — a nightly script (views → CSV → folder)
  • /warehouse/ directory skeleton
  • index.md template with placeholders for freshness, schema, and caveats

If your team already thinks in terms of governed context, this slots naturally into a Context Base.

See the Context Base page for how teams organize these snapshots so agents can use them without turning your data stack into a science project.

FAQ

1) Why CSV and not Parquet or JSON?

CSV is the lowest common denominator: humans can open it, and models read it fluently. Parquet is a better choice once size becomes the bottleneck—Dremio’s piece on evolving from CSV/JSON to Parquet explains the trade.

If you want a practical performance view, DuckDB’s benchmark-y essay on CSV vs Parquet (2024) is a good sanity check.

2) Why not just give the agent a vector DB?

That’s a different problem. Vector retrieval is great for fuzzy semantic matching. Shipment lookups and SLA slices are structured questions.

The longer answer is in Vector database vs Context Base.

3) How does the AI know which CSV to read?

index.md. It’s the table-of-contents the workspace serves. The agent reads it first, then chooses the right snapshot.

4) Doesn’t a nightly sync mean stale data?

Yes. That’s the trade-off you’re paying for safety.

Run it hourly. Run it every 15 minutes. Trigger it on events if you need tighter freshness. Just keep the boundary: the agent still reads files.

5) What about multi-agent setups (dispatcher + customer-service + analytics)?

Give each agent its own Access Point, scoped to the smallest folder it needs.

If you’re evaluating multi-agent setups more broadly, start at Hermes agent vs agent harness: enterprise needs.

6) Can the agent write back to the DB?

Not with this pattern. That’s intentional.

Write-back is a different door: explicit permissions, approvals, and a narrower interface. This post is about getting AI on the data without gambling the database.

Next steps

If you’re trying to make this pattern repeatable across teams—same folder contract, different data sources—start by formalizing your context layer.

  • Explore how a Context Base organizes governed snapshots: Context Base
  • If you need self-hosted or VPC deployment, see Open source

(For readers searching for the “puppyone db pattern”: the important idea isn’t the brand. It’s the boundary—agents get files, never the DB.)

Top comments (0)