<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://kfergusonuk.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://kfergusonuk.github.io/" rel="alternate" type="text/html" /><updated>2026-09-13T17:42:20+00:00</updated><id>https://kfergusonuk.github.io/feed.xml</id><title type="html">Kevin Ferguson</title><subtitle>Road and street works systems, national data standards, and applied AI in the public sector. Projects, writing and open source by Kevin Ferguson.</subtitle><entry><title type="html">I set out to connect England’s streetworks systems. I ended up mapping a third of the world’s.</title><link href="https://kfergusonuk.github.io/2026/08/27/connecting-englands-streetworks-systems.html" rel="alternate" type="text/html" title="I set out to connect England’s streetworks systems. I ended up mapping a third of the world’s." /><published>2026-08-27T00:00:00+00:00</published><updated>2026-08-27T00:00:00+00:00</updated><id>https://kfergusonuk.github.io/2026/08/27/connecting-englands-streetworks-systems</id><content type="html" xml:base="https://kfergusonuk.github.io/2026/08/27/connecting-englands-streetworks-systems.html"><![CDATA[<!-- IMAGES: eight images from the original article need adding.
     Save them into assets/streetworks/ and uncomment the
     matching line below each caption. Suggested filenames are given.
     Every image also needs alt text for screen readers — replace the
     bracketed text in each. -->

<p><img src="/assets/posts/streetworks-sdk/world-map.png" alt="World map of live roadworks pulled through the SDK, blue dots marking works sites" />
<em>StreetWorks SDK — roadworks world map, partial live pull, 26 August 2026. Blue dots are works sites.</em></p>

<blockquote>
  <p>“Make a Streetworks (and roadworks) Software Development Kit (SDK) that makes connecting to England’s systems — Street Manager, NSG, D-TRO, National Highways, etc. — easier, and maybe even pulls in data from across the UK… Europe… or even the world, puts it through a common model, and makes it consistent to use. Just link to each country’s version of Street Manager. How hard can it be…”</p>
</blockquote>

<p>After several months of work, multiple thousand burnt tokens, and many headaches and dead ends later, the StreetWorks SDK is now looking in pretty good shape.</p>

<p>At the start of this project, little did I realise just how lucky England is with our national streetworks infrastructure platforms. The story is not repeated in many countries. Nor did I realise how interesting the data comparisons would be.</p>

<p>My mental model was basically: link all the English systems I already use into one easy install, then find the equivalent of Street Manager in each country, connect to it, normalise the data, job done. It turns out there often isn’t an equivalent of Street Manager.</p>

<p>Sometimes there isn’t a national system at all. Sometimes there is, but only for motorways. Sometimes every state, province, region or municipality does something different. Sometimes the data is there, but you need a gazetteer to make sense of the location. Sometimes there’s an API, but you need credentials, or you have to register first. Sometimes there’s an open feed, but it follows a standard that’s implemented completely differently from every other feed using that same standard.</p>

<p>And sometimes there just isn’t a feed.</p>

<p>The SDK is now pulling in data from over 130 official sources worldwide, each with its own shape, authentication method, pagination and schema. All of that now comes together in StreetWorks-SDK, where the data can be parsed through a common model.</p>

<h2 id="so-what-is-streetworks-sdk-and-what-does-it-do">So what is StreetWorks SDK, and what does it do?</h2>

<p>Put simply, the SDK takes all the hard bits about connecting to various data sources — England and elsewhere — and makes them much, much simpler to use. Where is it, how does it want to talk to my computer, what do I need to do, how does it handle passwords.</p>

<p>Now, instead of spending the first valuable hour of a project working out how to handle tokens from DfT, handshakes in Swedish, or just what 시작일 means in Korean, you specify where you want to connect to, add your username and password to the <code class="language-plaintext highlighter-rouge">.env</code> file if needed, use the common model, and you’re in. Data ready to go, with whatever project you had in mind.</p>

<p>That can be as a solo developer, a development team, or an AI agent.</p>

<p>And that last one is becoming increasingly important. If an AI agent is asked to build something that uses roadworks data, the difficult part shouldn’t be discovering how a particular country’s infrastructure works before it can even start solving the actual problem — which is exactly the sort of thing the discovery layer, common model, and the agent-oriented files now in the repo are meant to take off its plate.</p>

<h2 id="quick-start">Quick start</h2>

<p>The whole point is that this is short. Install it, ask what covers the place you care about, then connect and read the data back through the common model.</p>

<p>First, discovery — which providers exist, and which need no credentials:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip <span class="nb">install </span>streetworks
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">streetworks</span>

<span class="c1"># Find a feed — browse by territory, or list the credential-free ones.
</span><span class="nb">len</span><span class="p">(</span><span class="n">streetworks</span><span class="p">.</span><span class="n">providers</span><span class="p">())</span>                  <span class="c1"># every provider
</span><span class="nb">len</span><span class="p">(</span><span class="n">streetworks</span><span class="p">.</span><span class="n">providers</span><span class="p">(</span><span class="n">credentials</span><span class="o">=</span><span class="bp">False</span><span class="p">))</span> <span class="c1"># just the keyless ones
</span><span class="n">streetworks</span><span class="p">.</span><span class="n">providers</span><span class="p">(</span><span class="n">territory</span><span class="o">=</span><span class="s">"Spain"</span><span class="p">)</span>      <span class="c1"># what covers Spain?
</span></code></pre></div></div>

<p>Run against the live registry today, that returns 138 providers currently registered, 103 of which need no credentials at all. Asking for Spain lists the five real Spanish feeds: DGT (Dirección General de Tráfico) nationally, Consell de Mallorca (IDEmallorca) for the island, Servei Català de Trànsit for Catalonia, Dirección de Tráfico del Gobierno Vasco for the Basque Country, and Ayuntamiento de Madrid (INFORMO) for the capital.</p>

<p>Each entry prints its own summary — what it is, its network scope, whether it needs credentials, and, on the last line, the exact import to use. That final line is the bridge to the next step:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>DGT (Dirección General de Tráfico)
Spain's national roadworks feed.
Network scope: multi authority interurban
Scope: National except Catalonia and the Basque Country...
Credentials: No credentials required
from streetworks.datex2.dgt import DGTClient   &lt;-- the import you need next
</code></pre></div></div>

<p>So the browse step hands you the import line directly — no hunting through docs for how to reach a given feed.</p>

<p>Then pick a feed and pull it. Most need no credentials at all; where one does, it goes in a <code class="language-plaintext highlighter-rouge">.env</code> file (a template is provided, just rename it) and the rest stays the same:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">streetworks</span> <span class="kn">import</span> <span class="n">get_provider</span>
<span class="kn">from</span> <span class="nn">streetworks.common</span> <span class="kn">import</span> <span class="n">from_datex2</span>

<span class="c1"># Connect — get_provider() hands back the client class for a key.
</span><span class="n">DGTClient</span> <span class="o">=</span> <span class="n">get_provider</span><span class="p">(</span><span class="s">"dgt"</span><span class="p">)</span>               <span class="c1"># Spain's national feed
</span><span class="k">with</span> <span class="n">DGTClient</span><span class="p">()</span> <span class="k">as</span> <span class="n">dgt</span><span class="p">:</span>                      <span class="c1"># no credentials needed
</span>    <span class="n">situations</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">dgt</span><span class="p">.</span><span class="n">iter_roadworks</span><span class="p">())</span>

<span class="c1"># Common model — run the native records through the from_* converter.
</span><span class="k">for</span> <span class="n">situation</span> <span class="ow">in</span> <span class="n">situations</span><span class="p">:</span>
    <span class="n">works</span> <span class="o">=</span> <span class="n">from_datex2</span><span class="p">(</span><span class="n">situation</span><span class="p">,</span> <span class="n">territory</span><span class="o">=</span><span class="s">"Spain"</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">works</span><span class="p">.</span><span class="n">sites</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="n">works</span><span class="p">.</span><span class="n">territory</span><span class="p">,</span> <span class="n">site</span><span class="p">.</span><span class="n">works_type</span><span class="p">,</span> <span class="n">site</span><span class="p">.</span><span class="n">date_confidence</span><span class="p">)</span>
</code></pre></div></div>

<p>Each <code class="language-plaintext highlighter-rouge">Works</code> carries its sites, every field in your own terms — <code class="language-plaintext highlighter-rouge">works_type</code>, <code class="language-plaintext highlighter-rouge">date_confidence</code>, <code class="language-plaintext highlighter-rouge">territory</code> — with the untouched source record still there on <code class="language-plaintext highlighter-rouge">.raw</code>. And where a territory has more than one provider (Spain has five, Norway has three), asking for the place rather than a specific feed lists the candidates instead of guessing which one you meant.</p>

<h2 id="the-common-model">The common model</h2>

<p><img src="/assets/posts/streetworks-sdk/common-model.png" alt="Diagram of the common model, showing native provider schemas resolving to shared Works, Site and Street shapes" /></p>

<p>More on the common model is in the <a href="https://github.com/KFergusonUK/StreetWorks-SDK/blob/main/docs/concepts/common-model.md">repository docs</a>.</p>

<p>What this means is that you don’t need to know the Italian for end date, or the German for street. Built over the top of every feed is a simple, always-works-the-same reference point, so you don’t need to know how DATEX II, WZDx or Street Manager work, or what the main data fields like “works start date” mean in each. However you interact, it’s always the same — or you can go to the <code class="language-plaintext highlighter-rouge">.raw</code> feed and get the data as it comes.</p>

<p>The inclusion of <code class="language-plaintext highlighter-rouge">.raw</code> is, I feel, important. Working through the data, I enjoyed seeing the different reference names and data nuances, such as Norway having Z coordinates in its feeds. By including the raw feeds, the native, culturally important data and labelling are not lost. They remain underneath, always accessible, some providing really rich additional data that would be difficult to accommodate in a common model.</p>

<p>The interface is unified, but the meaning — and the Z coordinate — is not flattened.</p>

<h2 id="whats-included">What’s included</h2>

<p>The main focus is, of course, streetworks and roadworks feeds, which can be surprisingly different. Next, and generally a much-needed companion, are the street gazetteers, or their equivalents. Also covered is the Digital Traffic Regulation Order platform, the initial layout for the coming National Underground Asset Register (NUAR) API, and the UK Police Crime API — more on that later.</p>

<h2 id="the-other-half-street-gazetteers">The other half: street gazetteers</h2>

<p>Roadworks are only half the story. A lot of roadworks data can’t even be plotted on its own — the feed tells you a works is on a given street, but not where that street physically is. For that you need a gazetteer: the authoritative register of what a street or address actually is, and where.</p>

<p>So the SDK treats gazetteers as a first-class part of the package, not an afterthought — and it keeps two things apart that are genuinely different. An address register (France’s BAN, the Netherlands’ BAG, Norway’s Kartverket) answers “where is this address?”. A street register (Great Britain’s OS Open USRN, the Netherlands’ NWB, Norway’s NVDB) answers “what and where is this street?”, with real geometry.</p>

<p>Lumping them together produced a real analytical error early on. “European gazetteers have no street geometry” looked true when the only examples to hand were address registers, and it’s simply false. The geometry lives in the street register, which in most countries is published separately, by a different body, from the addresses.</p>

<p>And just like the roadworks side, the gazetteer side has its own common model — BAN, BAG, NVDB, OS Open USRN and the rest all resolve to the same Street, Segment and Address shapes, so you reach for the same fields whichever country’s register you’re reading. I won’t repeat the whole demonstration here; the GitHub docs walk through the gazetteer converters in full.</p>

<h2 id="what-real-geometry-lets-you-do">What real geometry lets you do</h2>

<p>Once a street register gives you real geometry, you can do more than join it to roadworks. One of the worked examples in the repository takes Great Britain’s OS Open USRN street centrelines, densifies each one, and drapes it over a real elevation model — here, the Environment Agency’s LIDAR Composite DTM — to produce a 3D surface of the streets following the actual terrain. This is the Durham peninsula:</p>

<p><img src="/assets/posts/streetworks-sdk/durham-peninsula-3d.png" alt="3D mesh of Durham peninsula street centrelines draped over a LIDAR terrain model" />
<em>OS Open USRN street centrelines draped over the Environment Agency’s LIDAR Composite DTM (1m) of the Durham peninsula — a worked example from the repository, not a feature of the installed package. The mesh exports to STL, so you can 3D print it.</em></p>

<p>A couple of things about this matter more than the picture. First, it’s built with no heavy geospatial stack — no GDAL, no rasterio — just a hand-rolled raster decoder over the same httpx-and-nothing-else approach as the rest of the SDK.</p>

<p>Second, and more importantly, the draped height is treated honestly as what it is: a sampled estimate of the ground beneath a flat street centreline, never written back into the data as though it were a measured elevation of the road. Where the terrain model has a genuine gap, the point is dropped, not interpolated across — filling it would fabricate a plateau that isn’t really there.</p>

<p>That’s the same discipline the rest of the SDK applies horizontally — never silently reproject, always label the coordinate system — now applied to the vertical axis. Elevation is carried as a named provider’s stated value, with its vertical datum labelled as carefully as its CRS. The Environment Agency’s heights here are Ordnance Datum Newlyn; Norway’s NVDB uses a different datum again. Both are real, and the SDK never quietly assumes they’re the same — even where, for two British sources, they happen to agree.</p>

<h2 id="provider-matrix">Provider matrix</h2>

<p><img src="/assets/posts/streetworks-sdk/provider-matrix.png" alt="Summary provider matrix showing coverage by territory across roadworks, gazetteer, TTRO, NUAR and other columns" />
<em>The TTRO, NUAR and Other columns are effectively UK-only today (D-TRO, NUAR model, Police / DataVIA), hence the gaps elsewhere.</em></p>

<p>The full provider-by-provider matrix — including the state-by-state and province-by-province breakdown for the USA, Canada, Germany and France, and the specific data source behind every cell — lives in the <a href="https://github.com/KFergusonUK/StreetWorks-SDK">repository docs</a>.</p>

<h2 id="data-landscapes">Data landscapes</h2>

<p>Working through each zone, it struck me just how differently each area handles roadworks data. Some systems are very mature and clearly working well; others, perhaps less so.</p>

<p><img src="/assets/posts/streetworks-sdk/data-landscapes.png" alt="Comparison of data landscape maturity across regions" /></p>

<h3 id="usa-and-canada">USA and Canada</h3>

<p>I’ve grouped these as they share, in different proportions, two main systems: the more modern WZDx (Work Zone Data Exchange) and 511, based on an older system where North Americans would dial 511 for traffic and travel information, which has now largely gone online while keeping the name.</p>

<p>Both are very useful. The USA seems to be working towards WZDx, and Canada is largely on 511; some states are the other way round, some have both. Both are relatively easy to read once you’re set up, meaning that if you’ve worked out one feed, you’ve worked out most of the pattern. That doesn’t necessarily mean there is a feed, however — some states are missing from both entirely. Overall, good work for North America there.</p>

<h3 id="europe">Europe</h3>

<p>DATEX II dominates the national roads, including even the UK’s National Highways feed. Beyond the main roads, though, the picture is not so rosy. Some countries have a larger national feed, which is great to read in, but many are by state or province, and that doesn’t mean consistency between them. In some cases each area within one country can have its own unique schema and setup, some credential-protected, some not, some not available at all. The NAP system seems to be bringing some of that together. Overall, a tricky picture, but so much fun to look into, with a lot of data-rich feeds.</p>

<h3 id="uk">UK</h3>

<p>On to Blighty. England, as I mentioned earlier, really is fortunate with the national systems in place — Street Manager, NSG, D-TRO. The data is mostly clean and detail-rich. For all the complaining we like to do, these really are great systems that we’re lucky to have.</p>

<p>England is really the one place the SDK reaches a complete, joined-up national stack. The roadworks register (Street Manager), the street gazetteer (the National Street Gazetteer, plus OS Open USRN for open geometry) and the legal traffic orders (D-TRO) are all there, and all reachable through one interface. Most of that is access-controlled — you bring your own account for Street Manager, the NSG and D-TRO — but two routes need no account at all: OS Open USRN for street geometry, and Street Manager Open Data, the open subscribe-and-receive push feed of the register’s own works events. So you can get real English roadworks and street data flowing with zero credentials, then add accounts to unlock the fuller picture.</p>

<p>And here’s the thing that really makes England fortunate, which only became clear once I’d looked at everywhere else. Plenty of countries publish a national roadworks <strong>feed</strong> — the road authority telling you what it’s doing on its own network. Far fewer run a national roadworks <strong>register</strong>: the statutory system where anyone wanting to dig has to apply, and an authority grants or refuses it.</p>

<p>That distinction is the difference between being told about works and being the gatekeeper of them, and it is surprisingly rare. Of the national and territory-wide systems I’ve found so far, only a handful of national roadworks registers appear to exist in a usable, reachable format at all: England’s Street Manager, Scotland’s SRWR, and — punching well above its size — Jersey’s RoadWorkx. Ireland is a near-miss: MapRoad is a genuine national statutory register on paper, but I couldn’t find a published endpoint, schema or way in, so as far as actually consuming the data goes, it isn’t reachable. That gap between “a register exists” and “you can actually get the data” is itself part of the story.</p>

<p>Plenty of strong candidates don’t make that list, which is what surprised me. Iceland, New Zealand and Spain all have genuinely good national roadworks feeds — but they’re the road authority’s own operational feed, not a permit register. Most of the other really good permit registers I found are single cities doing it well in isolation: New York, Paris, Copenhagen, Helsinki. Not whole countries. A proper national register is the exception, not the rule.</p>

<p>The UK as a whole is more fractured. Scotland publishes a brilliant SRWR feed, but it must be linked to the NSG for plotting, as it doesn’t carry coordinates. Wales and Northern Ireland are limited, in the openly accessible feeds I found, to traffic feeds on main roads — a real miss on the data here. I would love to see some Welsh and Northern Irish API feeds in future.</p>

<h3 id="crown-dependencies">Crown Dependencies</h3>

<p>Jersey, Guernsey, Isle of Man. Jersey is the standout star here with a great roadworks feed. Guernsey and the Isle of Man have some catching up to do on the roadworks side, though Guernsey does have a good street gazetteer.</p>

<h3 id="new-zealand-and-australia">New Zealand and Australia</h3>

<p>New Zealand has a single country-wide feed, which is brilliant to see. Australia is split by region with no national register, and as with Europe there are multiple approaches to how the data is fed out — some credential-protected, some not. It’s a mixed bag, but most of the data is pretty good.</p>

<h3 id="nordics">Nordics</h3>

<p>I know we already covered Europe, but I did enjoy looking at the Nordic data. Norway stood out as one of the few sources I found carrying Z coordinates in its national road-link geometry, and I think that’s great. It tells a real story of the region’s layout and the importance of the topography.</p>

<h2 id="a-section-50-aside">A Section 50 aside</h2>

<p><img src="/assets/posts/streetworks-sdk/section-50.png" alt="Screenshot of an example Section 50 application page built against the Street Manager API" />
<em>The top half of an example Section 50 application page, for use with the Street Manager API.</em></p>

<p>I included this as a “why not” to provoke a little discussion, because the current Section 50 process is, in my opinion, somewhat outdated. Street Manager handles Section 50s, so why not use it as a Section 50 management platform? The free-text fields aren’t exposed in the open data publication, so why not use them to store webpage-calculated bonds and contacts?</p>

<p>This isn’t a recommendation, to be clear — just an observation that we have a pretty good national system that could be used to handle S50 management. The full example application page, along with the HTML and Python, is in the repository examples.</p>

<h2 id="worker-safety-and-road-worker-abuse">Worker safety and road worker abuse</h2>

<p><img src="/assets/posts/streetworks-sdk/worker-safety-map.png" alt="Map showing roadworks sites overlaid with historic crime data to indicate abuse risk" />
<em>Road worker safety and abuse risk map example, from the <a href="https://github.com/KFergusonUK/StreetWorks-SDK/blob/main/docs/examples.md">repository examples</a>.</em></p>

<p>Some might be slightly confused as to why I’ve included the UK Police Crime API in a streetworks SDK, but I see the two as often sadly interlinked. Road crews are often subject to verbal and sometimes physical assault. If we’re able to use the data to help determine whether a worksite sits in an area where additional safety measures might be appropriate, based on historic crime levels, then while it won’t guarantee nothing happens, perhaps measures could be put in place to reduce the likelihood of an incident — visible camera presence, a change of working hours.</p>

<p>Roadworks can be frustrating for us all, and I’m sure we’ve all seen someone “just standing around” “making us late” on a worksite. There are often good reasons for this, and after the summer we just had, I’m surprised more aren’t sat eating ice creams.</p>

<h2 id="busy-is-relative">Busy is relative</h2>

<p>I included a slightly silly comparison: Durham City and Paris. For those who don’t know, Durham is a small cathedral city in northern England with a population of around 50,000, covering about 15 km². Paris is a European capital with a population of around two million, covering about 105 km².</p>

<p>At the time there were 18 active streetworks in Durham City — quite a busy day, I thought. Then I loaded up Paris, with over 1,800 active roadworks. I went back to check the Paris feed was working properly and that this wasn’t every API feed Paris had. No: active works only. I suspect Paris hardly felt the difference either.</p>

<p>“Busy” really is relative.</p>

<p><img src="/assets/posts/streetworks-sdk/durham-vs-paris.png" alt="Side-by-side comparison of active works in Durham City and Paris" /></p>

<h2 id="code-examples">Code examples</h2>

<p>Two systems that share no schema, no standard, and no language — the United States (WZDx) and Spain (DATEX II). Run each through its converter and the same caller code handles both, unchanged:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">streetworks.common</span> <span class="kn">import</span> <span class="n">from_datex2</span><span class="p">,</span> <span class="n">from_wzdx</span>
<span class="kn">from</span> <span class="nn">streetworks.datex2.dgt</span> <span class="kn">import</span> <span class="n">DGTClient</span>   <span class="c1"># Spain  (DATEX II)
</span><span class="kn">from</span> <span class="nn">streetworks.wzdx</span> <span class="kn">import</span> <span class="n">WZDxClient</span>        <span class="c1"># USA    (WZDx)
</span>
<span class="c1"># United States: Washington State DOT (WZDx)
</span><span class="k">with</span> <span class="n">WZDxClient</span><span class="p">()</span> <span class="k">as</span> <span class="n">wzdx</span><span class="p">:</span>
    <span class="n">feed</span> <span class="o">=</span> <span class="n">wzdx</span><span class="p">.</span><span class="n">fetch</span><span class="p">(</span><span class="s">"https://wzdx.wsdot.wa.gov/api/v4/WorkZoneFeed"</span><span class="p">)</span>
<span class="n">us_works</span> <span class="o">=</span> <span class="n">from_wzdx</span><span class="p">(</span><span class="n">feed</span><span class="p">.</span><span class="n">road_events</span><span class="p">,</span> <span class="n">territory</span><span class="o">=</span><span class="s">"USA"</span><span class="p">,</span>
                     <span class="n">administrative_area</span><span class="o">=</span><span class="s">"Washington"</span><span class="p">)</span>

<span class="c1"># Spain: DGT national roadworks (DATEX II)
</span><span class="k">with</span> <span class="n">DGTClient</span><span class="p">()</span> <span class="k">as</span> <span class="n">dgt</span><span class="p">:</span>
    <span class="n">es_works</span> <span class="o">=</span> <span class="p">[</span><span class="n">from_datex2</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">territory</span><span class="o">=</span><span class="s">"Spain"</span><span class="p">)</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">dgt</span><span class="p">.</span><span class="n">iter_roadworks</span><span class="p">()]</span>

<span class="c1"># Two unrelated standards — now the same shape. Identical code handles both.
</span><span class="k">for</span> <span class="n">works</span> <span class="ow">in</span> <span class="p">[</span><span class="o">*</span><span class="n">us_works</span><span class="p">,</span> <span class="o">*</span><span class="n">es_works</span><span class="p">]:</span>
    <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">works</span><span class="p">.</span><span class="n">sites</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="n">works</span><span class="p">.</span><span class="n">territory</span><span class="p">,</span> <span class="n">site</span><span class="p">.</span><span class="n">works_type</span><span class="p">,</span> <span class="n">site</span><span class="p">.</span><span class="n">date_confidence</span><span class="p">)</span>
</code></pre></div></div>

<p>And the point I care about most — the common model sits over the top, but the native data is never flattened away:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">works</span> <span class="o">=</span> <span class="n">es_works</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">site</span> <span class="o">=</span> <span class="n">works</span><span class="p">.</span><span class="n">sites</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>

<span class="k">print</span><span class="p">(</span><span class="n">site</span><span class="p">.</span><span class="n">works_type</span><span class="p">)</span>       <span class="c1"># common model — one name for every provider
</span><span class="k">print</span><span class="p">(</span><span class="n">site</span><span class="p">.</span><span class="n">date_confidence</span><span class="p">)</span>  <span class="c1"># ...and honest about how sure the source is
</span>
<span class="c1"># Nothing is thrown away. .raw points back at the exact source record(s),
# in their own structure and language, always still there.
</span><span class="k">print</span><span class="p">(</span><span class="n">works</span><span class="p">.</span><span class="n">raw</span><span class="p">)</span>             <span class="c1"># the untouched payload, as Spain sent it
</span></code></pre></div></div>

<h2 id="what-could-you-build-with-it">What could you build with it?</h2>

<p>The SDK isn’t really the end product. It’s the plumbing underneath whatever comes next. A few obvious possibilities:</p>

<ul>
  <li><strong>Roadworks-aware routing</strong> — route around active works, closures or restrictions</li>
  <li><strong>Network monitoring</strong> — bring works from multiple authorities into one view</li>
  <li><strong>Cross-border applications</strong> — build something once and use the same model across different countries</li>
  <li><strong>Street works analytics</strong> — compare works, durations, impacts and patterns across authorities</li>
  <li><strong>Site safety tools</strong> — combine works locations with other datasets, such as historic crime data, to inform site-specific safety measures</li>
  <li><strong>Digital twins and 3D applications</strong> — use street geometry and elevation data to model the physical environment</li>
  <li><strong>Asset management</strong> — combine works and gazetteer information with other infrastructure datasets</li>
  <li><strong>AI agents</strong> — give an agent a consistent way to discover and consume roadworks data without having to understand every provider’s API first</li>
  <li><strong>Automated decision-making</strong> — feed standardised works data into systems that need to react to changes in the road network</li>
  <li>Anything else someone hasn’t thought of yet</li>
</ul>

<p><img src="/assets/posts/streetworks-sdk/av-reroute.png" alt="Autonomous vehicle rerouting example generated from SDK data" />
<em>An AV rerouting example from the <a href="https://github.com/KFergusonUK/StreetWorks-SDK/blob/main/docs/examples.md">repository</a> — not perfect, but a nice visual of what’s possible.</em></p>

<p>And that’s really the point. I don’t want to decide what StreetWorks-SDK is for. I want to make the data easy enough to use that other people can decide.</p>

<h2 id="where-this-goes-next">Where this goes next</h2>

<p>The SDK is open source, MIT licensed, and on PyPI — <code class="language-plaintext highlighter-rouge">pip install streetworks</code> — with the code at <a href="https://github.com/KFergusonUK/StreetWorks-SDK">github.com/KFergusonUK/StreetWorks-SDK</a>.</p>

<p>It’s a genuine work in progress. NUAR is modelled but not yet live, as it needs formal access I don’t have in a personal capacity. Several feeds are sat waiting on credentials, and there are whole countries I haven’t reached yet. The provider matrix will keep moving.</p>

<p>I should be clear that this is a personal project, built in my own time and separate from my day job. Any views here are my own, and nothing in it speaks for my employers.</p>

<p>The original idea came from a conversation with Christopher Carlon, likely over WhatsApp, where we considered how nice it would be to have a ready-made SDK for streetworks in the UK, and I sort of got carried away. What started as “wouldn’t it be nice if someone made this?” became “hang on, what does Sweden do?” Then: what about Spain? Then: does Australia have anything? Then: do all US states do this the same?</p>

<p>And somewhere along the way, the project became global. I’m still investigating.</p>

<p>If you work with roadworks, street, or address gazetteer data — or you maintain a feed that should be in here — I’d genuinely like to hear from you. Tell me what’s missing, tell me what I’ve got wrong, clone the repo, add something and submit a pull request, or just tell me your country does something interesting with Z coordinates. And if you build something on top of it, even better.</p>

<p>That was always the point: handle the boring plumbing, so there’s time left over for the interesting ideas.</p>

<p>Thank you to the people who have submitted pull requests to the project so far — Christopher Carlon and Jamie Atkinson. Your assistance is very much appreciated.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[The StreetWorks SDK now pulls from over 130 official sources worldwide. What I found along the way about how differently countries handle roadworks data — and how fortunate England is.]]></summary></entry><entry><title type="html">The future of street works: AI, automation and robotics</title><link href="https://kfergusonuk.github.io/2025/12/01/future-of-street-works.html" rel="alternate" type="text/html" title="The future of street works: AI, automation and robotics" /><published>2025-12-01T00:00:00+00:00</published><updated>2025-12-01T00:00:00+00:00</updated><id>https://kfergusonuk.github.io/2025/12/01/future-of-street-works</id><content type="html" xml:base="https://kfergusonuk.github.io/2025/12/01/future-of-street-works.html"><![CDATA[<!-- DATE: approximate — LinkedIn only gave "9 months ago". If you can
     pin it down, change the date field above AND the filename, and update
     the link on index.md, since the URL is built from the date. -->

<p>I firmly believe street works is about to change more in the next five years
than it has in the last twenty.</p>

<p>We’re entering a genuinely transformative phase. A lot of what we think of
as “future tech” is already live, being trialled, or about to hit
production. Examples already in the real world include:</p>

<ul>
  <li>Automated works plans from platforms like 1Streetworks and Causeway
one.network</li>
  <li>AI-assisted permit application and assessment emerging from suppliers like
Triopsis</li>
  <li>Automated site setup using systems like Highway Care’s Falcon</li>
  <li>Automated excavation such as SGN’s RRES, scanning and digging with high
precision</li>
  <li>Automated site inspection using technology from companies like Vaisala</li>
</ul>

<p>It’s exciting to see how quickly the industry is moving.</p>

<h2 id="the-part-that-decides-whether-any-of-it-works">The part that decides whether any of it works</h2>

<p>As these tools grow in capability and begin to connect to each other, one
thing becomes increasingly important: AI and automation depend heavily on
the quality and clarity of the data behind them.</p>

<p>This isn’t a criticism of data and systems teams — far from it. They’re
building the foundations the future will rest on. NSG custodians, mapping
specialists and others already do a huge amount, often with limited
resources.</p>

<p>It’s simply the reality that AI can only make safe decisions when the
underlying datasets are accurate and can connect to each other — via unique
keys such as USRNs — for cross-validation. Only then can the data truly
support those decisions.</p>

<p>Consider an AI system determining traffic management or drafting a permit
from incorrect assumptions: speed limits, road type, constraints, geometry,
surrounding assets. The output can only ever mirror the data it was given.</p>

<h2 id="and-when-something-goes-wrong">And when something goes wrong?</h2>

<p>If something fails in a fully automated process, who is legally responsible?
The highway authority? The utility? The NSG custodian? The software or AI
supplier? All of them?</p>

<p>That question doesn’t have a settled answer yet, and it’s one of the reasons
I think the near-term future looks more measured than the technology alone
would suggest.</p>

<h2 id="where-i-think-this-lands">Where I think this lands</h2>

<p>For structured tasks — planning, permit drafting, robotic excavation — AI
has a huge role to play: reducing workload, improving consistency, and
increasing safety.</p>

<p>But humans remain overseers. Picking up on collaborative opportunities, or
local context from residents that an algorithm can’t hear over a coffee. The
AI takes the day-to-day work; the humans add the high-value, human-focused
work.</p>

<p>For final coordination and safety-critical approvals, the safest model right
now is a simple one:</p>

<p><strong>AI assists. Humans decide.</strong></p>

<p>Innovation in our sector is something I genuinely love, and I think we’re
entering a very exciting moment. We just need to bring the technology
forward in a way that is safe, realistic, and grounded in how street works
actually functions day to day.</p>

<p>If you work in this space, I’d be interested to know which part of this
future feels closest to you.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Street works is about to change more in the next five years than it has in the last twenty. Much of what we think of as future tech is already live — and all of it rests on data quality nobody sees.]]></summary></entry></feed>