Databricks Field Guide

Generative AI · Chapter 28

Governed Actions

This chapter describes a gap in the standard lakehouse governance story and the way TechFabric fills it. It is the most opinionated chapter in the manual, and it is the one that most often changes how a client's architecture review goes.

The short version

Every major cloud platform is good at controlling who can read which data, and none of them controls what a system is then allowed to do about it. Those are different questions, and the second carries the business risk, because reading a customer's balance harms nobody while issuing a refund or cancelling a policy has consequences no data permission model inspects. Once software driven by a language model starts taking actions rather than producing text, the organisation needs a layer that checks each proposed action against written rules before it happens, records the decision for later audit, and guarantees the action either completes fully or not at all. That is what we build, and our rule is that the model proposes and never acts.

The gap #

Unity Catalog governs data access with real rigour. It knows who may read a table, which columns they may see, and which rows are visible to them, and it records every access. We rely on it completely, as Unity Catalog describes.

It says nothing about actions. When a system reads a customer's account, decides that a payoff quote should be regenerated, and calls an API that regenerates it, no data access policy has been violated. The read was permitted, and the write happened somewhere else entirely, in a system of record that Unity Catalog does not govern and cannot see.

For traditional analytics this gap does not matter, because analytics reads and does not act. For agentic systems it is the entire risk surface.

What an action layer has to provide #

Four things, and a data access model provides none of them.

A decision before the effect. Every proposed action is evaluated against policy before anything happens, and the evaluation returns pass, warn, or block. Warn is not a courtesy; it means the action may proceed but something about it is notable and must be recorded. Allow-and-deny systems force every ambiguous case into one of two buckets, and the ambiguous cases are the interesting ones.

A corrective path when the answer is no. A block that says only that the action was denied pushes the human into guesswork. A useful decision names what should happen instead, whether a different action, a screen to send the operator to, or a manual step the system cannot perform.

Evidence. Every decision emits a record carrying the decision identifier, the revision of the policy bundle that produced it, and a hash of the inputs it saw. That triple lets you answer, months later, why the system did what it did, using the policy as it existed then. Without the bundle revision an audit judges last quarter's decisions by this quarter's rules and reaches the wrong conclusion confidently.

Durability. An action half-applied when a process dies is the worst outcome available, which is why these workflows run on a durable execution engine rather than in a request handler that a deployment can interrupt.

How we implement it #

The fabric.pro platform layer provides a policy evaluator backed by Open Policy Agent. Policies are authored as code, versioned, tested in CI, and shipped as a bundle whose revision identifier appears in every decision record. The OPA server is co-located with the workflow worker, so evaluation is a local call rather than a network dependency that can fail independently of the workflow needing it.

Execution runs on Temporal. A workflow admitted by policy survives worker restarts, deploys, and infrastructure failures, resuming at the step it reached rather than at the beginning. Every side effect is an activity with its own retry policy and idempotency key, so a retry after a timeout does not issue the refund twice. Fabric Harness, our Apache-2.0 TypeScript framework, is the client-side half of this.

The Databricks side of the boundary stays clean. An agent on model serving emits a structured proposal, meaning a typed object naming the action, its parameters, and the evidence justifying it. That proposal is evaluated and either executes durably or comes back with a reason. The agent never holds credentials for the system of record, so a prompt injection hidden in a retrieved document has nothing to steal.

pass

warn

block

Agent reads
governed data

Structured proposal

Policy evaluation
OPA bundle

Durable execution
on Temporal

Execute
plus flag for review

Corrective action
returned

System of record

Decision evidence
id, revision, input hash

Where the proposal stops and the governed pipeline begins

Where the evidence goes #

Decision records are written back to the lakehouse, so governance decisions about actions become governed data with the same retention and access controls as everything else. An auditor asking which automated decisions were blocked last quarter, and why, gets a SQL query rather than a project. The write path usually goes through Lakebase, since one row per decision is an operational write pattern rather than an analytical one.

Advanced: what a mature action layer does #

Most teams building in this space stop at an allow-or-deny check in front of a tool call. What follows separates that from a layer you would defend in a regulated audit.

Simulation against historical proposals. A bundle can be evaluated against a recorded stream of past proposals without executing anything, producing a diff of which decisions would change. That turns a policy edit from a leap of faith into a reviewable artefact, and it is what makes people willing to change policy at all.

Two-key and quorum actions. Some effects should require a second human, or a second system, above a threshold. Encoding that in policy rather than in application code makes the threshold versioned evidence rather than a constant somebody edited.

Compensation rather than rollback. A refund that has left the building cannot be rolled back, only compensated by a later action. Modelling every action with its compensating counterpart, inside one durable workflow, is what lets a multi-step business transaction fail safely at step four.

Time and rate scoping. Policies referencing how many actions of a kind were already taken today, by this agent, for this customer, catch the failure mode per-action checks miss entirely, which is a thousand individually reasonable actions.

Decision replay. Because the evidence record carries the bundle revision and an input hash, any historical decision can be re-evaluated against the current bundle to see whether today's rules would decide differently. That is how you answer a regulator asking whether a past harm is still possible.

Governing effects, not just access

Capability Databricks plus fabric.pro AWS Azure GCP
Who may read the data Unity Catalog, one model IAM plus Lake Formation Entra ID plus Purview IAM plus Dataplex
Whether an action may be taken Evaluated per proposal, pass, warn or block IAM grants API permissions to principals, not decisions about effects Not addressed Not addressed
Evidence tied to policy version decisionId, bundleRevision, inputHash CloudTrail records the call, not the policy revision behind it Activity log, same limitation Audit Logs, same limitation
Durable multi-step execution Temporal, with compensation Step Functions, durable, no policy layer Durable Functions or Logic Apps Workflows
Decisions queryable beside business data Written into the lakehouse Export and join it yourself Export and join it Export and join it

We want to be precise about that claim. IAM, Lake Formation, Purview, and Dataplex are good at what they do, and Step Functions is an excellent durable engine we would happily use. The narrow claim is that none of them evaluates a proposed business action against versioned policy and emits evidence of the evaluation, because it is not what they are for. IAM answers whether a principal may call an API, not whether this refund, for this customer, at this amount, is something the business agreed to do automatically.

The test we apply in design review #

Every call that leaves the platform and changes something is asked three questions, and a call site that cannot answer all three is not ready for production.

none

named bundle

none

decision record

no

idempotent activity

Effectful call

Which policy
admitted it

Move behind
the action pipeline

What evidence
was written

Safe if the
process dies

Ready for production

The three questions every effectful call has to answer

The technology is replaceable, since Open Policy Agent could be another evaluator and Temporal another durable engine without changing anything we have argued here. The boundary itself is not replaceable, and neither is the discipline of keeping every effect on the far side of it.