Inspiration

I enjoy watching agents take a messy problem and work through it on their own.

One part of those demos has always made me uncomfortable, though. The agent usually finishes the work and then tells us that it succeeded.

That may be acceptable when the result is a draft. It feels very different when an agent is changing an AI model that people may depend on.

I used a Gemma scam message detector as the first Nightwatch case. A repair could catch more obvious scams while becoming worse at recognizing normal messages. Its headline score might improve even though the model had become less useful or more dangerous in the real world.

I wanted Gemini and the agents to do the difficult work. They should discover the failure, diagnose it, assemble the right specialists, design a repair, train a candidate, and evaluate the result.

I just did not think they should be allowed to approve their own work.

That became Nightwatch: an autonomous model repair system with an independent release boundary.

What it does

Nightwatch is built for ML engineers responsible for specialized models who currently have to diagnose regressions, prepare repair data, run training, compare evaluation suites, and make release decisions by hand.

An operator selects a pinned Gemma model, supplies a real CSV or JSONL evaluation dataset, maps its text and label fields, assigns target, safety, and regression suites, and freezes both the release thresholds and compute limit.

After the operator clicks Run Nightwatch, the system takes over.

Nightwatch evaluates the original model first and discovers which invariants actually failed. Gemini 3.6 Flash diagnoses the observed failure and requests three capabilities: target repair, safety boundary, and regression guard.

The mission worker searches Google Cloud Agent Registry for those capabilities. Registry results are treated as untrusted input. Deterministic code accepts only the agent identities, Agent Card hashes, HTTPS origins, service accounts, and capability tags already pinned in the frozen mission contract. The selected plan is sealed before any agent is called.

Three separately deployed Google ADK specialists then receive bounded assignments over private, OIDC authenticated A2A connections. Each returns a strict curriculum artifact with independent Agent Card, request, response, and artifact hashes.

Nightwatch validates those artifacts before launching exactly one bounded Gemma LoRA training attempt on Modal. The candidate is then evaluated against frozen evidence that the repair agents cannot change.

A deterministic Python gate makes the final decision. The candidate ends as either qualified_not_deployed or refused_not_deployed. Nightwatch never deploys a model automatically.

That separation matters. In one retained mission, a candidate reached 100 percent target accuracy and 100 percent safety accuracy. It was still refused because routine message recall fell from 87.5 percent to 75 percent. The agents improved the obvious scores, but the gate caught the hidden regression.

Judges can open the live Nightwatch experience and inspect three completed outcomes, the agent handoffs, immutable evidence, A2A receipts, and deterministic release decisions. Replaying a case starts no training and grants no operator authority.

How we built it

I started with the release gate, not the agents.

Before building the workflow, I wanted to prove that Nightwatch could reject a candidate that looked successful on the surface. Once the deterministic boundary could catch that failure, I built the autonomous repair system around it.

Gemini 3.6 Flash runs through Vertex AI. Google ADK provides the diagnostician and the three repair specialists. Google Cloud Agent Registry provides capability discovery, while the specialists communicate through private A2A endpoints. Gemma 3 is the student model being repaired, and Modal provides the bounded evaluation and training environment.

Cloud Run hosts the authenticated operator product, mission worker, public verifier, judge experience, and three specialist services. Each specialist runs under a separate service account and has only the permission needed to invoke Vertex AI.

Cloud Tasks advances each asynchronous mission one durable stage at a time. Firestore stores the hash chained mission journal. Cloud Storage retains create only artifacts, external call claims, and verification receipts.

Every mission begins with a content addressed contract containing the model revision, dataset identity, field mappings, evidence suites, gate policy, compute limit, and approved agent roster. Gemini can propose capabilities and repair data, but it cannot change that contract.

The scam message corpus was newly authored for Nightwatch and contains no customer messages or personal data. Curriculum, development, and sealed evaluation cases are separated by purpose. Exact overlap between training and evaluation evidence is rejected before training.

The public and private products are deliberately separated. The public experience can replay redacted missions and request a fresh verification receipt, but it cannot read Firestore, invoke Gemini, call the specialists, start training, or modify mission history.

Challenges we ran into

The first version began with a known failing score stored in the mission manifest. The workflow could repair a failure, but it was repairing a failure I had already identified for it.

I added a baseline evaluation stage so Nightwatch measures the selected model against the frozen evidence and discovers the failures itself before Gemini or any specialist is summoned. That completed the autonomous loop.

Dynamic agent discovery created a different problem. Finding an agent by capability is useful, but a Registry search result should not automatically become trusted execution authority. Nightwatch therefore freezes an approved roster in the mission contract and checks every discovered URN, Agent Card hash, endpoint origin, service account, capability, and fleet size before delegation.

The selected plan is persisted before the first A2A call. A retry cannot discover a different fleet halfway through the mission.

Asynchronous recovery was another challenge. Running every stage once was straightforward. Making the workflow safe when tasks were interrupted, retried, or delivered twice required immutable artifacts, deterministic task identities, bounded retries, and idempotent external calls.

One live run failed closed because the isolated Modal runtime still understood the previous contract schema. The original call record and exhausted Cloud Task were preserved. A versioned recovery task resumed the same contract and mission without creating a second training attempt or weakening the policy.

Evidence provenance also became important sooner than I expected. Instead of keeping whichever result looked cleanest, Nightwatch retains the model revision, dataset identity, case coverage, gate policy, artifacts, and terminal hash for each result.

Accomplishments that I am proud of

I am most proud that Nightwatch does not need the repair to succeed in order for the product to succeed.

In the latest real mission, Nightwatch evaluated 92 cases and discovered 14 baseline errors. Gemini diagnosed the failure and requested three capabilities. Agent Registry resolved the exact approved specialist fleet, and three private A2A agents independently produced 12 target repair rows, 8 safety boundary rows, and 10 regression guard rows.

Modal trained one candidate from those 30 validated examples.

Target accuracy improved from 83.3 percent to 91.7 percent. It looked promising.

But safety accuracy fell from 95.8 percent to 62.5 percent. Regression accuracy fell from 78.1 percent to 68.8 percent. Three critical scams were misclassified as routine messages.

All four fixed release invariants failed. Nightwatch refused the candidate, and production remained unchanged.

A second retained mission demonstrates the subtler hidden regression behind a 100 percent headline result. A third retained case passes every frozen invariant and becomes qualified, while still stopping short of automatic deployment.

These are not mocked outcomes. They produced the Firestore journals, Registry plan, A2A receipts, training claim, evaluations, hashes, verification receipts, and release decisions shown in the public product.

What we learned

The largest lesson was that model repair is not one score going up. A useful release policy must define both what should improve and what is not allowed to get worse.

I also learned that dynamic discovery should not mean dynamic trust. Agent Registry can find the right capability, but deterministic policy must still decide which identity is allowed to act.

Autonomy and authority are different. Nightwatch can complete the entire repair workflow autonomously without giving its agents permission to approve their own candidate.

Retry safety matters as much as model quality in a background agent system. A duplicated task must not create a second Gemini call, choose a different specialist, launch another training attempt, or produce conflicting evidence.

Finally, the interface must tell the same truth as the backend. A completed release gate is not necessarily a successful candidate. A refusal can be the correct and valuable result.

What's next for Nightwatch

Nightwatch is intentionally bounded today. It supports registered Gemma and PEFT compatible text classifiers, CSV or JSONL evaluation data, explicit evidence suites, one training attempt, and a fixed GPU time ceiling. It accepts data, not arbitrary user code.

The next step is to expand the same contract to additional specialized model families while preserving pinned revisions, bounded specialists, frozen evidence, and deterministic release authority.

A production version would add tenant isolation, organization managed agent rosters, shadow evaluation, monitored rollout, rollback support, and a separately authorized deployment service.

I still want agents to do more of the work.

I just do not want them to become their own release authority.

Built With

Share this project:

Updates