> ## Documentation Index
> Fetch the complete documentation index at: https://www.composer.id/llms.txt
> Use this file to discover all available pages before exploring further.

# The Intent ID

> The one identifier minted when Triage reaches a decision and carried into every system that records it: shape, minting, versions and carrier fields.

The Intent ID is the reference every system shares. This page covers its shape, how it is minted, how versions work and where it lands in a destination. Read it before you map a destination field or correlate a record back to a decision.

## Shape

An Intent ID looks like `itn_Vq3kX9mR2dLpZ0aQ7b`. It matches `^[A-Za-z0-9_-]{10,64}$`: letters, digits, underscore and hyphen only, between 10 and 64 characters. The shape is deliberately plain so the identifier survives being written into other systems' client-supplied fields, for example WorkAuthor's `externalId` (64 characters), Beeline's `externalId` on an intake request, or a custom field on an SAP Fieldglass job posting.

The same pattern is enforced wherever the identifier appears: the `IntentRecord`, `TimelineEvent`, `WebhookEvent`, `EnrichmentRequest`, `ReconciliationReport` and `PassthroughRequest` schemas, and the `DefenceFile` evidence document.

## Minted from the decision

In the Triage-fed chain the Intent ID is a pure function of the assessment response that produced the decision. In the reference code it is `itn_` followed by the first 22 characters of the Base64url SHA-256 digest of the WorkAuthor `responseId`. The same response always yields the same Intent ID, so a replayed completion event re-derives the same intent rather than forking the record.

<Check>
  Combined with find-before-create at the destination, the whole chain is idempotent without any shared state between the trigger and the adapter.
</Check>

## Immutable, versioned

The identifier never changes. What changes is `intent_version`, an integer that starts at 1 and only increases.

* An amendment to the decision increments `intent_version`, which mints a new idempotency key on purpose.
* Enrichment, which only fills in fields a destination requires, completes the same version. `POST /enrichment-request` does not bump `intent_version`.

The publish key `{intent_id}-{intent_version}-{target_system}` therefore stays stable through enrichment and changes only when the decision genuinely changes. [Publishing](/concepts/publishing) covers the key in detail.

## Written into the destination's own field

The convention is simple: write the Intent ID into the destination's client-supplied identifier field. `POST /plan` returns, for each destination, the `carrier_field` the Intent ID is written to and the `mode` the adapter uses.

<AccordionGroup>
  <Accordion title="Stamp mode" description="The Intent ID is written into the destination record" icon="check">
    The adapter writes the Intent ID into the destination's documented carrier field when it creates the record, or onto an existing record when you supply its `external_id` to `POST /publish`. Where that field is filterable on reads, as Beeline's `externalId` is, the record can be re-found from either side and a duplicate publish is detected before it happens.
  </Accordion>

  <Accordion title="Link mode" description="The linkage is recorded on the composerID side only" icon="git-branch">
    Some platforms expose read-centric or pure-transit APIs with no client-supplied identifier to write into. composerID records the `intent_id` to `external_id` linkage on its own side, as an `intent.linked` event on the timeline, and the destination page says so. `POST /reconcile` then needs the `external_id` because composerID linked the record rather than created it.
  </Accordion>
</AccordionGroup>

<Note>
  Carrier field names on the destination pages are indicative until they are confirmed against a tenant at onboarding. The pattern the Intent ID must fit is not indicative: it is fixed by the schema.
</Note>

## Two directions, no lookup table

Given an Intent ID, composerID knows every record it published. Given a destination record, its Intent ID leads back to the decision and, through the [Manuscript API](/api-reference/manuscript/overview), to the evidence behind it. Neither direction needs a mapping table, and neither can drift, because the identifier lives inside the record rather than beside it.

## Next steps

<Columns cols={3}>
  <Card title="Publishing" icon="send" href="/concepts/publishing">
    How the Intent ID becomes a record, safely under retry.
  </Card>

  <Card title="Events and the timeline" icon="webhook" href="/concepts/events">
    Everything that happens to an intent, in order, under one identifier.
  </Card>

  <Card title="Beeline guide" icon="plug" href="/guides/beeline">
    The Intent ID in `externalId`, end to end, against a fake tenant.
  </Card>
</Columns>
