A maritime release workflow where agents coordinate the work, but only human attestation and independently verified receipts can unlock the container.
This article was created for the purposes of entering the All Things Agentic Hackathon.
The container is undamaged.
It is still not moving.
That was the operational contradiction that pulled me into Cargo Release.
After a maritime casualty, cargo interests may need to provide General Average security before cargo is released. In practice, that can involve an average bond from the cargo interest and a guarantee from an insurer, routed through an average adjuster and then recognized by the carrier. The final adjustment can remain open long after the immediate release-security work is complete. That separation—release now, settle later—is documented in both the CMI guidance on the York-Antwerp Rules and UNCTAD's review of General Average practice.
For the person coordinating the cargo interest, this creates a peculiar queue of work:
- reconcile the casualty notice and cargo evidence;
- obtain the owner's attestation;
- obtain the insurer's guarantee;
- submit the security pack;
- retain an adjuster's rejection instead of losing it in email;
- correct the pack;
- obtain acceptance;
- request the carrier's release order;
- confirm that the carrier actually read it back;
- notify the operator without confusing notification with authority.
That is exactly the kind of multi-party friction an agent fleet should remove.
It is also exactly the kind of workflow where an agent should never be allowed to say, “Looks good to me—release the cargo.”
So I built the fleet around a constraint:
Agents coordinate. Humans attest. Independent receipts authorize release.
The model can inspect, extract, rank, explain, and propose. It cannot become the owner, insurer, adjuster, carrier, or state writer.
That is the product.
One attestation, eight bounded actions
Cargo Release begins with one synthetic casualty CloudEvent delivered through Google Cloud Pub/Sub and Eventarc. The deployed run converges on one durable mission in Cloud SQL—even when the same event is delivered more than once.
The workflow collects five prepared evidence sources. Two of them are deliberately placed in conflict.
One is a synthetic scanned adjuster rejection with a visible correction field. The other is a hostile email telling the model to ignore the process and manufacture acceptance.
The email stays visible, but it is quarantined. It creates no trusted fact, no memory entry, and no state transition.
The scan follows a different path. Its digest, case, container, revision, checkbox, missing field, and confidence must fit a typed schema. Deterministic policy—not model prose—decides whether that structure is acceptable.
Then Cargo Release stops.
The operator must make the sole human decision in the run: attest the synthetic owner bond.
That one action starts eight bounded downstream actions:
1 human attestation
→ 5 unique signed partner receipts
+ 1 security submission
+ 1 automatic correction
+ 1 marked post-release notification
= 8 autonomous downstream actions
Security pack v1 is rejected. That rejection is not treated as an exception to hide; it becomes durable evidence. The controller uses the validated missing-field reference to produce v2. The adjuster accepts v2. The carrier issues an order and then independently confirms read-back.
Only then does the physical cargo state move from HELD to RELEASED.
The General Average adjustment remains OPEN.
That last detail matters. The system does not collapse a complicated legal and commercial process into a dishonest green checkmark. It advances one bounded operational state and leaves the larger adjustment where it belongs.
The architecture is an authority map
Most cloud architecture diagrams answer, “Which products did you use?”
I needed this one to answer a harder question:
Who is allowed to change reality?
The system has four lanes.
1. Authenticated intake. Pub/Sub and Eventarc deliver the casualty envelope. The public Next.js service runs on Cloud Run and exposes a narrow authenticated relay. The only media input is the prepared, digest-bound synthetic scan. There is no unrestricted public upload surface.
2. Scoped coordination. Google ADK runs a coordinator and four specialized workers on Vertex AI: manifest evidence, security pack, carrier authority, and runtime recovery. Each worker has one read-only tool, structured output, no peer transfer, and the invariant release_authority=false.
3. Deterministic authority. A private Cloud Run controller is the sole state writer. Cloud SQL for PostgreSQL holds missions, versions, leases, evidence decisions, receipts, and hash-linked events. One human attestation and issuer-bound partner receipts advance the state graph. The insurer, adjuster, and carrier run as identity-isolated private Cloud Run services.
4. Observable consequence. The container changes state only after the two-key condition has been satisfied. A marked Slack message is sent after carrier read-back. Notification is proof of the consequence, never a cause of it.
Across the four lanes, Agent Identity, Agent Gateway, Registry, Model Armor, Memory Bank, Cloud Logging, and Cloud Trace constrain or observe the system. They never acquire release authority.
Cloud Run service identities are useful here because Google Cloud can authenticate service-to-service calls using the identity assigned to each workload rather than a shared credential baked into the application. Google documents that distinction explicitly in its Cloud Run service identity guide.
The resulting design rule is simple:
Intelligence may be distributed. Authority must remain explicit.
The failure that improved the project
The most important multimodal feature in Cargo Release is also the place where the honest answer is least glamorous.
I built a Vertex AI adapter for Gemini to extract an adjuster-rejection-v1 record from the prepared scan. The adapter is digest-bound, schema-versioned, and records a zero-authority model receipt.
Then I staged it against the managed service.
The ambiguous case failed closed, exactly as intended.
The valid scan did not pass. The managed model returned malformed structured output.
There were two tempting responses:
- loosen the validator until the output passed;
- hide the failure and record the happy path with a deterministic response.
I did neither.
The production interface and demo label the extraction FIXTURE. The deterministic fixture uses the same schema and validation boundary, so the evidence-to-v2 causal path remains demonstrable, but I do not claim that the live extraction is native Vertex inference. The managed adapter remains staged until a valid scan and an ambiguous scan both pass the required acceptance packet.
That choice cost the demo a shinier badge.
It also proved the safety property I cared about: malformed model output cannot talk the system into trusting it.
I started this project thinking “fail closed” was an implementation detail.
It became the strongest product requirement.
Rejection is evidence, not interruption
The next design mistake was more subtle.
A first version of a workflow like this naturally models rejection as an error:
submit → rejected → failed run
But an adjuster's rejection can contain the exact fact needed to create the correct revision. If I turn it into a generic exception, I throw away the information that makes autonomous recovery possible.
Cargo Release models it instead as:
submit v1
→ retain signed rejection + reason + source reference
→ select revision 2
→ correct the declared field
→ submit v2
→ retain acceptance
The run continues without another human click. The correction is bounded by a typed, validated reason—not an agent improvising a new security document.
This became a broader lesson:
A useful agentic system does not merely survive the wrong path. It turns the wrong path into the next verified input.
Idempotency is part of the user experience
Event-driven systems are allowed to redeliver. Browsers retry. Operators double-click. Remote partners time out after doing the work but before returning the response.
If “one attestation → eight actions” becomes sixteen actions under retry, the metric is theatre.
So the count is derived from durable, unique receipt kinds, event types, and delivered notifications. Duplicate events converge on one mission. Atomic leases permit one active writer. Partner receipts are issuer-bound, signed, digest-addressed, and valid only from an allowed prior state. Slack delivery is post-read-back and idempotent.
The managed concurrency probe delivered the same casualty six times across three Cloud Run instances. Every request returned successfully. The database retained one declaration, one run, and one human gate.
That test changed how I think about “autonomy.”
An autonomous system is not one that performs many actions. It is one that still performs the right number of actions when the infrastructure behaves normally—which includes duplication, delay, and retry.
Additional models, deliberately outside authority
The project also integrates three additional Google AI models, each downstream of the authority boundary:
- Gemma 4 reviews a sanitized owner-bond packet against a constrained checklist.
- Gemini Embedding 2 ranks eight reviewed synthetic cases after deterministic filtering.
- Veo 3.1 Fast creates a four-second post-release training replay in private Cloud Storage.
All three produce visible receipts. All three return release_authority=false.
The Veo replay is intentionally not attached to the authoritative Slack notice. It is training material, not evidence. A generated video should never become proof that the event it depicts actually happened.
That separation matters more than the number of models in the stack.
The live proof
The final continuous demo begins on the public Cloud Run deployment and shows the exact .run.app URL beside a fresh native Eventarc mission and Pub/Sub message ID.
The recorded mission is mission-13820650dbee; its Pub/Sub message is 21614781193876288.
From there, one uninterrupted live application execution shows:
- authenticated intake;
- hostile-text quarantine;
- the prepared visual evidence and its truth label;
- the sole owner attestation;
- v1 rejection and retained reason;
- automatic v2 correction;
- five verified receipts and carrier read-back;
- physical cargo moving to
RELEASEDwhile adjustment remainsOPEN; - the matching marked Slack consequence and
1 → 8/8proof metric.
The original v6 application source is preserved separately at 3 minutes 16.84 seconds with zero cuts, splices, or speed changes. In the 3-minute-28.80-second v7 master, its product-execution portion remains continuous through the completed consequence and proof metric. Only then does a disclosed 12-second Google Cloud Console insert show project ata-2026-cargo, cargo-release-controller, us-central1, the same mission filter, and GET /v1/missions/mission-13820650dbee 200 OK. The architecture footage then resumes and explains the exact Google Cloud service path. The two master edit boundaries around the Console insert are explicitly disclosed.
What I learned
1. The safest architecture begins with verbs.
Who may read? Who may propose? Who may write? Who may attest? Who may issue a receipt? Product names come after those answers.
2. A model receipt is not an authority receipt.
Provenance, confidence, schema version, and source digest make model output inspectable. They do not make it true or authorized.
3. Human-in-the-loop should name the human's actual decision.
The operator does not click “approve AI.” They attest one owner-bound fact. Everything else is bounded execution or independent receipt verification.
4. Preserve failure as data.
The rejected v1 is more valuable than a generic exception because it contains the reason that selects v2.
5. Truth labels beat implied sophistication.
NATIVE, ADAPTER, and FIXTURE are visible per mission. A managed service existing somewhere in the project does not upgrade a fixture run into native proof.
6. Generated media belongs after the decision boundary.
Veo can teach the workflow after release. It cannot prove the workflow before release.
What this does not do
Cargo Release is a fictional, synthetic architecture demonstration.
It does not decide coverage, liability, contribution, legal sufficiency, or a real General Average adjustment. It does not communicate with a real cargo owner, insurer, adjuster, carrier, terminal, or vessel. “Released” means the synthetic mission reached its deterministic terminal state after verified synthetic receipts.
The live visual extraction is truthfully labelled as a deterministic fixture while the managed Vertex adapter remains staged. The partner services are identity-isolated fixtures, not real commercial integrations.
Those are limits, not footnotes.
They are the line between demonstrating an authority architecture and pretending to operate one.
The takeaway
The easy version of this project was an agentic supply-chain control tower.
The interesting version was a system that could coordinate across multiple parties while remaining constitutionally incapable of impersonating any of them.
That is why the final screen does not say “AI approved.”
It says the owner attested, the insurer guaranteed, the adjuster accepted, the carrier read back, and the deterministic controller verified every transition.
The agents did the coordination.
They never held the key.
Try it: https://cargo-release-web-1015646664425.us-central1.run.app
Inspect the proof mission: https://cargo-release-web-1015646664425.us-central1.run.app/?mission=mission-13820650dbee
Source: https://github.com/Zen-cronic/cargo-release
Demo: https://youtu.be/mBSkNDSCHJY




Top comments (0)