Skip to content

Repository files navigation

Sentinel

Autonomous fraud investigation, with a human in command.

When a bank's monitoring system flags a suspicious transaction, a level-one fraud analyst spends 45-90 minutes investigating it by hand: pulling the customer's transaction history, KYC documents, device logs, sanctions screens, and prior cases, then writing a disposition that recommends closing the alert, escalating it, or filing a Suspicious Activity Report (SAR). One alert at a time.

Sentinel is an AI agent that does that same investigation autonomously, in about a minute. It produces the analyst's complete case file - a written narrative, a full evidence trail, citations to similar historical cases, and a recommendation with a confidence score - and then stops. A human reviewer makes the final call.

Live demo: https://sentinel-eight-kappa.vercel.app


What it does

  1. A transaction is flagged (in the demo, you fire one from the dashboard).
  2. Sentinel picks it up and investigates autonomously:
    • Pulls the customer, accounts, and flagged transactions from MongoDB Atlas.
    • Traces the money across the transaction graph with aggregation pipelines.
    • Checks KYC records, device fingerprints, and sanctions screens.
    • Runs Atlas Vector Search over thousands of historical case narratives to retrieve precedent - a past case with the same signature.
  3. It writes a SAR-style narrative, records every tool call as an auditable evidence trail, and produces a recommendation (close / escalate / file SAR) with a confidence score.
  4. A human reviewer approves, escalates, or rejects. Sentinel never files on its own.

A manual investigation takes ~55 minutes; Sentinel completes one in roughly 60-90 seconds.


Architecture

Everything runs in production - the app on Vercel, the agent and the MongoDB MCP server on Google Cloud Run, orchestrated through Inngest.

  Browser
    |
    v
  Next.js app (Vercel)  --- fire alert --->  Inngest Cloud
    ^                                            |
    | poll liveProgress                          | invokes investigate-alert
    |                                            v
    |                              /api/inngest (Vercel)
    |                                            |
    |                                            | POST /investigate
    |                                            v
    |                              Sentinel Agent (Cloud Run)
    |                              - Google ADK + Gemini on Vertex AI
    |                                            |
    |                                            | MCP tools over authenticated HTTP
    |                                            v
    |                              MongoDB MCP Server (Cloud Run)
    |                                            |
    +--------------------------------------------+
                         |
                         v
                  MongoDB Atlas
                  - operational data (customers, transactions, KYC, devices)
                  - case files + historical SAR narratives
                  - Atlas Vector Search (Voyage AI embeddings)

The agent reasons with Gemini, decides which queries to run, executes them through the MongoDB MCP Server, and grounds its conclusion in the institution's own history via vector search. The same Atlas cluster holds both the operational data the agent queries and the precedent it reasons from.


Stack

Layer Technology
Agent Google Agent Development Kit (ADK), Gemini on Vertex AI
Agent tools MongoDB MCP Server (HTTP transport)
Data + memory MongoDB Atlas (operational + Atlas Vector Search)
Embeddings Voyage AI (voyage-3-large, 1024-dim)
Agent hosting Google Cloud Run (FastAPI wrapper, containerized)
Orchestration Inngest (durable event-driven trigger)
App Next.js, tRPC, Tailwind, shadcn/ui
App data Prisma + MongoDB Atlas
Auth better-auth (email/password)
App hosting Vercel
Runtime Bun

How the live flow works

  1. The user fires an alert on the dashboard. A tRPC mutation resets the target case and sends a sentinel/alert.created event to Inngest Cloud.
  2. Inngest invokes the investigate-alert function (served at /api/inngest on Vercel), which calls the agent's /investigate endpoint on Cloud Run.
  3. The agent service resolves the case, seeds session state, and runs the ADK agent to completion. As it works, before/after callbacks persist each tool call, the final narrative (with a vector embedding), and the case status to MongoDB.
  4. The UI polls cases.liveProgress and streams the investigation into the case view in real time - tool calls appearing, stages advancing, the narrative landing - ending on a completed case awaiting human review.

Repository layout

src/                      Next.js app (App Router)
  app/                    routes: landing, auth, dashboard, cases, alerts, settings
  features/               feature modules (cases, alerts, dashboard, landing, ...)
  inngest/                Inngest client + investigate-alert function
  trpc/                   tRPC routers
  db/                     Prisma client + seed
sentinel-agent/           the Python agent (deployed to Cloud Run)
  sentinel_agent/         agent.py (root_agent), tools, persistence, prompt
  server.py               FastAPI wrapper exposing /investigate
  Dockerfile              container for Cloud Run
  run_case.py             headless single-case runner (local)
prisma/schema.prisma      data model

Running locally

# 1. Install app dependencies
bun install

# 2. Set up the agent (Python 3.12)
cd sentinel-agent
python3.12 -m venv .venv
./.venv/bin/pip install -e .
cd ..

# 3. Configure environment
cp .env.example .env
cp sentinel-agent/.env.example sentinel-agent/.env
# fill in: MongoDB Atlas URI, Voyage API key, Google Cloud / Vertex settings

# 4. Seed the database
bun run src/db/seed/index.ts

# 5. Run everything (Next.js + Inngest dev + agent)
bun run dev:all

The agent talks to a local MongoDB MCP server over stdio by default. Set MDB_MCP_HTTP_URL to point it at a hosted MCP service instead.

To run a single investigation headlessly:

cd sentinel-agent
./.venv/bin/python run_case.py <alert_object_id>

Deployment (Google Cloud Run)

Two services, both in us-central1.

MongoDB MCP server

gcloud run deploy sentinel-mcp \
  --image=docker.io/mongodb/mongodb-mcp-server:latest \
  --region=us-central1 \
  --no-allow-unauthenticated \
  --port=8080 \
  --args='--transport=http,--httpHost=0.0.0.0,--httpPort=8080' \
  --set-env-vars="MDB_MCP_CONNECTION_STRING=<atlas-connection-string>" \
  --set-env-vars="MDB_MCP_READ_ONLY=true"

Agent

The agent is wrapped in a small FastAPI app (server.py) that imports root_agent directly and exposes /investigate, then deployed with a plain Dockerfile:

cd sentinel-agent
gcloud run deploy sentinel-agent \
  --source . \
  --region=us-central1 \
  --allow-unauthenticated \
  --service-account=<compute-sa> \
  --memory=1Gi \
  --timeout=3600 \
  --env-vars-file=agent.env.yaml

Environment (in agent.env.yaml, gitignored): GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION, SENTINEL_MODEL, MDB_MCP_HTTP_URL, MONGODB_URI, MONGODB_DB, VOYAGE_API_KEY.

App (Vercel)

Set DATABASE_URL, BETTER_AUTH_SECRET, BETTER_AUTH_URL, NEXT_PUBLIC_APP_URL, VOYAGE_API_KEY, INNGEST_EVENT_KEY, INNGEST_SIGNING_KEY, and SENTINEL_AGENT_URL (the agent's Cloud Run URL). Sync the app to Inngest Cloud at <app-url>/api/inngest.

Notes

  • Secrets are passed via environment variables for this demo; production should use Secret Manager.
  • The Atlas IP allowlist is open for the demo so Cloud Run and Vercel can reach the cluster; production should use a VPC connector with a fixed egress range.

Human in the loop

Sentinel produces a recommendation, never a filing. Financial-crime decisions carry legal weight, so the agent stops at "file a SAR" and a human reviewer reads the case and makes the call - approve, escalate, or reject. The agent compresses the investigation; the judgment stays human.


License

MIT - see LICENSE.

Releases

Packages

Contributors

Languages