Install
openclaw skills install @yankhy-source/ratsinfo-deRead German municipal council records through the OParl API. Use when someone asks what a German town, city or district decided, planned, tendered or discussed, when they name a German municipality together with a topic such as a school renovation, a building project, a budget, a wind farm or a tender, when they ask what became of a council paper, who sits on a committee, or when they want to be told about new council papers on a subject.
openclaw skills install @yankhy-source/ratsinfo-deGerman municipalities publish their council papers, decisions and meeting agendas in a Ratsinformationssystem, a council information system. Around one to two hundred of them expose a machine readable interface called OParl. This skill reads it politely, answers the questions people actually have, and tells you honestly when it cannot.
Everything runs through one dependency free script:
scripts/ratsinfo.py, Python standard library only, no installation.
Network access: the script talks to the OParl endpoint you name and to
the public endpoint registry at dev.oparl.org. Nowhere else. It sends no
credentials, reads no local files apart from its own cache under
~/.cache/ratsinfo-de, and writes nothing outside that cache except an
iCalendar file when you explicitly ask for one.
| The question | The command |
|---|---|
| Does this town publish anything machine readable? | find <town>, then check <endpoint> |
| What has the council discussed about X? | papers <endpoint> --term X --since <date> |
| What became of this paper? Was it decided? | track <paper-url> |
| Tell me when something new comes up about X | watch <endpoint> --term X |
| When does the committee next meet? | meetings <endpoint> --days 60 or watch --kind meeting --ics |
| Who sits on which committee, since when? | people <endpoint> |
| Is this one council or a whole district? | bodies <endpoint> |
| Where, across many towns, is something moving on my subject? | scan --term X --pdf marktbericht.pdf |
| Give me a document I can file or send | report <paper-url> --pdf akte.pdf |
| Give me the raw object | get <url> |
Every command takes --json. Use it. The tables are for humans.
Work in this order. Skipping the health check is the single most common way to waste an hour on a dead endpoint.
python3 scripts/ratsinfo.py find Münster
Searches the official registry, cached for a week. A miss does not mean
the town has no endpoint. The registry holds around 127 entries, contains
duplicates and dead hosts, and is a lower bound rather than a census. If
find comes up empty, try the vendor URL patterns in
references/vendors.md, which are stable per vendor.
python3 scripts/ratsinfo.py check https://oparl.stadt-muenster.de/system
Prints the OParl version, the software product, the operator's contact
address, the licence, every body the endpoint serves, and the official
municipality key (ags, rgs) where the system states one. That key is
what lets a result be joined to population, election or budget data later.
Read the contactEmail. It is the fastest route to permission when
something is blocked, and writing to it is cheaper than working around a
block.
If more than one body appears, a Kreis or a Verbandsgemeinde is serving
several councils from one endpoint. bodies lists them, --body N selects
one. Silently taking the first is how you end up searching the wrong
council.
python3 scripts/ratsinfo.py papers https://oparl.stadt-muenster.de/system \
--term Sanierung --term Schule --since 2026-01-01
--term may be repeated and all terms must match.
Then the part that matters. A list of papers is not an answer, because the obvious next question is always the same: what became of it?
python3 scripts/ratsinfo.py track https://oparl.stadt-muenster.de/paper/12345
track walks the chain the specification provides, Paper to Consultation
to AgendaItem to Meeting, and prints the paper's route through the
committees as a timeline: which committee, on what date, in what role, with
what result, and which consultation was the authoritative one. It ends with
a plain status line, for example decided on 2026-03-10: beschlossen, or
pending since 2026-02-11, or no consultation recorded, this paper was never tabled.
No council frontend answers that question in one view. It is pure metadata, so it costs no PDF reading, and it is usually the answer the person wanted in the first place.
python3 scripts/ratsinfo.py watch <endpoint> --term Radverkehr
python3 scripts/ratsinfo.py watch <endpoint> --kind meeting --ics rat.ics
watch keeps a small state file per endpoint and asks the server for
modified_since the last run, which is the only server side filter OParl
offers and the one the specification obliges every server to support. On
each run it reports what is new and what has been withdrawn, and it honours
the soft delete flag, so a paper pulled from the agenda shows up as GONE
rather than silently disappearing. --ics writes an iCalendar file, which
is the only form in which a council date is useful, namely before it
happens. It is safe to run from cron. Use --dry-run to look without
advancing the state.
One town is rarely the question. A business wants to know where, across a region, something is moving on its subject.
python3 scripts/ratsinfo.py scan --term Schule --term Sanierung \
--days 180 --max-endpoints 25 --pdf marktbericht.pdf --org "Your firm"
scan walks the public endpoint registry (or a file of endpoints you
supply with --endpoints), health checks each municipality, searches its
papers, and writes a market report grouped by town with the official
municipality key, the responsible department and a link to every source.
It reports the endpoints it could not read, by name and with the reason. That is deliberate: a silent gap looks like "nothing is happening there", and this data is far too patchy for that to be an honest reading.
python3 scripts/ratsinfo.py report <paper-url> \
--pdf vorlage-27-2026.pdf --logo logo.png --org "Your organisation"
Writes a one page PDF dossier in German: the paper, its status, and its
route through the committees as a timeline, with the source, the retrieval
time and a note on the legal position in the footer. That is the artefact
people keep, put in a project file, or send to a client. --logo takes a
PNG and is optional, --org sets the name in the header.
The PDF writer is part of this skill (scripts/pdfreport.py), about three
hundred lines using only zlib and the base fourteen fonts. Nothing to
install, which is the whole point.
Say this to the user plainly instead of guessing around it.
No construction cost, no design stage, no budget line. These are the commercially valuable fields and OParl carries none of them. They appear, when at all, in the text of the paper itself. This skill prints the file URL and refuses to estimate. Any tool that hands you a figure here either read the PDF or invented it.
Tenders are not in here. Council records are the early indicator, months or years ahead. The actual procurement notices live in a separate system, the Datenservice Oeffentlicher Einkauf, in the OCDS format under CC0, and on TED above the EU thresholds. Point the user there for award values, CPV codes and deadlines.
No contact data of individuals. OParl's Person object does carry
email and phone, and this skill deliberately does not output them.
Those addresses are published so that citizens can reach their
representatives. Using them for acquisition is a change of purpose, and
German case law is clear enough about it that the polite route, the
function address of the responsible department, is also the safer and
more effective one.
There is no full text search. OParl offers no search parameter at
all. --term filters titles and reference numbers on the client side
after downloading the list. A paper whose subject appears only inside the
attached PDF will not be found. When that matters, take the file URL from
the output, fetch the PDF and read it.
Coverage is thin. Council information systems are near universal in Germany, OParl is not. The order of magnitude is one to two hundred endpoints against thousands of municipalities. For most towns someone asks about there will be no endpoint, and the honest answer is that this town's records are not machine readable, not that nothing was decided.
CC e-gov ALLRIS is effectively closed. Those installations answer with an HTML bot check page that needs a browser session. The script recognises the page and stops instead of retrying.
Some operators disallow their own API in robots.txt. Usually a
blanket rule aimed at search engines that catches the API path by
accident. The script honours it and stops. --ignore-robots exists for
the case where the operator has said yes in writing, and for no other
case.
Big cities need a date floor. Without --since or --days you are
paging through years of records at one request per second.
Non public sessions stay non public. If a system leaks them, that is not a licence to use them.
--max-pages to brute force a missing full text search.
Fetch the PDFs of the few plausible hits instead.track would give the real
one.--ignore-robots is the only switch that loosens a restriction, it is
never the default, and it is not a workaround for the ALLRIS bot check.--ics file you
name yourself.http and https are accepted. A file:// or ftp:// link in a
server response is refused, not followed.--allow-cross-host lifts that, deliberately and loudly.RATSINFO_USER_AGENT sets the identifying user agent, and you should.
RATSINFO_MIN_INTERVAL, RATSINFO_TIMEOUT, RATSINFO_CACHE and
RATSINFO_REGISTRY exist for the test suite. Lowering the interval against
a real municipality is the one thing this skill asks you not to do.
Council sessions are public by law and the documents of the public part are meant to be read. That is not the same as free to republish. Attachments such as expert reports, photographs and plans often carry third party copyright, and paper texts routinely name private individuals who were never public figures. A full text index of those names changes their situation without asking them.
Read the license field, keep the source with every document you store,
and think before you publish. references/recht-und-etikette.md has the
detail and the sources, in German, because the law is German.