FtM is central to structuring data in C4ADS across investigations, but until now using its vocabulary in a graph database has meant hand-writing and maintaining a Python class for each FtM entity type. followthemoney-neomodel removes this step. It automatically generates FtM’s full vocabulary as ready-to-use Python classes, allowing analysts and developers to build in ordinary Python, without Cypher and without manual schema mapping.
As the name suggests, followthemoney-neomodel combines Follow the Money (FtM) – the common open anti-corruption data standard maintained by OpenSanctions – and graph databases designed to store and explore highly connected data. Previously, developers who wanted to work with FtM data in a graph database had to write custom code or learn Cypher, a graph-specific query language. followthemoney-neomodel removes this hurdle and allows building in ordinary Python with the full FtM vocabulary already built into the toolkit.
We developed the followthemoney-neomodel in parallel with OpenSanctions’ Followthemoney-graph, and the two complement each other: their model loads FtM data at scale into a graph database, while ours gives developers a quick way to use it once it’s there.
Follow the Money (FtM) provides analysts and engineers with a common language for describing investigative data. It defines a variety of entity types – from people and companies to ships, bank accounts and sanctions – and the relationships between them, including ownership, governance and payment. In other words, FtM provides a common framework for anti-corruption investigators that makes data portable, interoperable and ready for analysis.
Because FtM is designed to model networks and describe entities based on their connections to each other, it can be easily coupled with graph databases. Neo4j, the graph database used by C4ADS and OpenSanctions, stores connections as its own data type with different properties, rather than leaving connections between traditional relational tables implicit. Diagrams ask questions like “Who is connected to this company and through what?” to ask quickly and naturally.
FtM structures data across investigations on our Horizons platform. Data collected from business registers, shipping records and sanction lists are mapped to the FtM schema regardless of the source format, allowing us to link datasets that would otherwise use incompatible formats.
As part of an ongoing collaboration with OpenSanctions, C4ADS has moved this relational database data into Neo4j for network analysis. Neo4j speaks its own query language, Cypher, while most data analysis and development takes place in Python. neomodel, an open source library maintained by Neo4j Labs, closes some of this gap by allowing developers to define and query chart data in pure Python and translate it into Cypher behind the scenes. But neomodel expects developers to hand-write a Python class for each entity type they use, and FtM defines many entity types. This discrepancy between the design of neomodel and the scope of FtM is what followthemoney-neomodel concludes.
At its core, followthemoney-neomodel is a connector library that connects FtM and Neomodel. FtM provides the schemas; neomodel provides the graph interface.
followthemoney-neomodel reads the installed version of FtM and dynamically generates the corresponding node and edge classes, one for each entity and relationship type that FtM defines, taking into account its schema hierarchy and property type (string, number or date/time). followthemoney-neomodel requires no manual schema mapping, coding or configuration.
In practice, a developer can import a class, use it to create an entity in a Neo4j diagram, and immediately start traversing relationships while remaining fully aligned with the FtM schema and in pure Python. The toolkit handles the translation so analysts and developers can focus on the investigation.
The following example uses followthemoney-neomodel to create a basic relationship between a person and a vehicle, two entity types defined in the FtM schema:
The result: a few lines of Python produce two entities linked by an ownership relationship in a Neo4j diagram without the need for Cypher. Developers can then set properties for the nodes and relationships.
Some aspects of how the followthemoney-neomodel library maps FtM concepts into Neo4j’s graph model are worth mentioning:
- node Follow FtM’s inheritance hierarchy. In FtM, entity types inherit from each other; That is, a person is a kind of legal entity, which is a kind of thing. The library preserves this by assigning multiple labels to each node. A Person node in Neo4j is named Thing, LegalEntity and Person. The thing is the top level of abstraction and every node in the diagram carries it.
- edge Types become relationships, not nodes. In FtM some describe types, such as: B. Property, the connection between two entities rather than a standalone entity. The library detects this and creates them as Neo4j relationships rather than nodes. Because Neo4j relationships have a single type rather than multiple labels, the library maps them to an uppercase relationship type so that “Ownership” becomes “OWNERSHIP” in the diagram.
A hypothetical study shows how the toolkit works in practice. A common use case for C4ADS is mapping the corporate and financial networks of politically exposed persons (PEPs). This example creates a network that uses Person, Asset, and Organization entity types as nodes and Membership, Ownership, and Payment as edges connecting the nodes.
Imagine a suspected money laundering network involving Mr. and Mrs. Smith modeled in Neo4j. Payments flow between people and organizations, people own assets, and memberships bind individuals to organizations. The diagram captures all of these connections as a traversable network, as shown below (see the unittest for the full setup code):
Here, the structure suggests payments are being routed through an intermediary, a pattern that may indicate money laundering. With this data in Neo4j, followthemoney-neomodel simplifies the query from Python.
The output of traverse() depends on how deep the query goes. Developers can get one or more relationships within the same call and mix optional and non-optional relationships. Since Cypher queries can get complex, the higher level of abstraction in Python helps. For example, the query above can be roughly translated as follows:
The results return all five elements of the path traversal: the starting organization, the payment relationship, the intermediate legal entity, the ownership relationship, and the ending value. Because followthemoney-neomodel encodes the FtM hierarchy, neomodel knows the exact abstract labels (LegalEntity instead of Person) to use when traversing a particular relationship. This keeps the terms as broad as possible when searching for specific permitted entities. Developers can filter properties at any point along the path. This is a powerful feature when searching for specific terms such as number or date/time. In this case, the all() method returns Mr. Smith’s assets valued at over $4,000 with every node and relationship found along the way.
For more information about Neomodel path traversal, see the Neomodel documentation.
Some limitations are associated with FtM’s data model and apply regardless of which tool you use to work with it. Others refer specifically to the way followthemoney-neomodel maps FtM to Neo4j.
FtM’s multi-valued properties and statement-level provenance (which source claimed what and with what certainty) are by default collapsed into individual Neo4j properties. If you want to preserve the path at the claim level, you must explicitly model it as its own node or edge. Multi-label nodes support hierarchy-aware queries, but may surprise you if you filter on a broad label like LegalEntity and expect it to be selective. OpenSanctions strongly advises against this. Finally, there is currently no way to reconcile old data with a newer FtM version: if the installed FtM version changes, nodes and relationships already in the graph will not be automatically updated to match the newly generated classes. We recommend pinning the FtM version you are building against.
followthemoney-neomodel is now available on GitHub, along with the documentation and full test suite referenced above. This project continues to evolve as part of our ongoing work with OpenSanctions. If you build with it, encounter problems, or have feedback about the schema mappings, open an issue in the repository.
Table of Contents
References and further reading
https://c4ads.org/tech-bulletin/bringing-follow-the-money-into-the-graph-a-new-neo4j-tool/





