Skip to main content
Use Case · DSPy

DSPy optimizes your prompts. Civic scopes your data access.

DSPy compiles and optimizes LLM programs. Civic makes sure the data they access during optimization stays within bounds.

use case / dspy

The optimizer pulled training data from the production database. Including PII.

Just imagine, one day…

You build a DSPy program that generates customer support responses. You set up a teleprompter to optimize the prompts against a training set. The training set connects to your database to pull real support tickets for few-shot examples.

The database query has no table restrictions. The optimizer pulls tickets from every table it can access, including a table with customer PII: names, emails, phone numbers. The optimized prompts now contain real customer data embedded as few-shot examples. You deploy the program. Customer PII is baked into every prompt.

Prompt optimization with unrestricted data access doesn't just leak data. It embeds it in every future call.

Without scoped access, optimization pulls data from every table it can reach.

It does things you did not intend

You wanted support ticket examples. The optimizer also pulled customer PII and embedded it in optimized prompts as few-shot examples.

You cannot prove what happened

Which tables were queried during optimization? Which rows ended up in the prompts? Without audit logs, you're reverse-engineering compiled prompts.

You cannot stop it fast enough

The PII is in the compiled prompts. Every call to the optimized program sends customer data to the LLM. Removing it means recompiling from scratch.

It gets confused and you never know

Customer profiles and support tickets are in the same database. The optimizer saw both as valid training data.

Connect DSPy through Civic in three steps

DSPy Agent

Add training database.

Allow queries on support_tickets only.

Make customer_profiles invisible.

Done. 1 tool connected:

✓ Database — support_tickets only

Your MCP URL and token are ready to copy.

The same scenario. Different outcomes.

Without Civic, the optimizer queries every table. With Civic, PII tables are invisible.

$ python optimize.py
[dspy] running teleprompter...
[db:read] support_tickets — 5,000 rows
[db:read] customer_profiles — 12,000 rows
[dspy] ✘ PII in optimized prompts
$ # customer data baked into every prompt.
$ python optimize.py
[dspy] running teleprompter via Civic...
[db:read] support_tickets — 5,000 rows
[nexus] customer_profiles — not in scope
[dspy] optimization complete. no PII.
$ # prompts optimized. no customer data included.

Ship safer with Civic

We'll help you implement authenticated, scoped, and auditable access without slowing down your build.