Inspiration

A critical potassium result comes back at 2 PM. The doctor who ordered it is in theatre. The result was delivered correctly, but nobody acts on it for six hours.

Many hospital workflow failures happen in these gaps. A result arrives but is not noticed. An insurer requests a document that sits in a shared inbox. A discharge waits on a pharmacy sign-off that nobody follows up on.

These failures have something in common: nothing happened.

Most agents react when an event occurs. Sentinel is designed for the harder problem of detecting when an expected event does not occur.

What it does

Sentinel turns hospital events into obligations. Each obligation records what needs to happen, who is responsible, when it is due, and what evidence proves completion.

It focuses on three problems.

Detecting silence. Every obligation carries its own next checkpoint. Cloud-based timers wake the system when action is expected, while a periodic sweep recreates any missing timers from the obligation ledger.

Requiring evidence before closure. Sentinel does not let an LLM decide that a task "looks complete." Evidence must pass deterministic checks for source, reference number, timestamp, subject, and required action before an obligation can close.

Protecting patient identity. Identifiers are replaced at the trust boundary before text reaches Gemini. The replacement is deterministic, so Sentinel can track the same case over time without storing patient names in the agent workflow.

For one test obligation, Sentinel ran for six real days. It sent a reminder, escalated the breach, and later escalated to a supervisor using timers created when the obligation was first opened.

How I built it

Sentinel runs as eight services on Google Cloud Run, with separate service identities and responsibilities.

The ingestion service uses Model Armor, Sensitive Data Protection, and Cloud KMS to screen and de-identify incoming text before it is stored or published.

The core engine stores the obligation ledger in Firestore with transactional updates and an append-only history. Two Gemini agents interpret incoming events and determine which department should act next. The agents have no tools and cannot directly modify the ledger. Their proposals must pass deterministic validation before becoming real obligations.

The agent fleet uses the same container image with different service accounts and separate tool allowlists. Each service verifies its own permissions and identity.

Policies are stored as versioned YAML. Each decision records the policy version that produced it, making previous decisions traceable.

The frontend is built with Next.js and IBM Carbon. Obligations are ordered by breach risk, and the interface can explain why an item is stuck by tracing its dependency chain.

Challenges

A large part of the build was learning where cloud systems behave differently from local development.

Gemini 3.5 Flash required the global endpoint rather than the regional endpoint used by the rest of the system.

Google's edge handling interfered with a /healthz endpoint, so service health checks had to move to /health.

A google-api-core version caused Firestore transactions to fail only on Cloud Run, which required pinning the dependency.

Cloud Run CPU throttling also meant buffered OpenTelemetry spans were not reliably flushed after requests completed, so trace export had to be made synchronous.

I also ran into Cloud Run hostname and DNS differences, plus compatibility issues between Turbopack and IBM Carbon's Sass setup.

These problems were not central to the original idea, but solving them made the system significantly more reliable.

What I learned

The biggest lesson was that timers alone do not solve absence detection.

If a timer disappears, nothing necessarily fails visibly. The obligation may simply stop being tracked. Sentinel instead treats the obligation ledger as the source of truth and reconstructs timers from it. Across twelve test obligations, all deadlines were detected, with a median detection delay of 5.6 seconds.

I also learned where LLMs should and should not make decisions.

In an evaluation using 30 pieces of evidence, the deterministic Evidence Gate produced 0% false closures, while Gemini produced 16% false closures on the same set. The model handled language well, but struggled with decisions based on exact authority rules and timestamp windows.

Prompt injection testing produced a similar lesson. Detection became less reliable when malicious instructions were embedded inside longer legitimate text. However, the agent itself had no tools or ability to close obligations, which limited the impact of a successful injection.

Another experiment showed that asking a model to assign an action's risk tier could confuse the seriousness of the medical situation with the authority required by the action. Deterministic policy rules were a better fit.

Finally, I learned to treat fallbacks carefully during evaluation. An early classifier test appeared to achieve 100% accuracy, but several requests had timed out and silently received correct default labels. Once fallback results were excluded, the true accuracy was 75%.

The main principle I took away is simple:

Use models for judgement over messy language. Use deterministic systems for facts you can know exactly.

What's next

The next step is validating Sentinel with real hospital staff.

The current workflows are based on documented failure modes rather than direct interviews with clinical teams. I also do not yet have a real-world baseline for how long these failures normally remain unnoticed.

Future work includes moving all public services behind IAM, adding role-scoped advisory memory, and testing the workflows with healthcare professionals.

The goal is not to make an agent that replaces hospital staff. It is to build a system that notices when an important responsibility is quietly falling through the gaps.

Built With

  • agent-registry
  • carbon-design-system
  • cloud-kms
  • cloud-monitoring
  • cloud-run
  • cloud-scheduler
  • cloud-tasks
  • cloud-trace
  • fastapi
  • firestore
  • gemini
  • gemma
  • google-adk
  • model-armor
  • nextjs
  • opentelemetry
  • pub-sub
  • pydantic
  • python
  • secret-manager
  • sensitive-data-protection
  • typescript
  • vertex-ai
Share this project:

Updates

Submission history