TramoGovernment software
Tramo: building permits for a Colombian municipality
Tramo is my government software company. Its system is in production at the Municipality of Marinilla, in Antioquia, and building permits move through it end to end: filings, drawings, construction resolutions, work in the public right-of-way, a public lookup for citizens, and archiving. Six fronts in one case file, with its status in plain sight and its deadlines counted. The municipality measures filing at half the time since the procedure was rebuilt, and reports fewer complaints and better standing with the public. Underneath it is 138 domain entities and roughly 40 modules on NestJS, Fastify, and TypeORM, with a Next.js frontend.
- 01
What a building permit is
A building permit is the authorization a citizen needs to build on, extend, or alter a property. It is not a form. It is a case file. A filing comes in with a number and a date, drawings come in, technical review happens, and a construction resolution comes out that grants or denies. Every step carries a legal deadline, and every document has to be archived exactly as it was signed.
On top of that sits work in the public right-of-way — sidewalks, streets, temporary occupancy — which moves on its own track and its own clock. Software that holds this cannot treat a case file as one row in a table. It has to know which stage the file is in, who touched it, which document replaced which, and how much time the municipality has left to answer.
- 02
The domain: 138 entities
Tramo models 138 domain entities across roughly 40 modules. Nobody chased that number. It is what shows up when a regulated procedure is modeled honestly instead of flattened into a handful of tables and a status column. The filing, the property, the applicant, the professional who signs, the document, the review, the resolution, and the archive are different things with different rules, so they stay apart.
What sets this apart from a commercial product is the consequence. If a cart miscalculates, a customer complains. If a municipal case file stores the wrong date, a legal deadline moves, and with it what the law allows. So the model is explicit past the point where it looks excessive, the boundaries between modules are real, and the rules of the procedure live in the domain rather than scattered across controllers.
- 03
Understanding the procedure before writing it
The first job was not programming. It was working out what a filing actually is. A regulated procedure cannot be digitised as-is, because as-is it carries steps that only existed to make up for everything being on paper: signatures confirming what the previous document already said, forms asking again for data the municipality already held, reviews waiting for someone to carry a folder from one desk to the next.
Copying that flow onto a screen would have produced a system that was faster to type into and exactly as slow to process. So the work went the other way: rebuild the procedure from what the regulation actually requires, separate legal requirement from paper habit, and reassemble the flow with that distinction made. The 138 domain entities come out of that. Not from wanting a large model, but from having looked at the procedure closely.
The municipality measures the result of that redesign at half the filing time. Same permit, same legal requirement: what came out was not rigour, it was the steps that existed only to move paper from one desk to the next.
And there is an effect the institution notices before anyone else. A procedure that answers within its deadline, with a traceable file and its status in plain sight, changes how it looks to the person waiting on it: diligence is what gets judged from outside, and the municipality reports theirs improved once the system started holding it up.
- 04
Who works better: the staff
The improvement you notice first is not the citizen's. It is the one felt by the person at the counter. The case file used to live scattered — a physical folder, an inbox with the drawings, a spreadsheet with the deadlines, the memory of whoever was carrying that case — so half a working day went on finding out where something was and retyping the same values into the next document.
Now the file sits in one place, with its stage, its owner and its deadline in plain sight. That changes a public servant's day more than it sounds: no more chasing paper, no more retyping, and no more being interrupted every few minutes by somebody asking where their permit stands, because the citizen can now look it up themselves.
The municipality reports both consequences: fewer complaints and better standing with the public. That follows, because they are the same thing seen from either side of the counter. An institution does not look more diligent because it says so. It looks diligent when it answers within the deadline and anyone can check.
- 05
The document is generated, not typed
Everything a document needs is already inside the case file: the parcel, the applicant, the professional who signs, the registry number, the address, the date of every action. When that document was written by hand, somebody typed those values one by one into a template, and that is where the error gets in: an ID number with one digit changed, a registry number miscopied, a date that does not match the filing.
In a regulated procedure that is not a typo. A wrong value in a resolution forces a correction, and a correction moves deadlines the law counts in days. So documents are generated from the case file, using information already loaded and checked, instead of asking the writer for it again. It is in production and the staff use it daily.
Do not confuse it with the case file assistant described below: that one is lookup, still experimental. This one is document generation, delivered and in use.
- 06
The public lookup for citizens
The public lookup is the open face of the system: anyone can search a filing and see where it stands, without calling city hall or asking someone for a favor. It is the part that most changes the relationship between a municipality and whoever is building, because a phone call becomes a query and a promise made across a counter becomes a status you can check at any hour.
Opening a case file to the public forces a decision about what is shown and what is not. A file holds personal data, technical documents, and administrative acts, and they do not share an audience. The lookup exposes the state of the procedure and what is public by nature, and leaves the rest inside. That cut is not a screen. It is a domain decision, made once and honored in every layer of the system.
- 07
The case file assistant, still experimental
Inside the case file there is an AI assistant that runs RAG over a vector database built from the documents of that filing. The idea is plain: ask in natural language what a technical opinion says or where an observation ended up, instead of opening one PDF after another. It is experimental. It is not yet in the hands of citizens, and it does not answer on behalf of the municipality.
Keeping it experimental is a decision, not a delay. In a municipality, an invented answer about a construction resolution is not an amusing hallucination. It is a legal problem, and someone could build on top of it. Before it opens up, every answer has to cite the document it came from, the assistant has to be able to say it does not know, and the whole thing has to be evaluated against real case files.
It is the same craft I bring to the agents already running in production — tightly scoped tools, validated output, traces of everything the model does — with the bar raised higher. An assistant that helps a public servant read a case file faster is useful on day one; one that answers on behalf of city hall has to earn that first. Where a mistake lands on a citizen standing in front of a construction site, AI moves slowly or it does not move.
- 08
Working with a city hall
Building for a municipality teaches things a commercial product never will. I do not get to invent the procedure: it is written into regulation, with stages, deadlines, and jurisdictions, and the software bends to it instead of the other way around. The public servants who use Tramo have been processing these permits by hand for years. When something does not fit them, the model is usually what is wrong, not them.
And one rule turns non-negotiable: nothing may fail silently. A lost order can be taken again; a lost filing leaves a person without an answer inside a legal deadline. That pushes toward loud failures, a record of every action taken on the file, and a state you can rebuild without asking anyone. It is the discipline I carry back into everything else I build.