An agent that queries your database needs two things the schema does not give it: what each column means, and who is allowed to see it. Most teams put both in the system prompt. A prompt is a request. It is not a control.
Key points
- A semantic layer holds business meaning and access rules, and it belongs next to the data.
- Postgres already has the primitives: comments, views, foreign keys, grants, row-level security.
- The gateway decides which tools run. The database decides which rows and columns come back.
Why business logic in a prompt fails
Column names hide meaning. purchases.price reads like a unit price. In the reference dataset it is the order total. An agent that multiplies it by quantity reports $502,529 for the top customer instead of $27,991.66 — roughly an 18x error from one misread column. A comment on that column fixes it permanently, for every agent and every dashboard that reads the table.
Security instructions have the same weakness. "Never show SSNs" is advice. The model may follow it, misread it, or be walked around it by a cleverly worded question. In October 2026, the AWS Machine Learning blog published a walkthrough that moves both meaning and rules into Postgres itself, using EDB Postgres AI's AIDB extension with an agent running on Amazon Bedrock AgentCore (AWS Machine Learning blog).
The intern and the badge
An intern is sent to the records room. The old way: the manager hands over a sticky note reading "don't open the salary drawer." The new way: every folder carries a label, and the drawers only open for the intern's badge.
Labels are COMMENT ON statements. The badge is the Postgres role. The drawers that stay shut are GRANT and row-level security. An intern can forget a sticky note. A cabinet does not forget a badge.
What the layer looks like inside Postgres
Four tables and one view in a c360 schema carry a customer-360 dataset. Three business ideas get written down once:
- State lives in
locations, reached through a foreign key fromcustomers.location. A comment says so. purchases.priceis the order total. A comment says so.- "Big spender" is a view with its own comment, so every consumer reads one definition.
AIDB indexes the schema and the definitions together into a semantic knowledge base, and turns foreign keys into join paths, so the agent stops guessing how tables connect. It then exposes the catalog as an MCP endpoint — the tool interface agents already speak.
Same prompt, same tool catalog, same agent code, two roles. The answers differ because Postgres enforces the difference. Traces land as rows in aidb_otel, so auditing is a SQL query rather than a screenshot from a dashboard.
Where the boundary actually sits
This is the part teams blur. AgentCore Gateway validates the token and applies a Cedar policy to decide which tools a caller may invoke. It does not decide which rows come back. It cannot, because the model writes the SQL. Any control that sits above the query can be routed around by a different query.
Split it explicitly: the gateway controls the verbs, the database controls the nouns.
What to do
- Take the table your agents query most and add
COMMENT ONstatements for the columns whose names mislead. Re-run your eval set and count how many answers change. - Create a read-only role, grant columns explicitly, and add a row-level security policy for tenant or region.
- Add a governance test: ask one sensitive question as two roles and assert the results differ. If they do not, your guardrail is still in the prompt.
