Inspiration

I'd previously built DocuSentinel, a document tampering detector using AI vision analysis, for an earlier cybersecurity hackathon. It worked well at catching obvious tampering — font mismatches, pixelation, misaligned text — but it had a real blind spot: every document was analyzed in total isolation. If the same forger reused a template across five slightly different fake documents, DocuSentinel would evaluate each one completely fresh, with zero memory of the others. When I saw this hackathon's theme — agents with real, persistent memory — it was an obvious fit: give DocuSentinel the one thing it was missing.

What it does

DocuSentinel Memory analyzes uploaded documents for signs of tampering, and remembers every document it has ever seen. When a new document comes in, it doesn't just return a verdict — it searches its own memory for documents that look similar, and if any of those were previously flagged as fraudulent, it surfaces a pattern warning. The system isn't just detecting fakes anymore; it's recognizing recurring fraud patterns across submissions over time.

How I built it

  • FastAPI backend, carried over from the original DocuSentinel
  • Google Gemini API analyzes each document image and returns a structured tampering verdict with confidence and reasoning
  • sentence-transformers (running locally, open-source) converts each document's analysis into a 384-dimension vector embedding
  • CockroachDB Cloud (Serverless) stores every analysis alongside its embedding in a native VECTOR column, using Distributed Vector Indexing to power fast similarity search as the memory grows
  • CockroachDB's Managed MCP Server connects the agent directly to the database for live queries
  • Deployed on AWS Lambda, with document storage in S3

The flow: a document is uploaded → Gemini analyzes it → it's embedded → CockroachDB is queried for similar past documents → the result and embedding are saved back to CockroachDB for future recall → the response includes both the verdict and any matching historical patterns.

Challenges I ran into

Almost every challenge was a real infrastructure integration problem rather than application logic:

  • Python 3.14 was too new for several core libraries' pre-built installers, forcing a switch to a Python 3.12 virtual environment
  • Working through two rounds of deprecated Gemini model names as Google's lineup moved forward
  • CockroachDB Cloud's SSL certificate verification failing locally on Windows, resolved by adjusting the SSL mode
  • SQLAlchemy's generic PostgreSQL dialect misreading CockroachDB's distinct version string
  • CockroachDB's native VECTOR type requiring explicit casting — psycopg2 sends Python lists as generic arrays by default, so similarity queries failed until I added explicit CAST(... AS VECTOR) calls and converted embeddings into CockroachDB's vector literal format

Each of these took real debugging against actual error tracebacks, not guesswork — which made the final working pipeline genuinely satisfying to see run end-to-end.

What I learned

How CockroachDB's vector indexing actually works under the hood — that it lets you store structured relational data and vector embeddings in the same table, avoiding the need for a separate dedicated vector database. I also got much more comfortable debugging real distributed-database integration issues rather than just app-level bugs.

What's next for DocuSentinel Memory

Wiring the MCP Server so the agent queries memory as part of its own reasoning rather than through the application's hardcoded logic, and moving from text-based embeddings toward embeddings derived from actual document content (OCR/layout) for more precise pattern matching.

Built With

Share this project:

Updates