Skip to content
All work

Visa applicationsIn production

An agent that completes visa filings.

A visa services platform where an AI agent completes the application from the applicant's own documents, and a browser extension fills the official embassy and government portals, none of which offers an API. Every field is validated before submission, and the case goes to a person the moment something doesn't match.

Role
Sole engineer
Client
Visa services platform (NDA)
Scope
Agent design to production
Status
Running in production

Context

Every destination has its own visa form and its own portal, and none of them offers an API. Visa specialists were typing the same applicant data into each country's portal by hand, applicants were abandoning long forms partway through, and one small mistake could cost weeks.

Constraints

  • One wrong field can cost an applicant weeks, or a refused visa.
  • Official portals have no API, and every country's form is different.
  • Coverage keeps growing: Schengen, the US, the UK, Turkey, the UAE, Sri Lanka, Kenya and more.
  • Every automated action has to be explainable to the person who checks it.
Visa agent: Schengen tourist visa
  • My wife is travelling with me. She has her own passport.
Passport number
···
Travel dates
···
Co-applicant
···
Bank statement
···
EUSchengen visa0 of 4 fields
Browser extension: fills the official visa portalWaiting

My responsibility

Sole engineer on the platform: agent design, the browser extension, the core API, document and identity workers, payments, status tracking and the production rollout.

Architecture

Core platform
A Spring Boot modular monolith on Java 21 with clear module boundaries: applicants, visa applications, documents, admin, travel agents, quality control, consent and notifications.
The agent
The agent works from the applicant's own documents, read by OCR. The model runs on AWS Bedrock, answers stream to the browser over Server-Sent Events, and every action is a typed tool call: fill a form field, draft a letter, escalate to a reviewer.
Portal autofill
A browser extension reads the official portal's HTML form, sends its fields together with the validated application to an AI model, and applies the field mapping that comes back. Visa specialists no longer retype applications: they check the filled form and submit it, on any country's portal from Schengen to Kenya.
Documents and identity
OCR and face-match workers consume from RabbitMQ, so heavy document and identity checks run off the request path and never block the applicant.
Payments
A separate service for checkout, 3-D Secure, webhooks and refunds.
Status tracking
For supported countries, RPA workers built on Playwright check embassy and government portals for status changes and report them into the core API, so nobody refreshes a portal by hand.

Critical decisions

Typed tool calls only

The model can act only through typed tool calls. Each one is a structure the system validates before it touches the filing, so nothing the model writes as prose can change an application.

Hold the case when unsure

If the agent cannot establish a field from the applicant's documents, the submission stops. A visa specialist sees the case with the reason attached and makes the call.

An extension, because there is no API

Official portals offer no API, so the extension fills the form in the browser and stops there. A visa specialist validates every field and clicks Submit; nothing reaches an embassy without a person.

Let AI map the form

An AI model maps each portal's form from its live HTML at fill time, so a redesigned portal or a new country usually needs little or no new code. The mapping comes back as JSON the extension applies field by field, and a person checks the result.

A modular monolith

One deployable with strict module boundaries. At this size that avoids the cost of running a distributed system, and any module can be split out later if volume demands it.

Payments behind an interface

The payment provider sits behind one interface. When the business moved from Razorpay to Stripe, no caller changed.

When things go wrong

WhenWhat happens
A supporting document, such as a bank statement, is out of date or doesn't match the applicationThe case is held for a visa specialist with the reason attached.
A country redesigns its visa portalThe extension maps the new form from its live HTML on the next fill, and a person still checks every field.
OCR or face matching is slow or failsThe worker handles it off the request path; the applicant keeps going.

Result

Running in production with real applicants, across Schengen, the US, the UK and more.

Of each application filled by the agent from the applicant's own documents

Stack

Java 21 · Spring Boot 3 · PostgreSQL · RabbitMQ · AWS Bedrock · Server-Sent Events · Stripe · Playwright · Browser extension

Next case study

Claims intake and EDI reconciliation for US health plans

Need a system that holds up like this one?

Tell me what's at stake. You'll hear back within one business day, and the first call is 30 minutes, with no obligation.