> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mesh.texturehq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Identity linking

# Cross-connector identity linking

Mesh can recognize one person across separate connector accounts within one
agent's perspective. Verification associates existing actors, private memories
and conversation history while preserving their original attribution. A name
claim never establishes identity or reveals whether the agent knows that person.

## Using the flow

1. The first account a person uses with an agent is that person. Nobody has to
   mark it: a connector-authenticated private session is the root by virtue of
   being first. An owner can additionally provision an exact participant ID
   onto a person before its first message, for example a phone number.
2. When the same person turns up on another channel, they ask the agent in that
   new private conversation to link their accounts, or send `link accounts`.
   The agent gives generic instructions and a code.
3. Within ten minutes, the person sends `link CODE` in their private conversation
   with the same agent on the account they already use. The person must carry the
   code between sessions themselves; the agent never forwards it.
4. The runtime verifies the persisted, connector-authenticated command before
   model inference. On success, both accounts resolve to the established actor.
   Earlier private memories and requester history become available across the
   linked accounts, subject to their original restrictions.

The model's `request_identity_link` tool only starts the flow. It accepts no
name, target, code or approval argument. There is no model tool for approving a
link, and a bare "yes" cannot complete one.

## Privacy and possession requirements

The implemented direction is **claimant → anchor**: show a code on the new account
and receive it on the established one. There is no name lookup, candidate list,
outgoing challenge notification, or contact-directory response. The claimant
receives the same instructions regardless of whom they claim to be. This avoids
both contact enumeration and unsolicited challenge notifications to real people.

Starting and confirming require persisted inbound messages in direct
conversations, with source evidence and an authenticated single-reader audience
matching that connector identity. A group message cannot establish a link even
if its audience happens to list only one reader. Connector bot messages bypass
command handling.

Any private account the agent already talks to can anchor. The proof is the
echoed code: it demonstrates control of two sessions, and that is the whole
claim being made. An owner assertion would add nothing about the second session,
so none is required. A new observation, name match, mention or model inference
still MUST NOT link accounts; only the echo does. The proof is not a legal
identity check. People must use it only for their own accounts, as the challenge
instructions state. Someone persuaded to copy another person's linking code could
authorize an unwanted association, just as with another account-possession
ceremony.

## Proof data and resolution

Verification provenance lives on the `connector_identities` row being verified:

* `verification_method`: `code_echo` for a completed possession challenge,
  `operator` for an owner-provisioned participant ID, null for an observation.
* `verified_via_identity_id`: the anchor identity for a code-echo proof.
* `verification_challenge_id`: the successful challenge supporting that edge.
* `verified_at`, `verified_by_user_id`, and `confidence`: timestamp, owner audit
  identity for provisioning, and proof strength (50 operator, 100 code echo).
* `verification_revoked_at`: severs the proof without erasing its provenance.

Composite foreign keys scope identities, actors and challenges to the same
`runtime_agent_id`. Check constraints require complete proof records.
`identity_challenges` retains the SHA-256 code digest, claimant and eventual
anchor, request/response message IDs, expiry, attempts and disposition.
`identity_link_attempts` records confirmation attempts, and
`identity_revocations` records recovery actions.

Original actor IDs, message authors, participation and memory subjects are never
rewritten. Roots are implicit: an identity is a root unless it carries an active
code-echo proof pointing at another identity. `mesh_verified_identity_actor`
follows active proof edges to that root; `mesh_canonical_actor` resolves an actor
to it for reads, falling back to the original actor when its proof is inactive.
The roster, actor timeline, memory subject relevance, display labels and
`search_history(speaker=requester)` use that live association. Raw IDs remain
authoritative historical attribution.

A linked child may anchor another account. Resolution is bounded to 32
identities per chain; confirmation refuses cycles and proofs beyond that bound.
An actor with multiple pre-provisioned identities cannot become a code-echo child
in this version: start the challenge from the separate account and confirm it on
one of the pre-provisioned actor's accounts instead. Provisioning is serialized
with confirmation so it cannot bypass that restriction.

## Private continuity

Audience snapshots remain immutable and connector-scoped. The additional read
path requires both single-reader identities to resolve through live proof chains
to the same actor in the same perspective. The destination must be a direct
conversation with that linked person, backed by persisted inbound evidence.

Only single-reader private source evidence qualifies. Multi-reader rooms,
workspace audiences, externally shared audiences, unknown evidence, explicit
conversation restrictions and external-tool grants are not widened by a link.
Existing permissions within a connector continue to apply. Every inherited
message and memory restriction still applies, including evidence used in an
agent reply that is later retrieved as history.

Memory and retrieved-history permissions are checked again before delivery. A
revoked link cannot authorize a reply still awaiting that check. Information
already delivered cannot be retracted.

## Limits and failure behavior

Codes have 80 random bits, are single-use, and expire after ten minutes. They are
stored as digests in the challenge table, although the plaintext necessarily
appears in the two private transcripts. A new accepted request abandons any
previous pending code for that claimant.

The limits are three starts per claimant account per fifteen minutes, ten
confirmation attempts per responding account per fifteen minutes, and five
failed confirmations against a known challenge. A throttled start returns the
same question with an unusable code. All unsuccessful confirmations use the same
public response. Budgets are bound to authenticated senders, never to a name
claimed by a stranger.

A worker retry of the exact successful response message may repeat the success
result while that same proof remains active. A new message replaying the code
cannot consume it again; retrying after revocation cannot restore the link.
An `unlink accounts` retry likewise reuses its recorded outcome and cannot revoke
a newer link. Confirmation, provisioning and revocation serialize under a
per-perspective transaction lock.

## Recovery and owner controls

Send `unlink accounts` privately to sever the current account's proof and every
proof chained through it. An install owner can use **Unlink this account** on a
linked account on the actor page. The severed accounts are separate people again,
exactly as before linking, and their private continuity is removed. Nothing
restores a severed subtree silently: each account re-links with a fresh code from
its own private conversation. There is no owner "verify" step, because there is
nothing for it to assert that the echo does not already prove.

Owner APIs under `/api/agents/{slug}/actors/{actorID}/identities` are:

* `POST` to provision a new exact participant ID onto this person.
* `DELETE /{identityID}` to sever an account's proof while retaining the account.

Verification provenance is operator audit data. It must not become a contact
directory in the model's context or a response to an unverified claimant.
Proof-bearing messages and identities restrict deletion; a complete perspective
purge explicitly clears proof pointers and deletes audit records first. Ordinary
revocation preserves them.

## Scope and delivery

Links belong to one agent's perspective. Two agents may independently link the
same person; neither inherits the other's links or memories. This human identity
flow does not change [agent-owned acting identities (repository)](https://github.com/TextureHQ/mesh/blob/main/docs/roadmap.md#agent-owned-acting-identities).

See [identity-delivery.md (repository)](https://github.com/TextureHQ/mesh/blob/main/docs/runtime/identity-delivery.md) for the three-PR sequence: proof
storage, conversational verification and recovery, then memory/history continuity.
The owner-verified-root requirement those PRs shipped with was removed afterwards
(migration `0097`); the possession proof was always the load-bearing part.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.