Inspiration

As a developer, one thing I absolutely hate is keeping track of every API and service release. Google Cloud has hundreds of services. Whenever a change notice lands, I have to dig through my own memory: do any of my apps use this, and will they break when it shuts down? Breaking changes ship with little warning. New features launch quietly and go unnoticed. Release notes rarely get the attention they deserve.

API communication is messy and fragmented. The infrastructure for automated code changes already exists. What is missing is the application layer that connects a provider's notice to a customer's codebase. PatchAPI is built as automated "API Master" that takes the notice and sends an agent fleet to investigate the impact and patch the relevant code, all without human intervention.

Providers should not just announce a change. They should apply it. If Google deprecates an endpoint, changes an SDK, or launches a better API, an agent should understand that change, inspect the repositories connected to the service, locate every affected integration, and open a pull request with the required migration or improvement.

What it does

PatchAPI connects two sides:

Provider Developer
Publishes services and release changes Connects repos and subscribes to providers
PatchAPI continuously ingests the feeds PatchAPI maps provider changes to affect code

When a provider change matches something in a repo, PatchAPI turns that overlap into a verified pull request.

Provider side

Providers point PatchAPI at the endpoints they already maintain. PatchAPI reads them and keeps the catalog and change stream synchronized automatically.

For Google Cloud:

  • Catalog: Service Usage — serviceusage.googleapis.com/v1/projects/{project}/services
  • Changes: BigQuery release notes — bigquery-public-data.google_cloud_release_notes.release_notes

PatchAPI parses the project, dataset, or table directly from the endpoint and continuously pulls updates. I designed it this way so providers do not need another publishing workflow: point PatchAPI at the existing source and it stays in sync.

Developer side

Developers sign in, create a project, and import GitHub repositories. An indexer scans each repo for provider identifiers — model IDs, *.googleapis.com hosts, SDK dependencies, and similar references — and stores where each one appears in Cloud SQL.

Developers then subscribe to providers such as Google Cloud. PatchAPI joins incoming changes against that inventory and surfaces relevant releases as Needs you or Watching.

Clicking Start remediation sends the change to a warm worker. The agent fleet then:

  1. Finds the affected code.
  2. Applies the migration.
  3. Tests it inside a GKE Agent Sandbox with gVisor isolation and default-deny networking.
  4. Verifies the fix from the pinned base SHA.
  5. Opens a GitHub pull request with the verified migration.

Features and functionality

1. Release-note ingest

Google does not push when a note lands. Cloud Scheduler starts a Cloud Run job on a cron — patchapi-refresh-releases. The job pulls the enabled-API catalog and the release-notes table into two rows of work and writes them separately. If a pull fails it records error and stops, so a half catalog never goes live.

2. Repo indexing and subscriptions

Importing a repo or pushing new code triggers the indexer. A Cloud Run worker searches for model IDs and *.googleapis.com hosts, then uses ast-grep to filter false positives.

Confirmed usages are stored in provider_usages with file, line, and type. Indexing progress streams to the UI over SSE.

When you subscribe to a provider, PatchAPI compares those usages against its change stream:

  • Needs you — your runtime, config, or tests already depend on something deprecated or shut down.
  • Watching — the change is future-dated, not currently used, or is a new identifier worth adopting.

The inbox shows affected repos, file counts, and source URLs. Dismissals survive future re-indexing.

Repo indexing and subscriptions

3. Remediation queue and warm workers

The act of starting remediation writes a RECEIVED row. That row is the queue. A warm Cloud Run worker pool claims it with FOR UPDATE SKIP LOCKED, so Start does not wait for a job to boot.

Remediation queue and warm workers

4. GKE Agent Sandbox

Generated code runs only inside a gVisor-isolated GKE sandbox with no service-account token, a read-only root filesystem, dropped capabilities, and strict resource limits.

Network access is denied by default. PatchAPI temporarily opens only the egress needed for dependency installation or live verification, scoped to that sandbox, then removes it immediately afterward.

GKE Agent Sandbox

5. Credential handling

Connecting GCP gives PatchAPI viewer access, not your secret values. It can see that GEMINI_API_KEY comes from Secret Manager, but Postgres stores only the resource name. For live verification, a broker fetches the secret just before the sandbox command and injects it only into that command's environment. The value never enters prompts, logs, evidence, or Postgres.

If a required secret is missing, the run pauses until it is added or GCP is connected. GitHub tokens are also never stored in the database.

Credential handling

6. Independent verification agent

A separate verifier agent grades each run using only the evidence: build logs, test logs, live probes, the diff, and the allowed file list. It cannot be the same agent that wrote the patch. The result is:

  • PASS — checks pass, no unexpected files changed, and deprecated identifiers are removed.
  • FAIL — verification found a real problem.
  • INCONCLUSIVE — there was not enough signal to prove success or failure.
  • SKIP — a specific check was not required for this migration. A pull request opens only on PASS. Nothing overrides the verifier.

Independent verification agent

Technologies used

Layer Technology
Agent runtime Google ADK 2.1, gemini-3.5-flash on Vertex AI locations/global
Prompt safety Model Armor — sanitizeUserPrompt,
Agent memory Vertex AI Agent Engine Memory Bank (reasoningEngines), repo-scoped
Tracing Cloud Trace over OTLP/gRPC to telemetry.googleapis.com, OpenTelemetry SDK
Console Next.js 16, React 19, Tailwind 4, TypeScript strict, SSE for live state
Control plane FastAPI, Python 3.12, Pydantic v2 contracts, uv, ruff
Workflow state Cloud SQL Postgres 16 via SQLAlchemy + asyncpg
Events Pub/Sub push
Scheduling Cloud Scheduler → hourly identifier for release notes
Code search Zoekt shards for recall, ast-grep rules for call-site confirmation
Code execution GKE Agent Sandbox on gVisor
Provider ingest Service Usage API, BigQuery public release-notes table
Auth Identity Platform, Google OAuth, one GitHub App
Secrets Secret Manager
Provisioning Terraform modules per environment
CI/CD GitHub Actions, Workload Identity Federation, Artifact Registry

Findings and learnings

Designing seconds-fast change detection

The first challenge was figuring out which breaking changes actually affect a user's codebase.

My first approach was to give the agent a repo and a release note and let it inspect everything. That worked for one repo and one notice, but not for hundreds of services and thousands of release notes. The same repo would be reread repeatedly, answers could drift, and the audit trail was basically just an agent transcript.

I eventually realized I had the direction backwards. Instead of bringing every notice to every repo, I process each notice once.

Change Intelligence turns a provider notice into a repo-agnostic manifest. The indexer already knows which APIs, SDKs, models, and services each project uses, so finding affected projects becomes a deterministic join in Postgres, which is why it only costs seconds.

Change detection

Designing a warm worker pool so remediation starts instantly

A full remediation — clone, patch, build, test, verify, and open a PR — can take several minutes, so I had to find somewhere reliable to run it.

I tried keeping it in the HTTP request, Pub/Sub push, the agents service, and Cloud Run Jobs. Each had a problem: request lifetime, redelivery, blocked concurrency, or slow cold starts.

I eventually landed on a Cloud Run worker pool.

Workers stay warm and wait for work. The API writes a remediation_runs row as RECEIVED and immediately returns. Workers claim runs using FOR UPDATE SKIP LOCKED, which lets multiple workers safely process different jobs without duplicates.

The result is that when the user clicks Start Remediation, the execution environment is already running and work can begin within seconds.

Warm worker pool

Resources

The official Google documentation I used to build this project, and that you can learn from too.

Area Resource Used for
Agent Platform Memory Bank Repo-scoped context that survives across runs
sanitizeUserPrompt REST reference Screening provider text before a model reads it
Model Armor through Agent Gateway Where the guardrail sits in the request path
ADK ADK on Agent Platform Running ADK agents on Google infrastructure
Multi-agent systems How the orchestrator and specialists compose
Function tools The tool contract every agent call goes through
Pause and resume What a run parked on a missing credential relies on
Safety and security Guardrail patterns for tool-using agents
adk-python Source and samples
Long-running agents that pause and resume The checkpoint-and-wake pattern behind a parked run
Sandbox Install Agent Sandbox Bringing the sandbox up on GKE
GKE network policy The per-phase egress windows
gVisor The isolation boundary generated code runs on
Observability Agent Observability What a fleet is expected to emit
Tracing on Agent Runtime Trace configuration
Instrument ADK with OpenTelemetry Getting ADK spans into Cloud Trace
Cloud Trace OTLP endpoint One remediation, one trace

Built With

  • agent-engine
  • agent-registry
  • artifact-registry
  • bigquery
  • cloud-run
  • cloud-scheduler
  • cloud-sql
  • cloud-trace
  • fastapi
  • gemini
  • github-app
  • gke
  • google-adk
  • google-cloud
  • gvisor
  • identity-platform
  • model-armor
  • next.js
  • opentelemetry
  • postgresql
  • pub-sub
  • python
  • secret-manager
  • typescript
  • vertex-ai
Share this project:

Updates

Submission history