AI build assistance
Build and change use cases with the coding agent your team already uses: Claude Code, Gemini CLI, or any agent that speaks the Model Context Protocol (MCP). The agent writes, Pipewright checks, a person decides. Everything on this page is in the open-source core from Pipewright 1.3.0, additive, and off until you use it.
The flow
intent "train a churn model every Monday from retail_entities, email me when a run fails"
-> the agent reads the context pack (APP_CONTEXT.md) and a playbook
-> it learns the environment through Pipewright's tools: metadata only, never rows
-> it drafts YAML on a branch; validate and doctor pass, judgement checks explained
-> it opens a pull request with the review bundle (pipewright review)
-> a person approves and merges; CI releases; a person approves the model
Three things make it safe, and each is enforced somewhere other than the agent’s good behaviour:
- An identity for the agent. The tools run as a service account with metadata-only roles. Google Cloud’s IAM refuses table data on every route, Pipewright’s tools or not.
- Context that cannot go stale quietly. The context pack is generated from the manifest and the use cases, stamped, and checked in CI.
- A person in the loop. The agent’s identity cannot release, run, approve or deploy. Its work arrives as a pull request with a review bundle.
What has been tested
Every row marked live ran end to end on real Google Cloud projects with a real agent before this page was written.
| Part | Tested |
|---|---|
| Agent identity from the starter, impersonation, metadata-only roles | Live: six attempts to read data around the tools (queries for entity rows, feature values and an average, the tables API twice, a listing of the landing bucket) all refused by IAM; table metadata allowed |
The local tool server (pipewright mcp), all tools | Live, with an MCP client acting as the agent: onboarding, doctor, runs, a failed run explained |
Context packs, playbooks, context check in CI | Live in GitHub Actions, on Windows and Linux checkouts |
| Judgement checks, gate minimums, the review bundle | Live, and in the test suite (632 tests) |
| Claude Code end to end (hosted server, Enterprise) | Live: a use case drafted, validated, reviewed, merged, released by CI, trained (AUC 0.977) |
| Gemini CLI | Configuration written and checked by tests; not yet run live |
1. Give the agent its own identity
An agent should not borrow a person’s access: a person can read rows, so an agent acting as that person can too. Give each team an agent service account with metadata-only roles, and let the team’s engineers impersonate it. With the starter, one setting per team:
tenants = {
retail = {
members = ["user:ana@example.com"]
agent_identity = true # pw-retail-agent, metadata only
feature_datasets = ["my-project.features"] # feature tables the team (and its runs) may read
}
}
agent_audit_logs = true # optional: Data Access audit logs for every metadata read (billed by volume)
| Grant | On | Why |
|---|---|---|
bigquery.metadataViewer | the team’s dataset and feature datasets | schemas, row counts, partitions; no table data |
bigquery.jobUser | the project | dry runs and job metadata |
storage.objectViewer, conditional on pipewright/ and contracts/ | the artifacts bucket | the manifest and release contracts |
aiplatform.viewer | the project | models, pipeline runs and their failed steps, feature group definitions |
cloudscheduler.viewer, monitoring.viewer | the project | the plan of schedules and alerts |
| a custom platform-metadata role | the project | doctor’s checks of buckets, registries, identities, services and topics |
iam.serviceAccountTokenCreator for the team’s members | the agent account | impersonation |
The manifest names it, so every tool knows who to act as:
"tenants": { "retail": { "agent_service_account": "pw-retail-agent@<project>.iam.gserviceaccount.com" } },
"ai": { "local_tools": "allowed" }
Without one, the tools run as you and say so in every answer. ai.local_tools: forbidden turns the local tools off in an environment, production for example. Run for an agent, doctor checks the identity cannot release, run, read table data, upload or deploy, and warns if it can.
2. Build the context pack
pipewright context build --env test
git add APP_CONTEXT.md AGENTS.md CLAUDE.md GEMINI.md .pipewright/playbooks
git commit -m "Context pack for coding agents"
APP_CONTEXT.md holds what an agent must not guess: the teams, their datasets and feature datasets, the environment’s policies, the modelling rules, every use case with where its features come from, and the playbooks. AGENTS.md, CLAUDE.md and GEMINI.md get a marked Pipewright block; your text outside it is never touched.
The pack is stamped with a fingerprint of Pipewright’s version, the manifest and every use case file. pipewright context check --env test fails when any of them changed since the build, and the pull request workflow from pipewright ci init runs it once APP_CONTEXT.md exists.
| Playbook | For |
|---|---|
onboard-a-use-case.md | a new use case from an entity table and the feature catalogue, to a pull request |
add-a-drift-alert.md | monitoring and an alert on an existing use case |
debug-a-failed-run.md | from a failed run to its first error and a proposed fix |
change-a-gate.md | a gate change, within the platform’s minimums, with the reason in the review |
3. Connect the agent
pip install "pipewright-mlops[gcp,mcp]==1.3.0"
pipewright mcp --env test --tenant retail --print-config
{ "mcpServers": { "pipewright": { "command": "pipewright",
"args": ["mcp", "--env", "test", "--tenant", "retail"] } } }
Put that in .mcp.json for Claude Code, or in .gemini/settings.json for Gemini CLI, at the repository root. The server runs on your machine over stdio, started by the agent. In Claude Code, /mcp shows it connected. Add --agent claude-code to the args to record the agent’s name with every call.
The tools
| Tool | What it answers |
|---|---|
environment | the teams, datasets, policies, and who the tools act as |
validate, resolve, explain | offline checks with the judgement checks; the effective configuration; any key’s meaning and default |
doctor, plan | live read-only checks; what a release would change: tables, schedules, alerts |
inspect_table | schema, row count, partitioning; personal columns flagged; descriptions returned as untrusted text |
list_features | Feature Store feature groups and the team’s feature tables: definitions only |
status, runs, model_list, monitor_status, retrain_list, lineage | what is live, the latest runs (a failed run’s steps and first error line), how models are doing |
bootstrap_usecase | drafts a use case from an entity table and chosen feature sources, from schemas only |
review_bundle | the pull request description for the current branch |
sample_rows, profile | always refuse in open source: rows never reach an agent (Enterprise offers aggregates under rules) |
A table or column description is written by someone else, so it comes back marked untrusted with a note: a description cannot instruct the agent. Errors come back as answers without values, never as a crash. Every call is logged in .pipewright/mcp-log.jsonl on your machine; that log is for you, and Cloud Audit Logs on the agent account are the record.
4. The rules a draft is held to
validate has always refused what is wrong. From 1.3.0 it also warns about what validates and still misleads, the mistakes people and agents make most:
| Judgement check | Example |
|---|---|
| Rows ordered in time with a random or stratified split | monthly snapshots split at random leak the future into training |
| A date or timestamp as a feature | derive a duration in a feature table instead |
| A feature named after the label | churn_flag_prev next to the label churned: possible leakage |
| A team with feature datasets whose use case takes no feature from them | the agent built its own features instead of the catalogue’s |
Warnings never fail a use case that passed before. One rule refuses: a platform can set gate minimums per environment in the manifest, and a use case below them fails like any policy.
"policies": { "evaluation": { "min_gates": { "auc": 0.70 } } }
A platform can also tighten what reaches an agent with ai.data_classes: offline: true (no tool calls Google Cloud) and deny_names (table and column names withheld, as patterns such as *ssn*).
5. Review and CI
pipewright review --env test --base main > PR.md
The review bundle is what a reviewer needs on one page: what a release would change in Google Cloud, the settings that moved against the base branch, the checks and their warnings, the feature sources, the context pack’s state, and a section for the author’s judgement calls. The pull request workflow from pipewright ci init gains a review job that runs context check and writes the bundle to the run’s summary.
The agent drafts, verifies and opens the pull request. A person reviews and merges it. CI releases it. A person approves the trained model. The agent’s identity has no permission for any step after the pull request, and its playbooks say so.
6. What the record shows
Refused attempts and BigQuery queries are always in Cloud Audit Logs. With Data Access audit logs on, every metadata read is too. Each entry names the agent account as the principal and the engineer who impersonated it as the delegate. Calls through Pipewright’s tools also carry the user agent pipewright-mcp/1.3.0 agent=<name> and BigQuery job labels pipewright-mcp, pipewright-agent and pipewright-session.