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.

WhoPlatform, security and risk teams
You needThe private blueprint, 1.3.0
CostsA small Cloud Run service per team

What has been tested

PartTested
Hosted server on Cloud Run, three identities, the audit tableLive in a private-blueprint environment, with Claude Code
Refusals and bypass attemptsLive: rows refused by the tool and, around it, by IAM (403 on every route); engineers cannot impersonate the server or aggregates identities
Aggregates under rulesLive: a label’s balance returned; small groups suppressed
Certified configuration in CILive in GitHub Actions on a pull request
EV-16 in an evidence pack, Fleet View’s AI agents pageLive, against the real Data Access audit logs
Plan explainerLive on real Terraform plans
Guardrail advisorTested against recorded perimeter violations; the live environment had none to advise on
Hosted server on private GKEUnit 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

IdentityWho acts as itWhat it can do
<prefix>-<team>-agentthe team’s engineers, for the local pipewright mcplook: schemas and row counts, runs, models, feature definitions, schedule and alert plans, the manifest and contracts. No table data, no changes
<prefix>-<team>-mcpthe hosted server only; nobody can impersonate itthe same looks, and writing the audit rows
<prefix>-<team>-aggthe hosted server only, for profilereading 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.

ConnectionHowWhen
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
Proxygcloud run services proxy <prefix>-mcp-churn --project <project> --region <region> --port 8765, kept running; it signs each request as youingress: internal reached through the proxy; needs the cloud-run-proxy gcloud component
GKEkubectl port-forward to the team’s service, with the ID token; the server verifies itruntime: 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

ToolOn the hosted server
environment, explain, inspect_table, list_features, runs, retrain_listas in open source, as the server’s identity
sample_rowsalways refused
profileaggregates under the platform’s rules, below
bootstrap_usecasethe 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 tableDataRead by 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 check fails 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.