Marked outputs
Public Preview

Content marking for terminal text answers

Duale AI marks terminal plain-text answers with machine-readable C2PA provenance to support the text-marking requirement in Article 50(2) of Regulation (EU) 2024/1689.

Duale AI marks terminal plain-text answers with C2PA provenance, supports verification, and explains how to preserve the mark through text transformations.

  • The mark is a C2PA 2.4 Annex A.8 manifest with generation time and identifier.
  • Verification returns valid, trusted, invalid, or unmarked; trusted requires a trust anchor certificate.
  • The mark adds about 1,855 characters of Unicode variation selectors without changing rendered text.
  • Reformatting, re-encoding, translation, or Unicode normalization can remove the mark from the text.
  • If marking cannot complete, Duale AI delivers the plain-text answer instead of failing the task.

Summaries were generated by AI. Generative AI is experimental.

Duale AI marks terminal plain-text answers with machine-readable C2PA provenance. The mark has no visible glyph, so the answer looks unchanged in a conforming renderer. It supports the text-marking requirement in Article 50(2) of Regulation (EU) 2024/1689.

Marked outputs

A terminal answer 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 terminal result from await response.model() is the authoritative marked value.

The mark is a C2PA 2.4 Annex A.8 manifest. It 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, model, provider, or Web source data.

Verify a text answer

Install the codec:

pip install c2patxt

Then verify the answer:

from c2patxt import verify

verdict = verify(answer_text)
print(verdict.state.value)

The state has four values:

StateMeaning
validThe mark, signature, and text hash are valid
trustedThe mark is valid and chains to a trust anchor supplied to the validator
invalidA mark is present but its validation failed
unmarkedThe text has no readable mark
  • State
    valid
    Meaning
    The mark, signature, and text hash are valid
  • State
    trusted
    Meaning
    The mark is valid and 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 proves that the text has not changed since signing. Signer identity needs a trusted certificate relationship, so use trusted when your workflow requires that check.

To compare a marked answer with an unmarked copy, compare the text returned by strip():

from c2patxt import strip

assert strip(answer_text) == expected_text

Use 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 terminal answer 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.