For the complete documentation index, see llms.txt. This page is also available as Markdown.

Approval-Gated Integration Writes

Require human approval before an agent performs an integration write. Approved writes resume on the agent's next turn across streaming chat, REST, and SMS.

Approval gating puts a human in the loop before an agent calls a write endpoint on one of your integrations. When a gated tool is invoked, the agent parks the call instead of executing it. An operator approves or rejects it, and the agent performs (or declines) that same write on its next turn - on streaming chat, REST, and SMS alike.

This guide covers the approval lifecycle and how to decide what to gate. For the approval_policy field and integration approval request/response schemas, use the Integrations API reference. Approval decisions require review-queue permission, but the decision endpoints are conversation-scoped integration endpoints.

This is not the external write proposal queue. An integration's approval_policy parks one Platform Integration call inside a supported conversation and resolves it through /integrations/approvals/.... It does not create an ExternalWriteProposal. External write proposals belong to a separate, private-preview connector write-back flow described in Review Queue.

Approval gates the integration call, not the underlying decision. Approving a refill write means "send the refill request to the pharmacy queue," not "this refill is clinically approved." Word agent and reviewer copy accordingly.

Key Concepts

  • Parked write: when the agent calls a gated endpoint, the exact tool name and parameters are stored and the agent receives an awaiting_approval result. Nothing reaches the external system yet.

  • Durable decision: the operator's approve/reject is recorded durably and scoped to the authenticated workspace, so it survives across turns and transports and stays tenant-isolated.

  • Single-consumption resume: the agent consumes one decision atomically so duplicate turn or event processing does not intentionally execute the parked write twice.

  • One pending write per conversation: a second gated write while one is already parked is refused with approval_pending_elsewhere rather than overwriting the first.

Approval gating applies to text and SMS conversations. Voice approval behavior is intentionally not implied by the public REST integrations surface.

Lifecycle

The decision is stored independently of a streaming connection and consumed once from the next supported turn, so REST and SMS do not depend on a live event stream. Server-sent events can provide an immediate-resume nudge for streaming clients, but they are a UI signal rather than the decision record.

After a grant is consumed, the integration write is attempted synchronously and is not automatically reconciled. A returned integration error is reported to the agent. If execution is interrupted after decision consumption, verify the destination before deciding whether a manual retry is safe.

If the parked write has expired by the time the decision is consumed, the agent reports that the action did not complete rather than falsely confirming success.

Approval Policies

Approval is configured per integration with approval_policy. The default is none, so existing integrations are unaffected until you opt in.

approval_policy

Effect

Use it for

none (default)

No approval required.

Safe reads and low-risk writes.

writes

POST, PUT, PATCH, DELETE require approval; GET runs normally.

Typical EHR and scheduling integrations.

all

Every endpoint requires approval, including reads.

Sensitive systems where even reads should be reviewed.

Set it on create or update of the integration. Treat a missing value on older integrations as none. See Integrations → Approval Policies.

Operator Decisions

Parked writes should be shown to operators with the identity, payload, and evidence needed to decide. The approval decision itself is conversation-scoped: the operator approves or rejects the pending write for the conversation, and the agent consumes that decision on its next turn.

Approve the parked write:

Approve a pending integration-write approval

post

Approve a pending human-in-the-loop integration-write approval for a conversation. Publishes integration.approval_granted to the workspace event channel; the subscribed text session fires the gated write. Requires ReviewQueue.review permission.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
conversation_idstring · uuidRequired
Responses
200

Successful Response

application/json

Resolution outcome for a pending integration-write approval.

statusstring · enumRequiredPossible values:
conversation_idstring · min: 1 · max: 256Required
post/v1/{workspace_id}/integrations/approvals/{conversation_id}/approve
POST /v1/{workspace_id}/integrations/approvals/{conversation_id}/approve HTTP/1.1
Host: platform.api-us.concurrence.com
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "status": "granted",
  "conversation_id": "text"
}

Reject the parked write. The reason is surfaced to the agent when provided:

Reject a pending integration-write approval

post

Reject a pending human-in-the-loop integration-write approval for a conversation. Publishes integration.approval_rejected to the workspace event channel; the subscribed text session declines the gated write. Requires ReviewQueue.review permission.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
conversation_idstring · uuidRequired
Body

Reject body — optional free-text reason surfaced to the agent.

reasonstring · max: 2000 · nullableOptional
Responses
200

Successful Response

application/json

Resolution outcome for a pending integration-write approval.

statusstring · enumRequiredPossible values:
conversation_idstring · min: 1 · max: 256Required
post/v1/{workspace_id}/integrations/approvals/{conversation_id}/reject
POST /v1/{workspace_id}/integrations/approvals/{conversation_id}/reject HTTP/1.1
Host: platform.api-us.concurrence.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 17

{
  "reason": "text"
}
{
  "status": "granted",
  "conversation_id": "text"
}

These endpoints require ReviewQueue:Review permission. conversation_id is the durable text conversation ID: a UUID for web conversations and the SMS routing key for SMS conversations. UUID-form conversation IDs are verified against the authenticated workspace; durable approval decisions are also scoped to the authenticated workspace.

Deciding What to Gate

Require approval when a write is hard to reverse, touches a source of truth, carries PHI, or was assembled from inferred conversation data. Allow direct writes only for low-risk operations your policy has cleared.

Whatever the write, a parked item must carry enough context for the operator to decide:

  • Identity of the subject, and how confident the match is.

  • Target system and object the write lands on.

  • Payload preview - and for updates, the diff (old → new), not just the final value.

  • Source evidence - transcript or form data the write was derived from, with inferred fields marked.

  • Risk notes - same-day slot, controlled substance, third-party recipient, duplicate-record risk, and so on.

Common write categories

Category
Require approval when
Reviewer needs

Scheduling (book / cancel / reschedule)

Scarce or same-day slots, fee implications, two-write reschedules, or uncertain identity/intent.

Patient identity, requested service, provider/time, current vs. proposed appointment, payload preview.

Forms & intake

Clinical, legal, or billing fields, or any field inferred from the conversation.

Form name, completed answers, inferred fields marked, missing fields, submission payload.

Medication / refill

Always for medication writes unless policy clears low-risk queue creation; strongly for controlled substances or dosage changes.

Patient, medication, dosage, pharmacy, urgency/symptoms, target queue. Confirm request submitted, not refill approved.

EHR write-back

Clinical notes, problem lists, identity/insurance fields, or other source-of-truth updates.

Field, old value, new value, source evidence, payload diff.

Outbound messages

PHI-bearing content, sensitive topics, third-party recipients, or non-templated copy.

Recipient, channel, message body, PHI/sensitivity label, send reason.

Safety escalation

Any outreach or task write driven by a clinical, legal, or classifier signal.

Risk signal, classifier confidence, patient identity, response SLA, proposed alert/outreach. The classification is not the write - the alert is.

Record creation (add patient / chart / ticket)

Creating a source-of-truth identity, especially with duplicate risk or voice/OCR-derived fields.

Demographics, identity confidence, duplicate-search results, proposed payload; return the new record ID before downstream writes.

Last updated

Was this helpful?