Skip to content

Kyvern

Build License Python Status EU AI Act

Decision provenance and accountability infrastructure for autonomous systems.

When an autonomous system makes a consequential decision — a robot stops mid-motion, a vehicle reroutes, an actuator fires — what happened is usually loggable. Why it happened, in a form a safety officer, regulator, or court can read, is almost always reconstructed after the fact, by hand.

Kyvern is the missing layer:

  • Records your system's own decisions. record_decision() signs what your robot, planner or operator decided, why, on which inputs and under which version of your policy, into a verifiable chain. Your decision logic stays yours.
  • Optional rule-first decision engine. Kyvern's own engine traces every action back to a human-authored policy. AI advises; rules decide.
  • Cryptographically signed audit chain. Every decision is recorded with full provenance: which rule fired, which inputs triggered it, which guardrails ran, what was downgraded. Linked via Ed25519 signature.
  • Guardrail-downgrade-only pattern. Safety layers can only make decisions safer, never more dangerous. Mathematically enforced.
  • LLM advisor with prompt injection defense. Models suggest; they do not act. Adversarial inputs are sanitized before reaching the decision boundary.
  • Air-gap deployable. Runs fully offline with local model fallback. No data leaves the deployment environment.

Status

Pre-1.0. Core engine and audit chain are battle-tested in a private deployment (separate codebase). This repository is the generalized, domain-neutral open-core extraction.

Active areas: recording a system's own decisions, the ROS2 safety-controller demo, the MCP server interface, EU AI Act evidence reports.

Recording your own decisions

Install from a clone of the repository (pip install .), then record a decision your system made:

from kyvern import record_decision

record_decision(
    "stop",                                   # what your system did
    source="safety_controller",               # who decided ("operator" for a person)
    reasoning="obstacle at 0.4 m, closer than 0.5 m",
    inputs={"obstacle_distance_m": 0.4},      # what it was based on (up to 64 KB)
    rule_id="stop-on-obstacle",               # the rule in your policy that fired
    policy_path="safety_policy.yaml",         # binds the decision to that policy version
)

The policy is your own YAML file with a rules: list; Kyvern records the SHA-256 of its content with each decision. The decision is signed and appended to ~/.kyvern/chain.jsonl (or $KYVERN_CHAIN_PATH) and can then be verified, anchored and reported on.

Verifying decisions

For auditors and compliance officers, the decision provenance chain can be verified offline without writing code:

kyvern-verify chain.jsonl --policy config/policies/default.yaml --pubkey ~/.kyvern/keys/signing.pub

Output:

✓ Chain integrity: VALID (3 decisions, 1 runtime events, all signed)
✓ Policy match: 5b64432b2dd0796f (default.yaml @ 2026-10-08 04:51 UTC): 3 decisions
✓ Signature verification: PASSED (Ed25519)
  Anchors: none (no chain.anchors.jsonl)

Decision summary:
  [0] 14:32:07  action=LOG     rule_id=POL-1  guardrails=[input-single-tick]
  [1] 14:32:09  action=ALERT   rule_id=POL-2  guardrails=[]
  [2] 14:32:12  event=sensor_anomaly source=imu_monitor
  [3] 14:32:15  action=ALERT   rule_id=POL-2  guardrails=[]

Audit hash: 5b64432b2dd0796f (verifiable against deployed policy)

EU AI Act evidence reports

Generate a PDF of checks run on a signed decision chain, mapped to the EU AI Act Articles they support: Article 12 (record-keeping) and Article 14 (human oversight):

kyvern-report chain.jsonl \
    --policy config/policies/default.yaml \
    --pubkey ~/.kyvern/keys/signing.pub \
    --output report.pdf \
    --system-id "AMR-Fleet-A" \
    --operator "Operations Team"

The PDF covers chain integrity, the policy check, action and threat-level distribution, the Article 12 and 14 checks, the policy version timeline, and a fingerprint of the report content. Each check is computed from the chain (PASS/FAIL with counts) or marked NOT ASSESSED where a chain cannot show it, such as whether an operator can override the system. The report supports an assessment; it does not establish conformity. See EU AI Act.

MCP server (Claude Desktop)

Plug Kyvern into Claude Desktop in ~30 seconds and ask questions like "what did my autonomous system do in the last hour?":

Kyvern is not published on PyPI yet, so install from source:

git clone https://github.com/altunbulakemre75/kyvern.git
cd kyvern
pip install -e ".[mcp]"

Then add to your Claude Desktop config:

{
  "mcpServers": {
    "kyvern": {
      "command": "kyvern-mcp",
      "args": ["--chain-file", "/path/to/chain.jsonl", "--pubkey", "/path/to/signing.pub"]
    }
  }
}

Five read-only tools (query_events, get_event, get_stats, verify_chain, search_events) and four resources cover signed audit query, chain verification, and active-policy metadata. See MCP integration.

Integrations

ROS2 safety-controller demo: a robot's own stop / slow / continue decisions, recorded with record_decision() from a /scan subscriber, then verified and reported. It runs without ROS2 too. See examples/ros2_safety_demo.

ROS2 bridge: publishes signed Decision objects to a ROS2 topic for consumption by autonomous systems. See ROS2 integration.

Architecture

See Architecture for the full design: components, data flow, audit chain implementation (Ed25519 + SHA-256 hash chain), the guardrail downgrade-only invariant, and integration points.

Security

Kyvern defends against two primary threats: insider post-hoc tampering of decision history (Ed25519 + SHA-256 hash chain) and AI-induced unsafe escalation (LLM advisory ceiling + guardrail downgrade-only invariant).

It does not defend against signing key compromise, sensor-level deception, runtime intrusion, or network attacks — those are operator responsibilities.

See Threat Model for the full threat model, including explicit non-defenses and what this means for compliance claims.

Roadmap

  • [x] EU AI Act Article 12 & 14 evidence report (cli/kyvern_report.py)
  • [x] ROS2 publisher (services/integrations/ros2_bridge.py)
  • [ ] ROS2 action sink with feedback loop (planned)
  • [x] MCP server interface (kyvern/mcp/, kyvern-mcp)
  • [ ] IMM filter as default in TrackManager
  • [ ] OpenAI provider in LLM chain
  • [ ] Internationalization of in-code documentation (Turkish → English)

License

Apache 2.0.

Contact

Discussion on Open Robotics Discourse or open a GitHub issue.