{
  "schemaVersion": "1.0",
  "title": "Manage a Chatwoot conversation lifecycle",
  "description": "Use this guide to read one existing Chatwoot conversation, send a public reply or private note, set its status, optionally hand it off, and verify final provider state. An optional branch covers creation when the pinned provider body is alr",
  "canonical": "https://getaip.org/docs/connectors/chatwoot/guides/conversation-and-message-lifecycle",
  "route": "/docs/connectors/chatwoot/guides/conversation-and-message-lifecycle",
  "source": "docs/connectors/chatwoot/guides/conversation-and-message-lifecycle.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Connectors",
  "documentType": "Connector",
  "language": "en",
  "downloads": {
    "md": "/docs/download/connectors/chatwoot/guides/conversation-and-message-lifecycle.md",
    "txt": "/docs/download/connectors/chatwoot/guides/conversation-and-message-lifecycle.txt",
    "json": "/docs/download/connectors/chatwoot/guides/conversation-and-message-lifecycle.json",
    "pdf": "/docs/download/connectors/chatwoot/guides/conversation-and-message-lifecycle.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Manage a Chatwoot conversation lifecycle\ndescription: >-\n  Read, message, update, hand off, verify, and recover one governed Chatwoot\n  conversation without losing Action identity\nkind: how-to\naudience: application-developer\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"97be86e9efedf07ecf1783b03800f683f107fb04\"\nconnector: chatwoot\ncapabilityIds:\n  - cap:chatwoot:conversation.get\n  - cap:chatwoot:message.list\n  - cap:chatwoot:conversation.create\n  - cap:chatwoot:message:create\n  - cap:chatwoot:conversation:status\n  - cap:chatwoot:conversation:handoff\naliases:\n  - Chatwoot conversation workflow\n  - Chatwoot message and handoff guide\n---\n\n# Manage a Chatwoot conversation lifecycle\n\nUse this guide to read one existing Chatwoot conversation, send a public reply\nor private note, set its status, optionally hand it off, and verify final\nprovider state. An optional branch covers creation when the pinned provider\nbody is already known.\n\nThe procedure preserves one Action identity and one idempotency key for each\nmutation. It never treats a lost response as permission to create a replacement\nAction.\n\n## When to use this guide\n\nUse this procedure when an application owns one bounded conversation task and\nneeds an auditable path through Chatwoot. It is suitable for a human-approved\nsupport reply, status change, or handoff.\n\nUse the exhaustive [conversation and message reference](../capabilities/conversations-and-messages.md)\nwhen choosing another provider operation. Use the\n[composite reference](../capabilities/aip-composite-operations.md) when\nimplementing the strict inputs themselves.\n\nThis guide does not configure the connector, create provider credentials,\ningest webhooks, prove customer delivery, or qualify a Chatwoot deployment.\n\n## Prerequisites\n\nBefore starting, obtain:\n\n- an authenticated AIP caller bound to the intended tenant;\n- an admitted Chatwoot connector route for one configured account;\n- a conversation ID from that same account, unless creating one;\n- authority to request and approve each intended mutation;\n- a private evidence location for Action, approval, and provider identifiers;\n- the exact pinned Chatwoot body schema if using `conversation.create`.\n\nApply two application checks required by the pinned source:\n\n- always send `private` explicitly to `cap:chatwoot:message:create`;\n- require at least one of `assignee_id` or `note` for\n  `cap:chatwoot:conversation:handoff`.\n\nDo not use direct connector invocation as an idempotency gate. The composite\nbranches publish a required key contract but do not validate or forward that\nkey themselves. Use the governed AIP path.\n\n## Plan the lifecycle\n\n| Step | Capability | Risk | Approval | Retry |\n|---|---|---|---|---|\n| Read conversation | `cap:chatwoot:conversation.get` | Low | No | Safe |\n| Read messages | `cap:chatwoot:message.list` | Low | No | Safe |\n| Create conversation, optional | `cap:chatwoot:conversation.create` | Medium | Required | Unsafe |\n| Send reply or private note | `cap:chatwoot:message:create` | Medium | Required | Unsafe |\n| Set status | `cap:chatwoot:conversation:status` | Medium | Required | Safe |\n| Handoff, optional | `cap:chatwoot:conversation:handoff` | High | Required | Unsafe |\n\nThe two reads are dot-named catalogue capabilities. The message, status, and\nhandoff operations are colon-named connector composites. Do not normalize the\nIDs.\n\n## 1. Pin discovery and identity\n\nRead tenant capability discovery and require the exact IDs planned above.\nRecord:\n\n- tenant and authenticated actor;\n- admitted connector type and immutable version;\n- connector instance and configured external account;\n- capability IDs and catalogue revision;\n- credential revision without credential bytes;\n- policy version used for approval.\n\nStop if the intended capability is absent. An operations file can filter\ndot-named catalogue operations, while the connector-generated manifest always\nstarts with the three composites. Tenant admission and authorization remain\nseparate controls.\n\nDo not put `account_id` in Action input. The connector host inserts its\nconfigured account into every provider route.\n\n## 2. Read authoritative before-state\n\nRead the conversation:\n\n```sh\nCONVERSATION_ID=314\n\naipctl action call \\\n  \"$AIP_URL\" \\\n  cap:chatwoot:conversation.get \\\n  --action-id act_chatwoot_lifecycle_read_001 \\\n  --input \"{\\\"conversation_id\\\":\\\"$CONVERSATION_ID\\\"}\"\n```\n\nThen read its messages:\n\n```sh\naipctl action call \\\n  \"$AIP_URL\" \\\n  cap:chatwoot:message.list \\\n  --action-id act_chatwoot_lifecycle_messages_001 \\\n  --input \"{\\\"conversation_id\\\":\\\"$CONVERSATION_ID\\\"}\"\n```\n\nRequire completed results tied to the submitted Action IDs. Preserve provider\nHTTP status, response body, provider request ID when present, and observation\ntime.\n\nConfirm that the conversation belongs to the intended account and that current\nstatus, assignee, recent messages, and other fields needed by policy match the\nplanned change. Provider result fields are not frozen by the generic output\nschema.\n\n## 3. Create a conversation when needed\n\nSkip this step for an existing conversation.\n\n`cap:chatwoot:conversation.create` uses:\n\n```text\nPOST /api/v1/accounts/{configured_account_id}/conversations\n```\n\nIts Action input has this source-owned envelope:\n\n```text\n{\n  \"body\": <exact object for the pinned Chatwoot route>\n}\n```\n\nThe connector does not validate provider-specific creation fields. Build the\nbody from the pinned provider schema, then retain its canonical form.\n\nBefore dispatch:\n\n1. assign one Action ID;\n2. assign one external-account-scoped idempotency key;\n3. bind approval to actor, tenant, capability, exact body, and policy hash;\n4. keep the same Action, key, and body through settlement.\n\nThe provider call is unsafe to retry and has no rollback. If its response is\nlost, search or list provider state before another create. Extract the new\nconversation ID only from a completed result or authoritative read.\n\nAfter creation, repeat the two before-state reads with that conversation ID.\n\n## 4. Send one reply or private note\n\nChoose visibility deliberately:\n\n| Intent | `private` |\n|---|---|\n| Customer-visible reply | `false` |\n| Internal note | `true` |\n\nPrepare one exact input:\n\n```json\n{\n  \"conversation_id\": \"314\",\n  \"content\": \"Your request is now with the operations team.\",\n  \"private\": false\n}\n```\n\nThe pinned runtime can reject an omitted `private` even though the published\nschema carries a default. Keep the Boolean explicit.\n\nSubmit with one Action and key:\n\n```sh\nMESSAGE_ACTION=act_chatwoot_lifecycle_message_001\nMESSAGE_KEY=chatwoot-lifecycle-message-314-v1\n\naipctl action call \\\n  \"$AIP_URL\" \\\n  cap:chatwoot:message:create \\\n  --action-id \"$MESSAGE_ACTION\" \\\n  --idempotency-key \"$MESSAGE_KEY\" \\\n  --input \"{\\\"conversation_id\\\":\\\"$CONVERSATION_ID\\\",\\\"content\\\":\\\"Your request is now with the operations team.\\\",\\\"private\\\":false}\"\n```\n\nExpected governed flow: the Action can enter `pending_approval` before provider\ndispatch. Approve only the exact text and visibility. A changed character or\nBoolean requires a new decision.\n\nAfter provider HTTP success, the composite constructs:\n\n```json\n{\n  \"conversation_id\": \"314\",\n  \"sent\": true\n}\n```\n\nThis does not prove customer-channel delivery. The provider message contains\nAIP connector, loop-prevention, and Action attributes for later correlation.\n\n## 5. Set the intended status\n\nChoose exactly one status:\n\n```text\nopen | resolved | pending\n```\n\nPrepare and submit:\n\n```sh\nSTATUS_ACTION=act_chatwoot_lifecycle_status_001\nSTATUS_KEY=chatwoot-lifecycle-status-314-pending-v1\n\naipctl action call \\\n  \"$AIP_URL\" \\\n  cap:chatwoot:conversation:status \\\n  --action-id \"$STATUS_ACTION\" \\\n  --idempotency-key \"$STATUS_KEY\" \\\n  --input \"{\\\"conversation_id\\\":\\\"$CONVERSATION_ID\\\",\\\"status\\\":\\\"pending\\\"}\"\n```\n\nThe connector posts the selected status to the provider's\n`toggle_status` route and constructs an output containing the conversation ID\nand status.\n\nThis mutation advertises safe retry, unlike every other Chatwoot mutation.\nThat contract does not add an idempotency header to the provider request. Read\ncurrent status before repeating a call whose response was lost.\n\n## 6. Handoff when required\n\nSkip this step if the conversation remains with its current owner.\n\nChoose at least one effect:\n\n- `assignee_id` to change provider assignment;\n- `note` to add a private handoff note.\n\nExample with both:\n\n```json\n{\n  \"conversation_id\": \"314\",\n  \"assignee_id\": \"42\",\n  \"note\": \"Escalated with the approved incident context.\"\n}\n```\n\nSubmit as one high-risk Action:\n\n```sh\nHANDOFF_ACTION=act_chatwoot_lifecycle_handoff_001\nHANDOFF_KEY=chatwoot-lifecycle-handoff-314-v1\n\naipctl action call \\\n  \"$AIP_URL\" \\\n  cap:chatwoot:conversation:handoff \\\n  --action-id \"$HANDOFF_ACTION\" \\\n  --idempotency-key \"$HANDOFF_KEY\" \\\n  --input \"{\\\"conversation_id\\\":\\\"$CONVERSATION_ID\\\",\\\"assignee_id\\\":\\\"42\\\",\\\"note\\\":\\\"Escalated with the approved incident context.\\\"}\"\n```\n\nThe connector performs assignment first and private-note creation second. The\ntwo provider calls are not atomic. A note failure can leave assignment\ncompleted.\n\nAn input containing only `conversation_id` returns `handoff: true` without a\nprovider call. Reject that no-op before approval.\n\n## 7. Verify final provider state\n\nRepeat `conversation.get` and `message.list` with new read Action IDs. Verify\nonly the fields required by the lifecycle:\n\n- conversation ID and configured-account ownership;\n- intended status;\n- intended assignee when handoff requested it;\n- created message or private note;\n- provider timestamps and request identity where available;\n- no unexpected duplicate message or note.\n\nThe generic result can contain unknown provider fields. Preserve them, but do\nnot make completion depend on an undocumented shape.\n\nAn inbound webhook can provide additional event evidence when ingress is\nconfigured. Synchronous composite success does not depend on receiving that\nwebhook, and a webhook does not replace the final provider read.\n\n## Retain lifecycle evidence\n\nKeep a bounded record for each mutation:\n\n| Evidence | Required identity |\n|---|---|\n| Action | Action ID, capability, tenant, actor, canonical input |\n| Approval | Approval ID, policy hash, approver, decision, expiry |\n| Idempotency | Key, external-account scope, input hash |\n| Route | Connector type, version, instance, account binding |\n| Provider | HTTP status, request ID when exposed, observation time |\n| Result | Terminal AIP status and constructed or generic output |\n| Verification | Final read Action IDs and checked provider fields |\n\nDo not store the Chatwoot API token, webhook secret, signing seed, or\nunredacted customer data merely to make the record more complete.\n\n## Recover an uncertain step\n\n| Uncertain operation | Read first | Decision |\n|---|---|---|\n| `conversation.create` | Search or list conversations using authoritative provider fields | Reuse the original settled result or escalate; do not blindly create again |\n| `message:create` | Conversation messages and AIP Action marker where exposed | Accept the existing message or escalate; do not resend blindly |\n| `conversation:status` | Conversation status | Accept matching state or use the safe-retry contract with the same intent |\n| Handoff assignment | Conversation assignment | Do not repeat assignment if already applied |\n| Handoff note | Conversation messages | Issue a separately approved note-only Action only if current state requires it |\n\nTransport, provider-temporary, and oversized-response failures can mark\nmutation outcome uncertain. The connector failure itself sets\n`retryable: false`.\n\nNo lifecycle mutation has AIP rollback. A corrective status, assignment, note,\nor provider-catalogue update is a new governed intent against current state.\n\n## Completion criteria\n\nThe lifecycle is complete only when:\n\n- every required capability was admitted for the intended tenant route;\n- each mutation used one Action, one canonical input, and one retained key;\n- each approval matched the exact mutation input;\n- final provider reads confirm the intended state;\n- public replies and private notes have the intended visibility;\n- partial handoff effects have been resolved;\n- restricted evidence is stored under tenant policy;\n- no uncertain mutation was replaced with an uncorrelated retry.\n\nThese criteria establish a governed application workflow. They do not prove\nlive-product qualification, message delivery, or production readiness.\n\n## Related documentation\n\n- [Conversation and message capabilities](../capabilities/conversations-and-messages.md)\n- [AIP composite operations](../capabilities/aip-composite-operations.md)\n- [Authentication and account isolation](../getting-started/authentication-and-account-isolation.md)\n- [Approvals and policy](../../../concepts/approvals-and-policy.md)\n- [Error reference](../../../reference/errors.md)\n",
    "text": "Manage a Chatwoot conversation lifecycle\n\nUse this guide to read one existing Chatwoot conversation, send a public reply\nor private note, set its status, optionally hand it off, and verify final\nprovider state. An optional branch covers creation when the pinned provider\nbody is already known.\n\nThe procedure preserves one Action identity and one idempotency key for each\nmutation. It never treats a lost response as permission to create a replacement\nAction.\n\nWhen to use this guide\n\nUse this procedure when an application owns one bounded conversation task and\nneeds an auditable path through Chatwoot. It is suitable for a human-approved\nsupport reply, status change, or handoff.\n\nUse the exhaustive conversation and message reference (../capabilities/conversations-and-messages.md)\nwhen choosing another provider operation. Use the\ncomposite reference (../capabilities/aip-composite-operations.md) when\nimplementing the strict inputs themselves.\n\nThis guide does not configure the connector, create provider credentials,\ningest webhooks, prove customer delivery, or qualify a Chatwoot deployment.\n\nPrerequisites\n\nBefore starting, obtain:\n• an authenticated AIP caller bound to the intended tenant;\n• an admitted Chatwoot connector route for one configured account;\n• a conversation ID from that same account, unless creating one;\n• authority to request and approve each intended mutation;\n• a private evidence location for Action, approval, and provider identifiers;\n• the exact pinned Chatwoot body schema if using conversation.create.\n\nApply two application checks required by the pinned source:\n• always send private explicitly to cap:chatwoot:message:create;\n• require at least one of assigneeid or note for\n  cap:chatwoot:conversation:handoff.\n\nDo not use direct connector invocation as an idempotency gate. The composite\nbranches publish a required key contract but do not validate or forward that\nkey themselves. Use the governed AIP path.\n\nPlan the lifecycle\n\n| Step | Capability | Risk | Approval | Retry |\n\n| Read conversation | cap:chatwoot:conversation.get | Low | No | Safe |\n| Read messages | cap:chatwoot:message.list | Low | No | Safe |\n| Create conversation, optional | cap:chatwoot:conversation.create | Medium | Required | Unsafe |\n| Send reply or private note | cap:chatwoot:message:create | Medium | Required | Unsafe |\n| Set status | cap:chatwoot:conversation:status | Medium | Required | Safe |\n| Handoff, optional | cap:chatwoot:conversation:handoff | High | Required | Unsafe |\n\nThe two reads are dot-named catalogue capabilities. The message, status, and\nhandoff operations are colon-named connector composites. Do not normalize the\nIDs.\n1. Pin discovery and identity\n\nRead tenant capability discovery and require the exact IDs planned above.\nRecord:\n• tenant and authenticated actor;\n• admitted connector type and immutable version;\n• connector instance and configured external account;\n• capability IDs and catalogue revision;\n• credential revision without credential bytes;\n• policy version used for approval.\n\nStop if the intended capability is absent. An operations file can filter\ndot-named catalogue operations, while the connector-generated manifest always\nstarts with the three composites. Tenant admission and authorization remain\nseparate controls.\n\nDo not put accountid in Action input. The connector host inserts its\nconfigured account into every provider route.\n2. Read authoritative before-state\n\nRead the conversation:\n\nCONVERSATIONID=314\n\naipctl action call \\\n  \"$AIPURL\" \\\n  cap:chatwoot:conversation.get \\\n  --action-id actchatwootlifecycleread001 \\\n  --input \"{\\\"conversationid\\\":\\\"$CONVERSATIONID\\\"}\"\n\nThen read its messages:\n\naipctl action call \\\n  \"$AIPURL\" \\\n  cap:chatwoot:message.list \\\n  --action-id actchatwootlifecyclemessages001 \\\n  --input \"{\\\"conversationid\\\":\\\"$CONVERSATIONID\\\"}\"\n\nRequire completed results tied to the submitted Action IDs. Preserve provider\nHTTP status, response body, provider request ID when present, and observation\ntime.\n\nConfirm that the conversation belongs to the intended account and that current\nstatus, assignee, recent messages, and other fields needed by policy match the\nplanned change. Provider result fields are not frozen by the generic output\nschema.\n3. Create a conversation when needed\n\nSkip this step for an existing conversation.\n\ncap:chatwoot:conversation.create uses:\n\nPOST /api/v1/accounts/{configuredaccountid}/conversations\n\nIts Action input has this source-owned envelope:\n\n{\n  \"body\":\n}\n\nThe connector does not validate provider-specific creation fields. Build the\nbody from the pinned provider schema, then retain its canonical form.\n\nBefore dispatch:\n1. assign one Action ID;\n2. assign one external-account-scoped idempotency key;\n3. bind approval to actor, tenant, capability, exact body, and policy hash;\n4. keep the same Action, key, and body through settlement.\n\nThe provider call is unsafe to retry and has no rollback. If its response is\nlost, search or list provider state before another create. Extract the new\nconversation ID only from a completed result or authoritative read.\n\nAfter creation, repeat the two before-state reads with that conversation ID.\n4. Send one reply or private note\n\nChoose visibility deliberately:\n\n| Intent | private |\n\n| Customer-visible reply | false |\n| Internal note | true |\n\nPrepare one exact input:\n\n{\n  \"conversationid\": \"314\",\n  \"content\": \"Your request is now with the operations team.\",\n  \"private\": false\n}\n\nThe pinned runtime can reject an omitted private even though the published\nschema carries a default. Keep the Boolean explicit.\n\nSubmit with one Action and key:\n\nMESSAGEACTION=actchatwootlifecyclemessage001\nMESSAGEKEY=chatwoot-lifecycle-message-314-v1\n\naipctl action call \\\n  \"$AIPURL\" \\\n  cap:chatwoot:message:create \\\n  --action-id \"$MESSAGEACTION\" \\\n  --idempotency-key \"$MESSAGEKEY\" \\\n  --input \"{\\\"conversationid\\\":\\\"$CONVERSATIONID\\\",\\\"content\\\":\\\"Your request is now with the operations team.\\\",\\\"private\\\":false}\"\n\nExpected governed flow: the Action can enter pendingapproval before provider\ndispatch. Approve only the exact text and visibility. A changed character or\nBoolean requires a new decision.\n\nAfter provider HTTP success, the composite constructs:\n\n{\n  \"conversationid\": \"314\",\n  \"sent\": true\n}\n\nThis does not prove customer-channel delivery. The provider message contains\nAIP connector, loop-prevention, and Action attributes for later correlation.\n5. Set the intended status\n\nChoose exactly one status:\n\nopen | resolved | pending\n\nPrepare and submit:\n\nSTATUSACTION=actchatwootlifecyclestatus001\nSTATUSKEY=chatwoot-lifecycle-status-314-pending-v1\n\naipctl action call \\\n  \"$AIPURL\" \\\n  cap:chatwoot:conversation:status \\\n  --action-id \"$STATUSACTION\" \\\n  --idempotency-key \"$STATUSKEY\" \\\n  --input \"{\\\"conversationid\\\":\\\"$CONVERSATIONID\\\",\\\"status\\\":\\\"pending\\\"}\"\n\nThe connector posts the selected status to the provider's\ntogglestatus route and constructs an output containing the conversation ID\nand status.\n\nThis mutation advertises safe retry, unlike every other Chatwoot mutation.\nThat contract does not add an idempotency header to the provider request. Read\ncurrent status before repeating a call whose response was lost.\n6. Handoff when required\n\nSkip this step if the conversation remains with its current owner.\n\nChoose at least one effect:\n• assigneeid to change provider assignment;\n• note to add a private handoff note.\n\nExample with both:\n\n{\n  \"conversationid\": \"314\",\n  \"assigneeid\": \"42\",\n  \"note\": \"Escalated with the approved incident context.\"\n}\n\nSubmit as one high-risk Action:\n\nHANDOFFACTION=actchatwootlifecyclehandoff001\nHANDOFFKEY=chatwoot-lifecycle-handoff-314-v1\n\naipctl action call \\\n  \"$AIPURL\" \\\n  cap:chatwoot:conversation:handoff \\\n  --action-id \"$HANDOFFACTION\" \\\n  --idempotency-key \"$HANDOFFKEY\" \\\n  --input \"{\\\"conversationid\\\":\\\"$CONVERSATIONID\\\",\\\"assigneeid\\\":\\\"42\\\",\\\"note\\\":\\\"Escalated with the approved incident context.\\\"}\"\n\nThe connector performs assignment first and private-note creation second. The\ntwo provider calls are not atomic. A note failure can leave assignment\ncompleted.\n\nAn input containing only conversationid returns handoff: true without a\nprovider call. Reject that no-op before approval.\n7. Verify final provider state\n\nRepeat conversation.get and message.list with new read Action IDs. Verify\nonly the fields required by the lifecycle:\n• conversation ID and configured-account ownership;\n• intended status;\n• intended assignee when handoff requested it;\n• created message or private note;\n• provider timestamps and request identity where available;\n• no unexpected duplicate message or note.\n\nThe generic result can contain unknown provider fields. Preserve them, but do\nnot make completion depend on an undocumented shape.\n\nAn inbound webhook can provide additional event evidence when ingress is\nconfigured. Synchronous composite success does not depend on receiving that\nwebhook, and a webhook does not replace the final provider read.\n\nRetain lifecycle evidence\n\nKeep a bounded record for each mutation:\n\n| Evidence | Required identity |\n\n| Action | Action ID, capability, tenant, actor, canonical input |\n| Approval | Approval ID, policy hash, approver, decision, expiry |\n| Idempotency | Key, external-account scope, input hash |\n| Route | Connector type, version, instance, account binding |\n| Provider | HTTP status, request ID when exposed, observation time |\n| Result | Terminal AIP status and constructed or generic output |\n| Verification | Final read Action IDs and checked provider fields |\n\nDo not store the Chatwoot API token, webhook secret, signing seed, or\nunredacted customer data merely to make the record more complete.\n\nRecover an uncertain step\n\n| Uncertain operation | Read first | Decision |\n\n| conversation.create | Search or list conversations using authoritative provider fields | Reuse the original settled result or escalate; do not blindly create again |\n| message:create | Conversation messages and AIP Action marker where exposed | Accept the existing message or escalate; do not resend blindly |\n| conversation:status | Conversation status | Accept matching state or use the safe-retry contract with the same intent |\n| Handoff assignment | Conversation assignment | Do not repeat assignment if already applied |\n| Handoff note | Conversation messages | Issue a separately approved note-only Action only if current state requires it |\n\nTransport, provider-temporary, and oversized-response failures can mark\nmutation outcome uncertain. The connector failure itself sets\nretryable: false.\n\nNo lifecycle mutation has AIP rollback. A corrective status, assignment, note,\nor provider-catalogue update is a new governed intent against current state.\n\nCompletion criteria\n\nThe lifecycle is complete only when:\n• every required capability was admitted for the intended tenant route;\n• each mutation used one Action, one canonical input, and one retained key;\n• each approval matched the exact mutation input;\n• final provider reads confirm the intended state;\n• public replies and private notes have the intended visibility;\n• partial handoff effects have been resolved;\n• restricted evidence is stored under tenant policy;\n• no uncertain mutation was replaced with an uncorrelated retry.\n\nThese criteria establish a governed application workflow. They do not prove\nlive-product qualification, message delivery, or production readiness.\n\nRelated documentation\n• Conversation and message capabilities (../capabilities/conversations-and-messages.md)\n• AIP composite operations (../capabilities/aip-composite-operations.md)\n• Authentication and account isolation (../getting-started/authentication-and-account-isolation.md)\n• Approvals and policy (../../../concepts/approvals-and-policy.md)\n• Error reference (../../../reference/errors.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "04f6201887c4256dc84b44104095ef6e6d40d42b510eeeaa2eacba83efa786bc"
  }
}
