How OpenSanctions' open matching engine screens names against sanctions lists

Updated

OpenSanctions screens a name by running it through an open matching engine that compares your query against aggregated sanctions, watchlist, and PEP data, then returns candidate entities with a score rather than a simple yes/no. You can reach that engine in three ways through one toolkit — yente-client — which bundles an SDK, a CLI, and an MCP server. The design goal is that when an LLM agent runs your screening, you can see exactly what it checked and prove it afterward.

What the matching engine actually does

The engine does not do exact string equality. It performs fuzzy matching: it normalizes names, handles transliteration and word-order variation, and scores how closely your input resembles each stored entity. That is why the output is a ranked set of candidates with confidence scores, not a binary hit.

This matters for screening because sanctions names arrive in many forms — "Vladimir Putin," "PUTIN, Vladimir Vladimirovich," or a Cyrillic original — and a rigid lookup would miss most of them.

The three layers of yente-client

The toolkit rolls three interfaces over the same underlying engine:

Layer What it is Typical use
SDK A programmatic library Embed screening into your own application or agent code
CLI A command-line tool Run one-off or scripted checks, inspect raw results
MCP server A Model Context Protocol server Let an LLM agent call screening as a tool

Because all three sit on the same open matching engine, a result you get from the CLI and a result an agent gets through the MCP server come from the same logic. That consistency is what makes the output auditable.

Why provenance is the point

The stated rationale is direct: if an LLM agent is going to run your sanctions screening, you need to know exactly what it is checking — and be able to prove it. As compliance workflows become more agentic, data provenance matters more, not less.

In practice this means two things you should verify on any result:

  • Which list and version the match came from, since OpenSanctions aggregates hundreds of sources.
  • What the engine compared, so a reviewer can reproduce the decision rather than trust a black-box score.

How to run a screening

  1. Choose your interface. For a quick manual check, use the CLI. For an automated pipeline or agent, use the SDK or MCP server.
  2. Submit the name (and any supporting fields your query includes) to the matching engine.
  3. Read the ranked candidates. Expect scored entities, not a single verdict.
  4. Inspect provenance for each candidate — the source list and the entity record — before acting.
  5. Record the query and result so the decision is reproducible.

The expected result at each step is a candidate set you can justify, not an opaque pass/fail.

Common sticking points

  • Treating a score as a decision. The engine ranks; your compliance policy sets the threshold and the human review step.
  • Ignoring transliteration. A name that looks like a miss may be a spelling variant the engine already handles — check the candidates before concluding "no match."
  • Assuming the data is static. OpenSanctions aggregates many sources, so list contents change; re-run screening rather than relying on a cached result.

For the underlying data itself — which sanctions, watchlists, and PEP sources feed the engine — see the collections and datasets, which are published as JSON.