When an AI model drafts your code or your text, two questions come later: who did what, and who checked it? aiprov writes the answers into a plain Turtle file next to your work, as a profile of W3C PROV-O.
- RecordedEvery step names its agent, person or model, its inputs and outputs by hash, and the telemetry the tool reports. Nothing is estimated.
- OpenOne Turtle file and one dependency (rdflib). Any tool that reads PROV-O reads the graph.
- VerifiableEvery statement is a claim on a seven-step ladder. The top two steps belong to people: the command line refuses an AI, and
provlog validatechecks it again in CI.
Code on GitHub · Vocabulary · The F(AI)²R paper it comes from
A demo: one report, two claims, one human check
Alice asks an AI model to turn her benchmark notes into a short report. Nine commands later, the graph below holds the whole story. The data is invented, the graph is real: this page ran the commands with aiprov 0.2.0 (git 2d72755) when it was built.
- Who. Alice is a person, registered with her ORCID iD. Model X is an AI model that acts on her behalf (
prov:actedOnBehalfOf). - What. Model X drafted
report.mdfromnotes.md. The activity records the model, both files (the output with its sha256) and the tokens the tool reported: 1,200 in, 800 out. - Claims. The report makes two statements. Each becomes a claim with a parent activity and a state on the ladder: "twice as fast" was checked by the model (AI-confirmed), "all functions tested" by nobody yet (unverified).
- Human check. Alice re-ran the benchmark and promoted the speed claim to human-confirmed. The promotion is an activity of its own, an audit pass associated with Alice, so the graph says who granted the step and when.
- The rule. Model X then tried to mark the other claim as human-read. provlog refused: the top two steps are for registered humans.
validatechecks the same rule on the whole file, so a hand-edited graph cannot slip it in either.
The commands, as run for this page
Each with --base https://example.org/demo/; the output is what provlog printed.
$ provlog init Seeded provenance.ttl (519 triples, base https://example.org/demo/, schema 0.3.0) $ provlog agent --id alice --type human --name "Alice Example" \ --orcid 0000-0002-1825-0097 agent:alice registered (human) $ provlog agent --id model-x --type ai --name "Model X" --model model-x \ --provider "Example AI" --acted-on-behalf-of alice agent:model-x registered (ai) $ provlog log --activity draft-report --pass authoring --agent model-x \ --label "Draft the report from the notes" --used notes.md \ --generated report.md --input-tokens 1200 --output-tokens 800 act:draft-report logged (544 triples total) $ provlog claim --id c-speed --text "The new parser is twice as fast." \ --parent draft-report --agent model-x --state ai-confirmed claim:c-speed added (state ai-confirmed) $ provlog claim --id c-tests --text "All public functions are tested." \ --parent draft-report --agent model-x --state unverified claim:c-tests added (state unverified) $ provlog promote --id c-speed --to human-confirmed --agent alice \ --note "Re-ran the benchmark myself" c-speed: ai-confirmed -> human-confirmed (logged as AuditPass, agent:alice) $ provlog claim --id c-tests --text "All public functions are tested." \ --parent draft-report --agent model-x --state human-read REFUSED: rung 'human-read' is human-only; agent:model-x is not a registered HumanAgent. An AI must never grant this rung. (exit 1) $ provlog validate [ OK ] parentless claims: 0 [ OK ] unattributed claims: 0 [ OK ] human-only rungs granted by AI agents: 0 [ OK ] human-only rungs without a recorded human promotion activity: 0 [ OK ] sources above needs-research without DOI/URL: 0 [ OK ] activities without agent: 0 [ OK ] session activities with no measurable span (a logging instant, not the span of the work): 0 [ OK ] agents referenced but not registered: 0 [ OK ] agents typed as both AI and human: 0 [ OK ] wasInformedBy targets that are not logged activities: 0 [ OK ] external references (nodes defined in another graph): 0 [ OK ] external references that carry a file path or a label: 0 [ OK ] sub-activities outside the orchestration plan: 0 [ OK ] orchestrations logged twice or informed by themselves: 0 [ OK ] sub-activities logged before their orchestration: 0 [ OK ] entities generated by two activities that carry a model role: 0 [ OK ] fallbackOf targets that are not other logged activities: 0 [ OK ] activities that are part of something that is not a session: 0 [ OK ] messages without a sender: 0 [ OK ] replies to a message that is not in this graph: 0 [ OK ] messages without a content hash, or whose kept text does not match it: 0 [ OK ] message text kept in a channel above internal or of unknown class: 0 [ OK ] records made by another agent or in arrears without a source (recordedFrom): 0 [ OK ] sessions with token sums from more than one capture path (only one is counted): 0 [ OK ] viaHarness targets that are not registered harnesses: 0 [ OK ] activities via a harness with neither a model nor a stated reason: 0 [ OK ] telemetry chain anchors without one valid head, a length of at least 1 and an author: 0 [ OK ] premises that are not claims: 0 [ OK ] premise cycles: 0 [ OK ] atleast claims with minPremises missing or above the number of premises: 0 [ OK ] composite claims without premises: 0 [ OK ] claims stated above their effective rung: 0 [ OK ] decisions that are malformed (asker, hash, two options, recommendation, text matching hash): 0 [ OK ] options or deciding activities that are incomplete: 0 [ OK ] chosen options that the decision did not offer: 0 [ OK ] decisions set to done by an agent that is not a registered human: 0 [ OK ] supersedes links to a missing decision, to itself or in a cycle: 0 [ OK ] decision text kept where the data class is unknown or above internal: 0 [ OK ] graph states its schema version
The resulting graph: demo.ttl (Turtle, with the vocabulary), and the dashboard that aiprov-dashboard builds from it.
Try it
$ pip install git+https://github.com/noheton/aiprov $ provlog --base https://your.org/prov/ init
Then register your agents and log your steps as above. The README lists every command; issues and pull requests are welcome.
Cite
Krebs, F. (2026). aiprov: domain-agnostic AI provenance over PROV-O (Version 0.2.0) [Software]. Zenodo. https://doi.org/10.5281/zenodo.23651340
All versions: https://doi.org/10.5281/zenodo.23651333. Citation metadata: CITATION.cff.