EU AI Act classifies autonomous vehicles as high-risk (Annex III, category 3a). Open VLA models have democratized autonomous driving development. Every company fine-tuning these models for production needs accountability infrastructure for safety-critical trajectory decisions. The same record-keeping and transparency obligations that apply to cloud AI apply to every path planning decision a vehicle makes.
Who this is for: AV engineers deploying VLA models (Alpamayo, EMMA, FSD, SuperVision, or custom), safety engineers responsible for ISO/PAS 8800 compliance, compliance teams governing EU AI Act high-risk systems, robotics developers building path planning pipelines, and assessors evaluating autonomous AI decision-making systems.
New to SWT3? SWT3 is a cryptographic accountability protocol for AI systems. When your model makes a decision, the SDK mints a witness anchor -- a tamper-evident fingerprint proving what happened, when, and whether it passed validation. Anchors are organized by procedures (numbered evidence types like AI-MOB.6) and each procedure records three factors (numeric values with defined meanings). Clearing levels (0-3) control how much context metadata accompanies the anchor, from full detail to factors-only. Full SDK documentation.
1. Why Autonomous AI Needs Accountability
Your vehicle's planning model makes 10-30 trajectory decisions per second. Each one is a safety-critical action that regulators can ask you to explain. When an assessor, a regulator, or an accident investigator asks "what did the AI decide at 14:32:07 and why?" -- the answer needs to be a verifiable record, not a log file.
Open-weight VLA (Vision-Language-Action) models released under permissive licenses have lowered the barrier to building autonomous driving systems. Startups can fine-tune a 34-billion-parameter foundation model and distill it to edge hardware. The technology is accessible. The accountability infrastructure is not.
Three regulatory frameworks converge on this gap:
- EU AI Act Annex III(3a) explicitly lists autonomous vehicles as high-risk AI systems. Article 9 requires documented risk management. Article 12 requires automatic logging of events relevant to identifying risks. Article 15 requires accuracy, robustness, and cybersecurity measures.
- ISO/PAS 8800 is the harmonized standard for road vehicle AI safety. Clauses 6-10 cover the full lifecycle from design to deployment, including trajectory validation and operational safety classification.
- UNECE WP.29 Regulation 157 governs automated lane-keeping systems and requires evidence of system behavior during operation -- what the AI decided, when, and why.
Key principle: SWT3 witnesses the decision, not the trajectory. Context stores only cryptographic hashes and counts -- never raw coordinates, waypoints, or proprietary causal reasoning traces. The anchor proves the decision happened and whether it passed safety validation. The raw data stays in your system.
SWT3 provides two procedures for autonomous AI governance:
- AI-MOB.6 (Trajectory Decision Attestation) -- witnesses that a VLA or planning model produced a trajectory and whether it passed safety validation
- AI-MOB.7 (VLA Inference Witnessing) -- wraps any VLA inference function to capture timing, success/failure, and I/O hashes transparently
2. Trajectory Decision Attestation (AI-MOB.6)
Every trajectory decision your planning model makes can be witnessed with a single method call. The anchor records whether the trajectory passed safety validation, its classification level, and optional provenance metadata -- all as hashes, never raw data.
Python
import hashlib
from swt3_ai import Witness
witness = Witness(
endpoint="https://sovereign.tenova.io",
api_key="axm_live_...",
tenant_id="YOUR_TENANT",
)
# Hash your trajectory data before witnessing -- raw data never leaves your system
traj_hash = hashlib.sha256(trajectory_bytes).hexdigest()
coc_hash = hashlib.sha256(reasoning_trace_json.encode()).hexdigest()
witness.witness_trajectory(
safety_validated=True,
waypoint_count=47,
trajectory_hash=traj_hash,
coc_trace_hash=coc_hash,
action_class="navigate",
safety_classification="nominal",
sensor_sources=["camera_front", "camera_rear", "lidar_top", "radar"],
model_id="alpamayo-2-super",
)
Failure behavior: witness_trajectory() never blocks or throws on network errors. If the clearing house is unreachable, the payload is buffered in the local write-ahead log (WAL) and flushed when connectivity returns. Your inference loop is never interrupted by witnessing failures.
TypeScript
import { createHash } from "node:crypto";
import { Witness } from "@tenova/swt3-ai";
const witness = new Witness({
tenantId: "YOUR_TENANT",
apiKey: "axm_live_...",
});
// Hash locally -- raw trajectory data never leaves your system
const trajHash = createHash("sha256").update(trajectoryBytes).digest("hex");
const cocHash = createHash("sha256").update(reasoningTraceJson).digest("hex");
witness.witnessTrajectory({
safetyValidated: true,
waypointCount: 47,
trajectoryHash: trajHash,
cocTraceHash: cocHash,
actionClass: "navigate",
safetyClassification: "nominal",
sensorSources: ["camera_front", "camera_rear", "lidar_top", "radar"],
modelId: "alpamayo-2-super",
});
MCP (Model Context Protocol)
// Any MCP client can call the witness_trajectory tool:
{
"tool": "witness_trajectory",
"arguments": {
"safety_validated": true,
"waypoint_count": 47,
"trajectory_hash": "a1b2c3d4e5f6...",
"action_class": "navigate",
"safety_classification": "nominal",
"sensor_sources": ["camera_front", "lidar_top"],
"model_id": "alpamayo-2-super"
}
}
Factor Semantics
| Factor | Label | Value | Regulatory Ref |
|---|---|---|---|
factor_a | attestation_required | 1.0 (required by policy) | EU AI Act Annex III(3a) |
factor_b | safety_validated | 1.0 = passed, 0.0 = failed | EU AI Act Art. 9(2)(a) |
factor_c | safety_classification | 0-5 enum (see Section 4) | ISO/PAS 8800 Cl. 8 |
What Gets Stored at Each Clearing Level
Full context: model_id, safety_validated, safety_classification, waypoint_count, trajectory_hash, coc_trace_hash, coc_node_count, action_class, sensor_count, sensor_sources list.
Reduced: model_id, provider_category ("trajectory"), sensor_count only. No trajectory hash, no CoC trace, no sensor names.
Factors only. model_id is hashed (SHA-256 truncated). No context metadata. The anchor proves a trajectory decision was made and its safety classification. Nothing else.
3. VLA Inference Wrapping (AI-MOB.7)
Wrap any VLA inference function and every call is witnessed automatically. The wrapper captures timing, input/output hashes, and success/failure. It works with any callable -- not coupled to any specific model API or framework.
Python -- Wrapper Pattern
from swt3_ai import Witness
witness = Witness(tenant_id="YOUR_TENANT", api_key="axm_live_...")
# Wrap any inference function
infer = witness.wrap_vla(model.predict, model_id="alpamayo-2-super")
# Every call is now witnessed (AI-MOB.7)
trajectory = infer(camera_frames)
Python -- Decorator Pattern
@witness.wrap_vla(model_id="alpamayo-2-super")
def predict(frames):
return model.forward(frames)
# Each call mints an AI-MOB.7 anchor automatically
trajectory = predict(camera_frames)
TypeScript
import { Witness } from "@tenova/swt3-ai";
const witness = new Witness({ tenantId: "YOUR_TENANT" });
const infer = witness.wrapVLA(model.predict, "alpamayo-2-super");
// Sync or async -- both work transparently
const trajectory = await infer(cameraFrames);
Factor Semantics
| Factor | Label | Value | Regulatory Ref |
|---|---|---|---|
factor_a | inference_occurred | 1.0 | EU AI Act Art. 12(1) |
factor_b | latency_ms | Inference latency in ms | EU AI Act Art. 15(1) |
factor_c | succeeded | 1 = success, 0 = exception | EU AI Act Art. 9(4)(b) |
Zero-copy frame handling: The wrapper never hashes raw camera frames. At 1920x1080x3 per frame across 6-12 cameras at 10-30 FPS, hashing pixel data would add 50-200ms per call -- unacceptable in a 33ms latency budget. Instead, the wrapper hashes lightweight metadata (<0.1ms). If your camera pipeline already produces frame hashes, pass them via input_frame_hashes.
# With pre-computed frame hashes from your camera pipeline
infer = witness.wrap_vla(
model.predict,
model_id="alpamayo-2-super",
input_frame_hashes=["a1b2c3...", "d4e5f6...", "g7h8i9..."],
)
trajectory = infer(camera_frames)
4. Safety Classification Codes
The safety_classification parameter encodes the operational state of the vehicle when the trajectory decision was made. This maps to factor_c in the witness anchor.
| Code | Classification | When to Use |
|---|---|---|
| 0 | reserved | Not classified or classification not applicable |
| 1 | nominal | All safety checks passed, no anomalies detected, normal driving |
| 2 | cautionary | Safety checks passed with warnings (e.g., low confidence, edge-case scenario) |
| 3 | degraded | Operating in reduced capability mode (e.g., sensor failure, limited visibility) |
| 4 | emergency | Safety system intervened (e.g., emergency braking, collision avoidance activated) |
| 5 | abort | Trajectory was rejected before execution (e.g., failed safety validation, minimum risk condition triggered) |
Emergency vs. abort: "Emergency" means the trajectory was executed under safety intervention -- the vehicle acted. "Abort" means the trajectory was rejected before any action was taken. Both record factor_b = 0.0 (safety validation failed), but they represent fundamentally different operational states. Auditors need this distinction.
# Emergency braking during lane change
witness.witness_trajectory(
safety_validated=False,
safety_classification="emergency",
action_class="change_lane",
model_id="alpamayo-2-super",
)
# Trajectory rejected before execution
witness.witness_trajectory(
safety_validated=False,
safety_classification="abort",
action_class="navigate",
model_id="alpamayo-2-super",
)
The SAFETY_CLASSIFICATION_CODES dictionary is exported from both SDKs for programmatic use:
# Python
from swt3_ai import SAFETY_CLASSIFICATION_CODES
# {"reserved": 0, "nominal": 1, "cautionary": 2, "degraded": 3, "emergency": 4, "abort": 5}
// TypeScript
import { SAFETY_CLASSIFICATION_CODES } from "@tenova/swt3-ai";
// { reserved: 0, nominal: 1, cautionary: 2, degraded: 3, emergency: 4, abort: 5 }
5. Multi-Sensor Fusion Provenance
Autonomous vehicles fuse data from multiple sensor types: cameras, LiDAR, radar, ultrasonic, GPS, and IMU. The sensor_sources parameter captures which sensors contributed to the trajectory decision without exposing raw sensor data.
witness.witness_trajectory(
safety_validated=True,
sensor_sources=[
"camera_front_wide",
"camera_front_narrow",
"camera_rear",
"camera_left",
"camera_right",
"lidar_top",
"radar_front",
"radar_rear",
"imu",
],
model_id="your-vla-model",
)
What survives at each clearing level:
- Level 0-1: Full
sensor_sourceslist andsensor_count - Level 2:
sensor_countonly (e.g., 9). No sensor names. Auditor knows how many sensors contributed but not the sensor configuration. - Level 3: Neither. Factors only.
Why sensor provenance matters: If a trajectory decision was made with 3 sensors instead of 9, that is a different risk profile. An assessor reviewing an incident needs to know whether the model had full sensor coverage or was operating in degraded mode. The sensor_count combined with safety_classification tells that story without exposing your sensor architecture.
6. Offline and Edge Operation
Vehicles operate offline. Tunnels, rural roads, underground parking, and cellular dead zones are normal operating conditions. SWT3 handles this with the same write-ahead log (WAL) architecture used across all edge deployments.
How It Works
- Every
witness_trajectory()call writes the payload to a local WAL file immediately - The WAL survives process restarts and power loss
- When connectivity returns,
flush()drains the WAL to the clearing house - AI-MOB.5 (Bilateral Flush Correlation) verifies all locally buffered anchors were successfully correlated after flush
# No endpoint = local-only mode (WAL captures everything)
witness = Witness(clearing_level=2)
# Drive for 2 hours through a tunnel...
for frame_batch in camera_pipeline:
trajectory = model.predict(frame_batch)
witness.witness_trajectory(
safety_validated=trajectory.safety_passed,
waypoint_count=len(trajectory.waypoints),
trajectory_hash=sha256(trajectory.serialize()),
model_id="your-vla-model",
)
# Back online -- drain the WAL
receipts = witness.flush()
print(f"Flushed {len(receipts)} trajectory anchors")
Buffer tuning for AV workloads: At 10 Hz inference, the default buffer fills quickly. Set buffer_size=100 and flush_interval=10.0 (seconds) for high-frequency AV workloads. The WAL handles overflow -- no anchors are lost.
7. Performance Constraints
Autonomous driving systems have strict latency budgets. The witnessing layer must add negligible overhead.
| Inference Rate | Latency Budget | SWT3 Overhead | Budget Impact |
|---|---|---|---|
| 30 Hz | 33 ms | < 0.1 ms | < 0.3% |
| 20 Hz | 50 ms | < 0.1 ms | < 0.2% |
| 10 Hz | 100 ms | < 0.1 ms | < 0.1% |
SWT3 achieves this through three design decisions:
- No raw frame hashing. Camera frames are large (6MB+ per frame, 6-12 cameras). Hashing pixel data adds 50-200ms. The wrapper hashes lightweight metadata instead, or accepts pre-computed hashes from your existing camera pipeline.
- Non-blocking buffer.
enqueue_many()writes to an in-memory buffer. Flush happens on a background thread. The inference loop is never blocked by network I/O. - SHA-256 fingerprint minting is fast. One SHA-256 hash of a ~100 byte string takes microseconds. The fingerprint formula is deterministic and requires no network calls.
Recommended Configuration
# High-frequency AV configuration
witness = Witness(
endpoint="https://sovereign.tenova.io",
api_key="axm_live_...",
tenant_id="YOUR_TENANT",
clearing_level=2, # Sensitive -- hashes only, no raw context
buffer_size=100, # Flush every 100 payloads
flush_interval=10.0, # Or every 10 seconds, whichever comes first
)
8. Regulatory Framework Mapping
AI-MOB.6 and AI-MOB.7 map to four regulatory frameworks that govern autonomous vehicle AI systems:
| Framework | AI-MOB.6 Reference | AI-MOB.7 Reference | Requirement |
|---|---|---|---|
| EU AI Act | Annex III(3a), Art. 9(2)(a) | Art. 12(1), Art. 15(1) | Risk management, automatic logging, accuracy |
| ISO/PAS 8800 | Cl. 6, Cl. 7, Cl. 8 | Cl. 9, Cl. 10 | AI safety lifecycle, operational classification |
| NIST AI RMF | MANAGE 4.1, MEASURE 2.6 | MEASURE 2.5, MAP 3.2 | Risk management, measurement, mapping |
| UNECE WP.29 R157 | R157 | R157 | Automated lane-keeping, operational evidence |
High-risk AI systems shall have a risk management system that identifies and analyzes known and foreseeable risks. witness_trajectory() with safety_classification provides evidence that risk was assessed for each trajectory decision, not just at system design time.
High-risk AI systems shall be designed with capabilities enabling the automatic recording of events relevant to identifying risks. wrap_vla() records every inference call automatically -- timing, success/failure, and I/O provenance -- without requiring changes to the model code.
Road vehicle AI safety requires classifying the operational state during AI decision-making. The safety_classification parameter (nominal, cautionary, degraded, emergency, abort) directly maps to ISO 8800's operational classification framework.
Regulation 157 requires evidence of automated driving system behavior during operation. SWT3 anchors provide tamper-evident records of every trajectory decision with cryptographic fingerprints that can be verified independently.
9. Verification and Audit Presentation
Creating evidence is half the story. Presenting it to a regulator, assessor, or accident investigator is the other half. Every witness anchor can be independently verified without access to your systems.
What an Assessor Sees
When your ISO/PAS 8800 assessor or EU AI Act notified body asks for trajectory decision evidence, you provide the SWT3 anchor fingerprint. They verify it independently:
# Verify a single anchor fingerprint
curl https://sovereign.tenova.io/api/v1/attest/verify?token=SWT3-E-VULTR-AI-AIMOB6-PASS-1774800010-a1b2c3d4e5f6
The verification response confirms the procedure, verdict, timestamp, and that the anchor has not been tampered with. The assessor does not need access to your dashboard, your model, or your trajectory data. The anchor is self-verifying.
What a Regulator Sees During Investigation
After an incident, the regulator needs the full timeline: what the AI decided, when, in what order, and whether safety systems intervened. The forensic timeline reconstruction API returns a chronological view of all anchors for a given time window:
# Reconstruct all trajectory decisions in a 60-second window
curl "https://sovereign.tenova.io/api/v1/reconstruct?start=1774800000000&end=1774800060000&procedure=AI-MOB.6" \
-H "Authorization: Bearer axm_live_..."
The response includes every trajectory anchor with its safety classification, verdict, and timestamp. Emergency (code 4) and abort (code 5) events are flagged automatically. The regulator gets the answer to "what did the AI do in the 30 seconds before the incident" without depending on your application logs.
Each anchor fingerprint is a SHA-256 hash of the tenant, procedure, factors, and timestamp. Changing any value produces a different fingerprint. The clearing house stores the original fingerprint at ingest time. If the anchor has been altered, verification fails. This is cryptographic proof, not a log entry.
Public Verification Portal
Any anchor can be verified through the public portal at /verify -- no authentication required. Paste the SWT3 anchor string or fingerprint and get immediate confirmation of procedure, verdict, and timestamp integrity.
10. When to Use MOB.6 vs SAFE.1 vs CHAIN.1
SWT3 has multiple procedures that touch autonomous system governance. Here is when to use each:
| Procedure | Use When | Example |
|---|---|---|
| AI-MOB.6 | A planning model produces a trajectory decision | VLA outputs a path: turn left at intersection |
| AI-MOB.7 | You want every VLA inference call witnessed automatically | Wrap model.predict() with transparent witnessing |
| AI-SAFE.1 | A safety system reacts to an event | Emergency braking triggered by obstacle detection |
| AI-CHAIN.1 | One agent hands off to another | Planner agent passes trajectory to control agent |
| AI-EMRG.1 | Emergency override lifecycle | Driver takes manual control, disengagement event |
| AI-DRIFT.2 | Model performance changes over time | Trajectory quality degrades in new weather conditions |
These procedures are complementary. A single driving scenario might generate all of them:
- MOB.7 -- VLA inference call witnessed (every frame)
- MOB.6 -- trajectory decision attested (every planning cycle)
- SAFE.1 -- emergency braking triggered (rare, reactive)
- CHAIN.1 -- planner hands trajectory to controller (agent boundary)
- EMRG.1 -- driver disengages autonomous mode (override lifecycle)
11. Quick Reference
MOB Namespace (Mobile Edge Governance)
| Procedure | Title | SDK Method |
|---|---|---|
| AI-MOB.1 | SIM-Bound Attestation | Protocol spec (mobile telecom) |
| AI-MOB.2 | Roaming Attestation | Protocol spec (mobile telecom) |
| AI-MOB.3 | Dual-SIM Policy Enforcement | Protocol spec (mobile telecom) |
| AI-MOB.4 | Peer-to-Peer Trust Mesh | Protocol spec (device mesh) |
| AI-MOB.5 | Bilateral Flush Correlation | Protocol spec (offline sync) |
| AI-MOB.6 | Trajectory Decision Attestation | witness_trajectory() / witnessTrajectory() |
| AI-MOB.7 | VLA Inference Witnessing | wrap_vla() / wrapVLA() |
Install
Minimal Example (3 Lines)
from swt3_ai import Witness
witness = Witness(endpoint="https://sovereign.tenova.io", api_key="axm_live_...", tenant_id="YOUR_TENANT")
witness.witness_trajectory(safety_validated=True, model_id="your-vla-model")
Full SDK documentation: sovereign.tenova.io/docs
UCT Registry (109 procedures): sovereign.tenova.io/registry
Create a free account: sovereign.tenova.io/signup