AI build assistance on Enterprise
The open-source tools make an agent safe to use. Pipewright Enterprise makes it provable to an organisation: who used an agent, what it saw, and that no row of the team’s data reached a model. One block in the platform file turns it on; without the block nothing changes.
What has been tested
| Part | Tested |
|---|---|
| Hosted server on Cloud Run, three identities, the audit table | Live in a private-blueprint environment, with Claude Code |
| Refusals and bypass attempts | Live: rows refused by the tool and, around it, by IAM (403 on every route); engineers cannot impersonate the server or aggregates identities |
| Aggregates under rules | Live: a label’s balance returned; small groups suppressed |
| Certified configuration in CI | Live in GitHub Actions on a pull request |
| EV-16 in an evidence pack, Fleet View’s AI agents page | Live, against the real Data Access audit logs |
| Plan explainer | Live on real Terraform plans |
| Guardrail advisor | Tested against recorded perimeter violations; the live environment had none to advise on |
| Hosted server on private GKE | Unit and Terraform plan tests only, not yet run on a cluster |
Turn it on
spec:
ai:
build_assistance:
enabled: true
runtime: cloud_run # or gke (needs spec.gke with kubeflow)
local_tools: forbidden # production: the hosted server only; allowed (default) elsewhere
server_image: <region>-docker.pkg.dev/<project>/<prefix>-images/pipewright-mcp-server@sha256:...
ingress: internal # default; all for test environments reached from laptops (IAM still decides)
min_instances: 0 # 1 keeps a server warm: agents time out on a cold start
data_classes:
aggregates: { allowed: true, min_group_size: 10 } # off by default; at least 5
deny_names: ["*ssn*", "*salary*"] # names agents never see
offline: false # true: no live tools at all
certified_agents: [claude-code, gemini-cli]
approved_models:
- projects/<ai project>/locations/<region>/publishers/anthropic/models/<model>
tenants:
churn:
ai: { engineers: ["group:churn-eng@example.com"] }
Two applies on the first build, like the launcher. The first creates the identities, the audit table and the grants, with server_image: null. Push the image with scripts/publish_image.sh <images repository> mcp-server --build, set its digest, and apply again for the servers. Plan, read the plan, then apply: pipewright platform explain-plan below helps with the reading.
Three identities per team
| Identity | Who acts as it | What it can do |
|---|---|---|
<prefix>-<team>-agent | the team’s engineers, for the local pipewright mcp | look: schemas and row counts, runs, models, feature definitions, schedule and alert plans, the manifest and contracts. No table data, no changes |
<prefix>-<team>-mcp | the hosted server only; nobody can impersonate it | the same looks, and writing the audit rows |
<prefix>-<team>-agg | the hosted server only, for profile | reading the team’s dataset; the server applies the group rules before anything leaves it |
The blueprint also creates a custom role for platform metadata, the ai_tool_calls table in the evidence dataset (with your key), one Cloud Run service per team with run.invoker for its engineers, a perimeter ingress rule for engineers and agent identities, and the ai rules and each team’s agent_server in the manifest.
Connect an agent
Write the certified configuration once and commit it, so every engineer and CI use the same one:
pipewright agent-config write --env prod --agent claude-code --tenant churn --direct
pipewright agent-config check --env prod --agent claude-code
That writes .mcp.json and .claude/settings.json (or .gemini/settings.json): the hosted server, Pipewright’s read-and-verify commands pre-approved (validate, doctor, review, context build and others), and data commands denied (bq query, bq head, gcloud storage cat and others). Commands that change Google Cloud are never pre-approved: release, run, approve, deploy, sync and erase always ask a person. With an approved model, Claude Code is pointed at it on Vertex AI.
| Connection | How | When |
|---|---|---|
Direct (--direct) | the service’s URL with your ID token in a header: export PIPEWRIGHT_ID_TOKEN=$(gcloud auth print-identity-token) | inside the network, or an environment with ingress: all. Tested live |
| Proxy | gcloud run services proxy <prefix>-mcp-churn --project <project> --region <region> --port 8765, kept running; it signs each request as you | ingress: internal reached through the proxy; needs the cloud-run-proxy gcloud component |
| GKE | kubectl port-forward to the team’s service, with the ID token; the server verifies it | runtime: gke |
pipewright mcp --env prod --tenant churn --print-config prints the right settings for the environment, with the token or proxy command to run.
What the hosted server does
| Tool | On the hosted server |
|---|---|
environment, explain, inspect_table, list_features, runs, retrain_list | as in open source, as the server’s identity |
sample_rows | always refused |
profile | aggregates under the platform’s rules, below |
bootstrap_usecase | the server has no copy of your repository, so it answers with a skeleton command (pipewright new-usecase ... --from minimal) and only the drafted files that differ from it, for the agent to write over the skeleton |
validate, doctor, review and context build run on the command line, from the repository root; the context pack for a hosted environment says so, and the certified settings pre-approve them.
Aggregates under rules
- Rows, null rate and distinct count of a column; counts per value only for groups of at least
min_group_size, the rest reported as suppressed. - The 5th and 95th percentiles only from at least 20 times the minimum group size; never a raw minimum or maximum.
- Never on withheld, policy-tagged or personal-looking columns, and only on the team’s own and feature datasets. An identifier-like column (
customer_id,uuid) gets rows, null rate and distinct count only: never values or percentiles, which would be real identifiers. - At most 10 GiB billed per query, run as the aggregates identity, which only the server can act as.
The audit
Every call, refused and failed ones too, is a row in ai_tool_calls: time, team, the caller (from the verified ID token), the agent’s name (as its client sent it), the tool, the data class and the outcome. Never values. If the row cannot be written, the call is refused: no audit, no answer.
Proof for risk and audit
- EV-16 in every evidence pack: no BigQuery
tableDataReadby the team’s agent or server identity in 90 days, from the Data Access audit logs, with the hosted server’s calls by data class and outcome. Reads by the aggregates identity are listed separately, as the rules allow them. It says what it cannot show: what an agent sent to its model, or data a person pasted by hand. - Fleet View, Platform > AI agents: the rules per environment, and every call per team in 30 days, refusals included. The evidence matrix has an EV-16 column.
- Certified configurations in CI:
pipewright agent-config checkfails a pull request whose committed configuration loads a data-reading MCP server, leaves data commands open, pre-approves a change, or uses a model outside the approved endpoints.
# in the pull request workflow, after the check job
- name: Certified agent configuration
run: |
pip install "pipewright-enterprise==1.3.0"
pipewright agent-config check --env "$ENV" --agent claude-code
The platform kit
For platform teams working with an agent on the platform repository:
pipewright platform context build --config platform.yaml # PLATFORM_CONTEXT.md, four playbooks, pointer blocks
pipewright platform context check --config platform.yaml # CI: fails when stale
terraform show -json plan.tfplan > plan.json
pipewright platform explain-plan plan.json # findings; exit 1 on a danger finding
pipewright platform guardrails --config platform.yaml --project <project>
The plan explainer flags data destroyed (keys, key rings, buckets, datasets, tables, registries, clusters), guardrails removed or no longer enforced, perimeter changes, a grant removed and re-added in one apply, authoritative IAM, ingress opened to all and deletion protection turned off. It reads the plan; a person still decides.
The guardrail advisor reads VPC Service Controls dry-run violations and proposes identity-bound perimeter rules, only for callers the platform file names, the project’s own service accounts and Google service agents; anyone else is listed for a person to look into. It has been tested on recorded violations, not yet on a live perimeter’s.
Limits
- A person can still paste data into a conversation by hand: policy, training and certified configurations cover that, not IAM.
- The agent’s name in the audit is what its client says. The caller is proven; the agent is not.
- On GKE, RBAC cannot narrow port-forwarding to one team’s pods. An engineer could reach another team’s server in the namespace; it still acts as its own team’s metadata-only identity, and the audit names the engineer. Use Cloud Run where that matters.