# Kyvern: signed, verifiable records of why your robot did what it did (ROS 2 example)

**URL:** <https://discourse.openrobotics.org/t/kyvern-signed-verifiable-records-of-why-your-robot-did-what-it-did-ros-2-example/58711>\
**Category:** Projects\
**Created:** [October 8, 2026, 8:46pm UTC](https://discourse.openrobotics.org/t/kyvern-signed-verifiable-records-of-why-your-robot-did-what-it-did-ros-2-example/58711 "2026-10-08T20:46:16Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![altunbulakemre75](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/altunbulakemre75/32/33981_2.png) [@altunbulakemre75](https://discourse.openrobotics.org/u/altunbulakemre75)\
**Post date:** [October 8, 2026, 8:46pm UTC](https://discourse.openrobotics.org/t/kyvern-signed-verifiable-records-of-why-your-robot-did-what-it-did-ros-2-example/58711/1 "2026-10-08T20:46:16Z")

</div>

Hi all,

In May I asked here where “why did the robot do that?” gets answered  
( [The accountability gap in ROS2: where does "why did the robot do that?" get answered?](https://discourse.openrobotics.org/t/the-accountability-gap-in-ros2-where-does-why-did-the-robot-do-that-get-answered/54841) ).  
This is what came out of that discussion so far: Kyvern, an Apache-2.0 Python  
library that records a robot’s own decisions in a signed, hash-linked chain  
that someone outside your team can verify.

What it does

- Your controller keeps its own logic. When it decides (or, at 10 Hz, when  
its decision changes) it calls record\_decision(): the action, the rule that  
fired, the inputs it was based on, and the SHA-256 of the policy file in  
force.
- Every entry is Ed25519-signed and hash-linked. kyvern-anchor timestamps the  
chain head with an RFC 3161 authority, so rewriting anchored entries is  
detectable even by whoever holds the key, as long as the receipts are kept  
off the host.
- kyvern-verify checks the chain offline against your policy file(s).  
kyvern-report produces a PDF of checks mapped to EU AI Act Articles 12 and  
14; each row is computed from the chain or marked “not assessed”.
- Upstream components (guards, monitors) can sign their own records into the  
same chain as events.

ROS 2 example  
examples/ros2\_safety\_demo is a LaserScan-based safety controller  
(/scan → /safety/action) that decides stop / slow / continue from its own  
policy YAML and records every change of action. It also runs without ROS 2:

```auto
pip install .
python examples/ros2_safety_demo/run_demo.py --anchor

```

Then edit one record in the chain and run kyvern-verify again.

Limits

- It records and verifies; it does not gate commands. (For that piece, see  
JakPot42’s Sentinel Ledger in the thread above.)
- Without anchors, deleting entries from the end of a chain is not  
detectable; kyvern-verify --require-anchors makes that a failure.
- It is a Python library with an example node, not yet a ROS 2 package, and  
the node has not run on a real robot.
- Alpha, not certified, not a safety system. The report supports an  
assessment; it does not make anything compliant. For many robots the  
Machinery Regulation 2023/1230 is the more direct obligation than the AI  
Act; that mapping is not built yet.
- Built with an AI coding assistant; I review the specs, the tests and the results.”

What I’d like to learn

- What would you need recorded for your own safety controller: which inputs,  
which topics?
- Is JSON on std\_msgs/String good enough, or would a message type or a  
rosbag2 storage plugin fit better?
- Would anyone try it on a real AMR stack? I’ll help with the integration.

Repo: [GitHub - altunbulakemre75/kyvern: Decision provenance and accountability infrastructure for autonomous systems · GitHub](https://github.com/altunbulakemre75/kyvern)  
Docs: [Kyvern](https://altunbulakemre75.github.io/kyvern/)
