VIGIL

Drug safety, governed by the clock.

When a patient is harmed by a medication, a legal clock starts. Drug-safety teams have as little as 7 days to assess the case, obtain a physician's sign-off, and file it with regulators. Miss the window and it is not an inconvenience — it is a reportable regulatory violation that can halt a drug and put more patients at risk.

Today that pipeline runs on spreadsheets, email chains, and human memory. VIGIL replaces it with a single long-running UiPath Maestro case that carries its own regulatory deadline, escalates the instant a patient turns serious, and refuses to close until a qualified physician has signed.


Inspiration

I have an engineering background, and what drew me to pharmacovigilance was that it is a domain where a missed deadline is not a soft failure — it is a legal one. That makes it a perfect fit for orchestration rather than a chatbot. The interesting problem was never "can an agent read a report." It was "can the deadline, the human accountability, and the escalation become properties of the process itself, instead of things a tired human has to remember." Maestro's case model is built for exactly that, so I chose the least-saturated track and went deep instead of wide.


What it does

One adverse-event report becomes one governed case that moves through five stages, with a human gate in the middle and a regulatory clock running the whole time.

Stage What happens Type
1 · Intake Validates the 4 ICH E2B core elements Agent
2 · Triage Scores seriousness, assigns the 7/15-day deadline Agent
3 · Medical Review Physician approves, requests info, or rejects Human gate
4 · Reporting Builds the E2B summary, identifies regulators Agent
5 · Closure Verifies completion, writes the audit record Agent

Two things make it more than a linear flow:

  • The SLA clock rides the whole case, warns at 80%, and escalates on breach.
  • An interrupting exception path fires the moment a case is flagged serious, pulling it off the normal track and onto the urgent one.

Architecture

        ┌─────────┐     ┌─────────┐     ┌──────────────┐     ┌───────────┐     ┌─────────┐
 report │ 1·Intake│ ──▶ │2·Triage │ ──▶ │3·Med Review  │ ──▶ │4·Reporting│ ──▶ │5·Closure│
   in   └─────────┘     └────┬────┘     │  ★ HUMAN GATE│     └───────────┘     └─────────┘
                             │          └──────────────┘
                  on serious │
                             ▼
                     ┌───────────────┐         ┌──────────────────────────┐
                     │ ⚡ Expedited   │         │ Causality Service (coded)│
                     │  Escalation   │ ◀─seriousness─ │ WHO-UMC + ICH E2D  │
                     │ (interrupting)│         └──────────────────────────┘
                     └───────────────┘

        ┌────────────────────────────────────────────────────────────────────┐
        │ ⏱  15-DAY REGULATORY SLA CLOCK · warns at 80% · escalates on breach │
        └────────────────────────────────────────────────────────────────────┘

The Case Manager evaluates entry, exit, and completion rules across every stage, producing an auditable execution trail suitable for regulatory inspection.


How I built it

The orchestration is low-code in UiPath Maestro — five Agent Builder agents wired stage to stage, a Human Action with an approval app for the physician gate, a case-level SLA with escalations, and a secondary interrupting stage for the serious-case path.

The brain behind the routing is coded. I built a Python causality service using a coding agent through UiPath's official skills integration:

npm install -g @uipath/cli
uip login                            # auth to the tenant
uip skills install --agent gemini    # 21 UiPath skills installed

The service computes WHO-UMC causality and ICH E2D seriousness, and outputs the value that drives the Maestro case's escalation:

{
  "causality": "Probable",
  "causalityReason": "Plausible time to onset (21 days), positive dechallenge, and no alternative explanation, without a positive rechallenge.",
  "seriousness": "serious",
  "reportingDeadlineDays": 15
}

That seriousness output is what the low-code case acts on. Coding agent built the brain; Maestro acts on it. 10/10 self-tests passing.

I also built a self-contained clinical frontend (the Causality Workstation) that runs the same WHO-UMC logic in the browser, so a reviewer can score a real adverse event and watch the routing decision live.


Challenges I ran into

The honest ones, because they shaped the build:

  • Starved agent inputs. The auto-generated agents declared heavy required schemas that were not fully wired between stages, so each one failed validation at runtime. The Closure agent needed all 19 required fields set, including a nested deadlineStatus object that only parsed once wrapped in parentheses so the JS engine read it as a value, not a code block.

  • A CLI packaging regression. The newest UiPath CLI packed solutions in a "unified" format that the judging environment rejected with JSON is not a valid Case Management JSON of any previous version. I traced it to packageInfo.json and the difference between unified and legacy package layouts — a real diagnosis, not a guess.

  • A platform-wide publish outage during the final submission window, which blocked many participants at once. I kept a clean cloud-tenant build and a recorded end-to-end run as a fallback while the environment recovered, then deployed successfully once it did.


What I learned

The biggest lesson: design the stages and the data contracts between agents first, before touching prompts. Almost all of my debugging time went into mismatched inputs between stages. Once I treated the work as a case with explicit contracts, the deadline, the human gate, and the escalation stopped being things I had to code and became properties of the case itself.


What's next

  • Bind the exception gate directly to the causality service's live output.
  • Spawn a child case per regulator (FDA, EMA, PMDA), each with its own jurisdiction-specific deadline.
  • Generate standards-compliant ICH E2B(R3) submission files from the Reporting stage.

Every report a case. Every case on the clock. Every serious patient escalated in time.

Built With

Share this project:

Updates