語音代理聽起來可能很專業、回應即時,卻可能在短短一句話中造成信任危機:「不要再打電話給我。」
如果該請求只更新 SMS 路徑,你的代理可能明天仍繼續撥打。若僅更新通話逐字稿,你的後續工作流程可能仍持續發送簡訊。對於推出 AI 撥號器、收件匣代理、排程機器人或多步驟推廣工作流程的開發者而言,同意不再是靜態的勾選框,而是執行階段的狀態。
這正是 AI 同意記錄 的用武之地。它為每個代理動作提供簡單規則:在聯絡、豐富、錄製或升級某人之前,先從單一持久來源檢查最新的同意狀態。
本指南將說明如何設計該記錄,而不讓你的產品變成合規迷宮。
本文件提供技術架構指導,並非法務建議。若你的工作流程涉及受管制的推廣、健康、金融、就業或敏感個人資料,請務必諮詢合格的法務審查人員。
為什麼 AI 代理讓同意管理變得更困難
傳統應用程式通常在可預期的時機要求權限:註冊、電子報訂閱、Cookie 橫幅、電話號碼擷取,或帳單同意。
AI 代理模糊了這個界線。
一個實際運作的代理可能:
- 接聽來電
- 摘要語音信箱
- 傳送後續連結簡訊
- 排程另一次通話
- 豐富 CRM 紀錄
- 觸發下週的活動步驟
- 將案件轉交給真人
- 工具呼叫失敗後重試
- 從語音切換至 SMS 或電子郵件
每個步驟本身可能都合理,但當同意在某個頻道變更,而工作流程的其他部分卻未察覺時,風險便會浮現。
常見的失敗模式很簡單:
- 使用者在眼前頻道撤銷權限。
- 代理將訊息記錄為對話文字。
- 另一個工作流程因未檢查撤銷狀態而持續執行。
這不是 LLM 的問題,而是狀態管理問題。
什麼是 AI 同意記錄?
AI 同意記錄 是一份附加式權限事件紀錄,加上快速讀取模型,用以回答一個問題:
這個特定代理現在是否被允許對這個人執行這個特定動作?
該記錄應追蹤跨頻道、身分、代理、工作流程、工具與時間的同意與撤銷。
它不只是一欄 subscribed: true。
實用的記錄會儲存:
- 同意屬於誰
- 適用於哪個頻道
- 涵蓋什麼目的
- 何時授予或撤銷
- 如何擷取
- 哪個工作流程或代理對其採取行動
- 支持決策的證據
- 撤銷是否應停止單一頻道或所有相關推廣
對 AI 工作流程而言,最重要的不是日誌,而是動作前的政策檢查。
團隊最常忽略的同意接觸點
首先,請繪製出代理可能建立、使用或變更權限狀態的每個位置。
1. 語音撤銷
使用者可能說:
- 「不要再打電話給我。」
- 「把我從名單中移除。」
- 「不要再聯絡這個號碼。」
- 「只寄電子郵件給我。」
- 「改傳簡訊給我。」
- 「我沒有要求這個。」
不要將這些語句埋在逐字稿中。請將它們萃取為候選同意事件。
語音撤銷的困難在於代理可能在長對話中聽到。你需要一個獨立的分類器或確定性語句層,專門監控權限變更,而非僅產生最終摘要。
2. SMS 關鍵字與自然語言
多數團隊會先處理 STOP、UNSUBSCRIBE 與 START。這是必要的,但使用者不一定會使用精確關鍵字。
你也需要捕捉自然語言:
- 「請不要再傳簡訊給我」
- 「打錯號碼」
- 「改打我辦公室電話」
- 「不感興趣,請移除我」
精確關鍵字可採用確定性處理;自然語言則可先分類,不確定時再路由至確認或人工審核。
3. 電子郵件與通知偏好設定
代理可能從原本以語音為基礎的工作流程起草或傳送電子郵件。若電子郵件有獨立的同意目的,記錄必須知道這一點。
同意不應因為代理有其他可用工具而悄悄擴張。
4. CRM 匯入與過時名單
許多 AI 工作流程從匯入的聯絡人開始。該匯入可能包含舊的同意標記、部分頻道歷史,或完全沒有證據。
請將匯入的權限視為較低信任等級,直到驗證為止。儲存來源與時間戳記,以便代理選擇更安全的模式。
5. 人工覆寫
人類需要覆寫路徑,但覆寫應為帶有理由的明確事件,而非隱形的管理員編輯。
良好的覆寫紀錄應回答:
- 誰變更了狀態
- 為什麼變更
- 審核了哪些證據
- 變更是暫時還是永久
實用的同意資料模型
保留寫入模型為附加式。從中建立獨立的目前狀態檢視。
以下是簡潔的 TypeScript 風格模型:
type ConsentChannel = "voice" | "sms" | "email" | "push" | "in_app";
type ConsentPurpose =
| "support_followup"
| "appointment_reminder"
| "marketing_outreach"
| "transactional_update"
| "recording"
| "data_enrichment";
type ConsentEventType =
| "granted"
| "revoked"
| "limited"
| "confirmed"
| "expired"
| "human_override";
type ConsentEvent = {
id: string;
tenantId: string;
subjectId: string; // person/customer/contact
normalizedContact: string; // phone/email/device id hash
channel: ConsentChannel;
purpose: ConsentPurpose;
eventType: ConsentEventType;
scope: "single_channel" | "all_channels" | "all_outreach";
source: "voice_agent" | "sms_keyword" | "web_form" | "crm_import" | "human";
evidenceRef: string; // transcript span, form id, message id, admin note
confidence: number; // 0..1 for AI-extracted events
workflowRunId?: string;
agentId?: string;
createdAt: string;
expiresAt?: string;
};
Enter fullscreen mode Exit fullscreen mode
有幾個細節很重要:
-
scope可防止「不要打電話」在政策未允許的情況下意外變成「停止一切」。 -
purpose可避免預約提醒的同意被誤用為行銷推廣。 -
evidenceRef讓你能夠解釋系統為何做出該決定。 -
confidence可讓不確定的 AI 擷取事件暫停,而非盲目行動。
每個代理動作所需的執行階段檢查
在任何狀態變更或聯絡動作之前,先向記錄索取決策。
type ConsentDecision = {
allowed: boolean;
reason: string;
matchedEventIds: string[];
requiresHumanReview?: boolean;
safeAlternative?: "do_not_contact" | "in_app_only" | "ask_for_confirmation";
};
async function canAgentAct(input: {
tenantId: string;
subjectId: string;
channel: ConsentChannel;
purpose: ConsentPurpose;
action: "call" | "text" | "email" | "record" | "enrich";
workflowRunId: string;
}): Promise<ConsentDecision> {
const state = await consentStore.currentState(input);
if (state.hasGlobalRevocation) {
return {
allowed: false,
reason: "Subject revoked all outreach",
matchedEventIds: state.blockingEvents,
safeAlternative: "do_not_contact",
};
}
if (state.channelRevoked) {
return {
allowed: false,
reason: `${input.channel} permission was revoked`,
matchedEventIds: state.blockingEvents,
safeAlternative: "in_app_only",
};
}
if (!state.hasPurposeGrant) {
return {
allowed: false,
reason: `No active consent for ${input.purpose}`,
matchedEventIds: [],
safeAlternative: "ask_for_confirmation",
};
}
return { allowed: true, reason: "Active consent found", matchedEventIds: state.grantEvents };
}
Enter fullscreen mode Exit fullscreen mode
代理不應擁有最終決定權。它可以請求動作,但由你的後端決定該動作是否被允許。
如何從語音逐字稿處理撤銷
語音代理需要在逐字稿周圍建立小型管線。
步驟 1:擷取逐字稿片段
不要只儲存完整的逐字稿區塊。請儲存帶有時間碼的片段。
{
"span_id": "span_928",
"speaker": "user",
"text": "Please stop calling this number. Texts too.",
"start_ms": 184200,
"end_ms": 188700
}
Enter fullscreen mode Exit fullscreen mode
步驟 2:萃取同意意圖
對明顯語句使用確定性規則,對較模糊的語言則使用 LLM 分類器。
{
"intent": "revocation",
"channels": ["voice", "sms"],
"scope": "all_outreach",
"confidence": 0.94,
"evidence_span_id": "span_928"
}
Enter fullscreen mode Exit fullscreen mode
步驟 3:套用信心政策
範例政策:
- 信心
>= 0.90:立即寫入撤銷事件 - 信心
0.65 - 0.89:暫停工作流程並請求人工審核 - 信心
< 0.65:儲存為訊號,不自動變更狀態
對於撤銷,寧可誤判也應避免持續不必要的聯絡;對於新的同意授予,則應更嚴格。
步驟 4:停止進行中的工作流程
記錄寫入應發出事件,以取消或暫停相關工作流程。
await eventBus.publish("consent.revoked", {
tenantId,
subjectId,
channels: ["voice", "sms"],
scope: "all_outreach",
evidenceRef: "call_123:span_928",
});
Enter fullscreen mode Exit fullscreen mode
接著工作程式應停止後續步驟:
on("consent.revoked", async (event) => {
await workflowStore.pauseRuns({
tenantId: event.tenantId,
subjectId: event.subjectId,
affectedChannels: event.channels,
reason: "consent_revoked",
});
});
Enter fullscreen mode Exit fullscreen mode
若撤銷未能取消已排程的工作,該記錄就只是一本日記,而非控制系統。
設計頻道感知規則
並非每個權限事件都有相同的意義。
請使用政策矩陣:
| 使用者陳述 | 建議範圍 | 預設動作 |
|---|---|---|
| “Stop texting me” | 僅限 SMS | 封鎖 SMS,允許其他已授權的頻道 |
| “Stop calling me” | 僅限語音 | 封鎖通話,允許其他已授權的頻道 |
| “Do not contact me” | 所有推廣 | 封鎖語音、SMS、電子郵件、推播 |
| “Wrong number” | 聯絡方式 | 封鎖該電話號碼,並標記身分品質 |
| “Email me instead” | 頻道偏好 | 封鎖目前頻道,要求檢查電子郵件權限 |
| “Do not record this” | 錄製目的 | 停止錄製,僅在工作流程允許時繼續 |
此矩陣應存在於程式碼或政策設定中,而非提示詞內。
記錄在架構中的定位
簡單的生產流程如下:
- 代理提出動作。
- 執行階段政策檢查工具權限。
- 同意記錄檢查使用者權限。
- 速率限制器檢查預算與頻率。
- 工具執行者執行動作。
- 稽核日誌記錄決策與證據。
此順序很重要。請勿先呼叫工具,再檢查同意。
對於語音代理,請在兩個方向放入記錄:
- 在撥出通話或簡訊之前
- 在即時通話中出現撤銷時
- 在通話結束後處理摘要時
- 在活動重試之前
- 在人工交接後續動作之前
可觀測性:應記錄什麼
每次同意決策都應產生小型收據。
{
"decision_id": "cd_456",
"workflow_run_id": "run_789",
"agent_id": "voice_followup_agent",
"subject_id": "contact_123",
"requested_action": "sms.followup",
"purpose": "appointment_reminder",
"allowed": false,
"reason": "sms permission revoked",
"matched_event_ids": ["ce_111"],
"created_at": "2026-07-30T06:08:00Z"
}
Enter fullscreen mode Exit fullscreen mode
這有助於除錯與使用者信任。當有人詢問代理為何聯絡或未聯絡時,你能提供具體答案。
請追蹤以下指標:
- 各頻道偵測到的撤銷次數
- 需要審核的不確定同意事件
- 被封鎖的代理動作
- 撤銷後暫停的工作流程
- 從撤銷到工作流程取消的時間
- 有匯入同意但無證據的聯絡人
- 誤判與漏判的審核結果
關鍵指標不是「傳送了多少則訊息」,而是「有多少動作被正確允許、封鎖或暫停」。
常見錯誤
錯誤 1:將提示詞視為政策
系統提示詞可以告訴代理尊重同意,但無法在重試、工作程式、佇列與整合中強制執行同意。
政策應屬於後端檢查。
錯誤 2:僅儲存目前狀態
單一 can_contact=false 旗標會隱藏決策原因。你需要事件歷史以進行稽核、除錯與安全還原。
錯誤 3:忽略目的
傳送登入碼的權限,不等於傳送行銷序列的權限。請將同意與目的綁定。
錯誤 4:讓已排程工作繞過檢查
佇列中的工作應在執行時檢查同意,而非僅在排程時檢查。同意可能在排程與傳送之間發生變化。
錯誤 5:跨頻道擴張同意
若使用者提供電話號碼用於提醒,不要假設代理可永久撥打、傳送簡訊、豐富資料、錄製並寄送電子郵件。擴張必須是明確的。
小型實作檢查清單
可作為初步檢查:
- [ ] 列出代理可能聯絡、錄製、豐富或更新個人的所有動作。
- [ ] 為每個動作定義目的。
- [ ] 建立附加式同意事件。
- [ ] 建置目前狀態讀取模型。
- [ ] 在工具執行前加入後端同意檢查。
- [ ] 從語音與 SMS 萃取撤銷。
- [ ] 在撤銷後暫停進行中的工作流程。
- [ ] 儲存證據參照,而非僅儲存旗標。
- [ ] 為不確定的 AI 擷取事件加入人工審核。
- [ ] 記錄同意決策收據。
- [ ] 在撤銷後測試佇列工作。
- [ ] 個別審核匯入的 CRM 同意。
測試記錄
根據真實失敗模式建立測試案例。
it("blocks scheduled SMS after spoken all-channel revocation", async () => {
await ledger.append({
subjectId: "c1",
channel: "voice",
purpose: "marketing_outreach",
eventType: "revoked",
scope: "all_outreach",
source: "voice_agent",
confidence: 0.96,
evidenceRef: "call_1:span_9",
});
const decision = await canAgentAct({
tenantId: "t1",
subjectId: "c1",
channel: "sms",
purpose: "marketing_outreach",
action: "text",
workflowRunId: "run_1",
});
expect(decision.allowed).toBe(false);
expect(decision.reason).toContain("revoked");
});
Enter fullscreen mode Exit fullscreen mode
也請測試:
- SMS
STOP在政策設定為所有推廣時,封鎖後續語音。 - 「改寄電子郵件給我」不會在未取得電子郵件權限時寄送電子郵件。
- 匯入的 CRM 同意會過期或需要驗證。
- 低信心撤銷會暫停工作流程。
- 人工覆寫會建立事件與收據。
- 重試中的工作程式會在執行前重新檢查同意。
與更廣泛 AI 架構的連結
同意記錄最適合與其他執行階段控制並存:
- 執行階段政策 決定工具呼叫是否安全。
- 速率限制 控制頻率與支出。
- 租戶隔離 防止跨客戶狀態洩漏。
- 輸出來源 儲存生成決策的證據。
- 核准閘道 暫停高風險動作以供審核。
同意是大型系統中的一條界線。但這是使用者能立即理解的界線。如果他們說停,系統就應該停。
常見問題
什麼是 AI 同意記錄?
AI 同意記錄是一份附加式同意與撤銷事件紀錄,加上執行階段讀取模型,用以決定 AI 代理是否可以聯絡、錄製、豐富或代表某人採取行動。
這只適用於語音代理嗎?
不是。語音代理讓問題變得明顯,但相同的模式也適用於 SMS 代理、電子郵件代理、支援副駕、CRM 自動化、通知系統,以及使用個人資料的 AI 工作流程。
LLM 可以決定同意是否存在嗎?
LLM 可以協助分類「請讓我安靜」等模糊語言,但不應作為最終強制執行層。請撰寫候選事件、套用信心規則,並由後端政策做出決定。
單一頻道的撤銷是否應停止所有頻道?
這取決於使用者陳述、產品政策與法律情境。「不要再傳簡訊給我」可能是頻道專屬;「不要聯絡我」通常應停止所有推廣。請將此編碼在政策矩陣中。
佇列中的工作是否需要再次檢查同意?
需要。昨天排程的工作今天可能已失效。每個佇列中的聯絡動作都應在執行前立即檢查最新的同意狀態。
我應該先建置什麼?
從撤銷開始。擷取 SMS 關鍵字、語音停止語句、在撥出動作前進行目前狀態檢查,以及工作流程取消。之後再加入目的層級授予、審核佇列與更豐富的證據收據。
結語
AI 代理讓工作流程更快,但速度也讓同意錯誤的代價更高。最安全的模式很簡單:代理可以提出聯絡,但由記錄決定聯絡是否被允許。
如果某人在某處撤銷權限,所有相關工作流程都應在下一個工具呼叫執行前收到通知。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.