Inspiration

A home-care agency lives or dies by paperwork that expires. A physician order lapses and every visit under it becomes unbillable. A plan of care goes unreviewed and the next survey finds it. Nobody forgets these on purpose — they are small, recurring, and easy to lose under the day's real work. We wanted an agent that watches for them, does the work, and stops at exactly the point where a human has to decide.

What it does

Two pulses beat every five minutes against a Cloud SQL ledger. The clock creates jobs from business rules and the calendar and hands them out. The AI — Gemini running as a worker named Nomi — arrives uncalled: it picks up a job, reads its source, and either submits a result quoting the source as evidence, asks the owner a question when it cannot know, or reports that it is stuck, with an assessment. A machine check verifies the result against each rule's acceptance criteria before anything reaches a person.

What remains for the human is exactly the judgment: approve, send back, answer, abandon — and, at the bedside, sign. There is no code path from the agent to any of those. The approved visit-note draft is delivered to the medical record's inbox addressed to its visit; the doctor edits it on site and signs; a database trigger freezes the signed note forever — and the signed note becomes next week's source material. The loop closes. Billing follows the same grammar: charges derive from signed visits only, cap violations become 0-point flags, and applying the exception is a human ruling.

Every step is an event appended to a ledger that is never overwritten, so "what happened, and who decided it" is always answerable.

How we built it

  • Gemini 3.5 Flash on Vertex AI, reached with the workload's own identity — no API key exists anywhere.
  • Google GenAI SDK (google-genai) — the only model dependency in the project.
  • Cloud Run Jobs + Cloud Scheduler for the two pulses; a Cloud Run service for the window; Cloud SQL for PostgreSQL holding two databases — the agent's ledger and a synthetic EMR — with Secret Manager, Artifact Registry and Cloud Build for the wiring.
  • Onion architecture with dependencies pointing inward only, enforced by 6 import contracts on every run. The AI is modeled inside the domain as a worker with an assignment, a budget and a retry limit — not an oracle bolted onto a workflow.
  • The five design documents are the source of truth: the test suite parses their tables and fails when code and design disagree (state machine, events, value objects, operations, interfaces). 902 tests; a break-checker removes each of the 70 domain obligations one at a time and asserts the suite goes red every time.
  • The proof of the architecture: we swapped the LLM (Ollama → Vertex AI Gemini), the ledger (SQLite → Cloud SQL) and the scheduler (launchd → Cloud Run Jobs) — and git diff baseline..pillars-swapped -- domain app is empty.

Data sources

Everything is synthetic and in-repo: 10 invented patients whose "addresses" are public landmarks (a shrine, a station, a park — the map is real, no real residence is ever pointed at), 3 invented clinicians, a fictional fee schedule ("Nagisa Schedule") that mirrors the shape of the real Japanese one but none of its numbers. The seven care workflows are JSON topic files — data, not code. No real health information appears anywhere, and the agent is never given any.

Challenges we ran into

  • The model's word is never evidence. A result only finishes when a quote can be pulled from the source that backs it; if not, the clock schedules a recheck and goes back for one.
  • Prompt injection has nowhere to go: the in-app guide receives only readers and the LLM port — no writing tool appears in its type signature, so there is no code path from a conversation to an action.
  • Version changes were double-creating jobs mid-period. The fix was in the origin key, and the reconciliation tests caught the design/code drift immediately.
  • An underspecified instruction made the agent ask the same clarifying question every month — which proved the ask-a-human path works, and was fixed by one sentence of data, not code.

Accomplishments that we're proud of

An agent that cannot approve its own work — by construction, not by policy. A live demo that runs itself honestly: while judging is under way, a scripted stand-in named Sim-Director presses the human buttons on the same public forms, every press recorded under its own name, with a banner disclosing it on every page. Questions still wait for a real person.

What we learned

Autonomy is arriving uncalled — the clock never wakes the agent. And the boundary between "the AI does the work" and "the human owns the judgment" is only real if it is a type, a table, and a test — not a prompt.

What's next for Troupe

More bounded contexts (pharmacy, scheduling against clinician calendars), richer assessments, and letting agencies write their own topic JSON through the window.

Built With

  • cloud-build
  • cloud-run
  • cloud-scheduler
  • cloud-sql
  • domain-driven-design
  • fastapi
  • gemini
  • google-genai-sdk
  • postgresql
  • pydantic
  • python
  • secret-manager
  • vertex-ai
Share this project:

Updates

Submission history