- Duale AI
- Documentation
- Content marking
Content marking: C2PA marks on Task Results
Describes how to verify, read, and preserve C2PA generation-provenance marks that Duale AI attaches to eligible plain-text Task Results.
This page covers how Duale AI marks plain-text Task Results with C2PA provenance, how to verify marks, read generation identifiers, and preserve marks.
- Marked outputs and C2PA manifest structure.
- Verification states and the c2patxt codec.
- Generation identifier behavior and usage.
- Mark preservation, overhead, and failure handling.
Summaries were generated by AI.
For eligible terminal plain-text Task Results, Duale AI attempts to attach a machine-readable generation-provenance mark. If marking cannot complete, Duale AI delivers an unmarked result instead of failing the Task, as described below.
Marked outputs
A completed Task Result carries a mark when its declared response format is plain text or unset. Structured formats,
streaming deltas, internal Tool messages, reasoning traces, and empty answers do not carry one. The Task Result returned
by await response.model() is the authoritative marked value.
The mark is a C2PA Manifest Store embedded in the C2PATextManifestWrapper defined by C2PA 2.4 Annex
A.8. C2PA states that this
unstructured-text carrier remains under review and can change after implementation feedback and interoperability
testing. The mark records that software generated the text, the generation time, the text/plain format, the software
that wrote the mark, and an opaque generation identifier. It contains no prompt, customer, Tenant, Task, Agent Identity,
model, provider, or Web-source data.
This mechanism is one technical input to an Article 50(2) assessment. It does not by itself establish that the complete marking solution is effective, interoperable, robust, reliable, or compliant with Regulation (EU) 2024/1689.
Verify a text answer
Install the codec:
pip install c2patxtThen verify the answer:
from c2patxt import verify
verdict = verify(answer_text)
print(verdict.state.value)c2patxt returns four states for the profile that Duale AI emits:
- State
valid- Meaning
- The mark, signature, and text hash are valid under that profile
- State
trusted- Meaning
- The profile-valid mark chains to a trust anchor supplied to the validator
- State
invalid- Meaning
- A mark is present but its validation failed
- State
unmarked- Meaning
- The text has no readable mark
Branch on state; bool(verdict) raises. A valid result establishes that the delivered text matches the text hash
signed in the extracted mark. It does not identify the signer, establish that another C2PA validator supports Annex A.8,
or prove regulatory compliance. Use trusted when your workflow requires signer identity through a trusted certificate
relationship.
To compare a marked answer with an unmarked copy, compare the text returned by strip():
from c2patxt import strip
assert strip(answer_text) == expected_textUse the stripped value only for comparison. Store and forward the original marked answer.
Read the generation identifier
Each marked answer has one identifier for its generation:
from c2patxt import extract
manifest = extract(answer_text)
print(manifest.claim["instanceID"]) # "xmp:iid:<uuid>"The identifier stays the same when you read the same delivered answer again. A new generation gets a new identifier. Keep it with the answer when you need to discuss that generation with Duale AI. It does not resolve to prompt, routing, or account data by itself.
Preserve the mark
The mark uses Unicode variation selectors. This changes the bytes and character count by about 1,855 characters, or
7.2 kB of UTF-8, while leaving the rendered text unchanged. Compare visible text with strip() and allow for the fixed
overhead in byte limits.
Reformatting, re-encoding, translation, Unicode normalization, or another text transformation can remove the mark. Verify it when you receive the completed Task Result and preserve the original bytes when provenance matters.
If marking cannot complete, Duale AI delivers the plain-text answer instead of failing the task. An unmarked result
therefore says only that no readable mark is present. Under the Terms of Use, customers must not
deliberately remove or hide a mark from an Output.
A mark records generation provenance. It does not prove factual accuracy or identify the Web sources used. Sources and factuality covers those checks.