Skip to main content
Every provenance record in ProvenanceKit is expressed as one or more of three types: Entity, Action, or Attribution. This is the EAA model — a pure meta-pattern with no economic or governance opinions baked in.

Why three types?

Provenance answers: who did what, to what, with what authority? Separating claims (Attribution) from events (Action) from participants (Entity) means you can express any provenance structure without the schema being too specific to one use case.

Entity

An Entity represents any participant that can perform or be attributed to an action.
Role is a freeform string. Use "human", "ai", "organization", or any domain-specific value. The only built-in semantics are in the aiAgent field (present when role is "ai").

Action

An Action represents something that happened. It is the central event record.
CIDs (content identifiers) are the connective tissue between actions. An output CID from one action can be an input CID in a downstream action, forming a provenance graph automatically.

Attribution

An Attribution makes a claim linking an Entity to either an Action or a resource (CID).
Attribution targets either actionId (attributing to the event that produced something) or resourceRef (attributing directly to a CID), not both.

Extensions

Any EAA type can carry extensions — a typed dictionary keyed by ext:namespace@semver. Extensions add domain semantics without changing the core schema.
All built-in extension schemas are in @provenancekit/extensions and validated with Zod.

Composing a provenance graph

Multiple EAA records compose into a directed acyclic graph (DAG) via CIDs:
This graph is what @provenancekit/indexer materializes from on-chain events, and what the ProvenanceGraph UI component renders.

Gotchas

  • Self-attribution is allowed by design. The contracts do not enforce who can make a claim. The assumption is that claims are signed and audited by the consuming application or off-chain verifier.
  • CIDs must be deterministic. For provenance to link correctly across systems, use a consistent content-addressing scheme (IPFS CIDs are recommended).
  • sessionId is app-managed. Generate a session ID per conversation, pipeline run, or creative session. Pass it to all actions in that session. The API does not enforce uniqueness or lifecycle.