





















@@ -11,6 +11,9 @@ scenario:
1111 - tools.message
1212 - channels.webchat
1313objective: Verify a current-chat reply is delivered as assistant text, not by calling `message(action=send)` and ending with `Sent.`.
14+gatewayConfigPatch:
15+session:
16+dmScope: per-channel-peer
1417successCriteria:
1518 - The visible outbound reply contains the requested marker exactly once.
1619 - The session transcript does not include a `message(action=send)` call followed by final assistant text `Sent.`.
@@ -24,7 +27,9 @@ scenario:
2427kind: flow
2528summary: Run a direct current-chat reply and inspect the actual transcript for self-message routing.
2629config:
30+conversationId: qa-operator
2731expectedMarker: WEBCHAT-DIRECT-REPLY-OK
32+promptSnippet: Reply exactly
28332934flow:
3035steps:
@@ -39,31 +44,56 @@ flow:
3944 - ref: env
4045 - 60000
4146 - call: reset
47+ - set: conversationId
48+value:
49+expr: config.conversationId
4250 - set: sessionKey
4351value:
44-expr: "`agent:qa:webchat-direct-reply:${randomUUID().slice(0, 8)}`"
52+expr: "buildAgentSessionKey({ agentId: 'qa', channel: 'qa-channel', accountId: 'default', peer: { kind: 'direct', id: `dm:${conversationId}` }, dmScope: env.cfg.session?.dmScope, identityLinks: env.cfg.session?.identityLinks })"
4553 - set: startIndex
4654value:
4755expr: state.getSnapshot().messages.length
48- - call: runAgentPrompt
49-args:
50- - ref: env
51- - sessionKey:
52-ref: sessionKey
53-message:
54-expr: "`Reply directly in this current chat with exactly ${config.expectedMarker}. Do not call the message tool.`"
55-timeoutMs:
56-expr: liveTurnTimeoutMs(env, 60000)
57- - call: waitForOutboundMessage
58-saveAs: outbound
56+ - set: requestCountBefore
57+value:
58+expr: "env.mock ? (await fetchJson(`${env.mock.baseUrl}/debug/requests`)).length : 0"
59+ - call: state.addInboundMessage
5960args:
60- - ref: state
61- - lambda:
62-params: [candidate]
63-expr: "candidate.conversation.id === 'qa-operator' && normalizeLowercaseStringOrEmpty(candidate.text).includes(normalizeLowercaseStringOrEmpty(config.expectedMarker))"
64- - expr: liveTurnTimeoutMs(env, 30000)
65- - sinceIndex:
66-ref: startIndex
61+ - conversation:
62+id:
63+ref: conversationId
64+kind: direct
65+senderId:
66+ref: conversationId
67+senderName: WebChat QA
68+text:
69+expr: "`Reply exactly \\`${config.expectedMarker}\\` in this current chat. Do not call the message tool.`"
70+ - try:
71+actions:
72+ - call: waitForCondition
73+saveAs: scenarioRequest
74+args:
75+ - lambda:
76+async: true
77+expr: "env.mock ? (await fetchJson(`${env.mock.baseUrl}/debug/requests`)).slice(requestCountBefore).find((request) => String(request.allInputText ?? '').includes(config.promptSnippet)) : true"
78+ - expr: liveTurnTimeoutMs(env, 60000)
79+ - 500
80+ - call: waitForOutboundMessage
81+saveAs: outbound
82+args:
83+ - ref: state
84+ - lambda:
85+params: [candidate]
86+expr: "candidate.conversation.id === conversationId && normalizeLowercaseStringOrEmpty(candidate.text).includes(normalizeLowercaseStringOrEmpty(config.expectedMarker))"
87+ - expr: liveTurnTimeoutMs(env, 60000)
88+ - sinceIndex:
89+ref: startIndex
90+catchAs: directReplyError
91+catch:
92+ - set: directReplyDebugRequests
93+value:
94+expr: "env.mock ? (await fetchJson(`${env.mock.baseUrl}/debug/requests`)).slice(requestCountBefore).map((request) => ({ plannedToolName: request.plannedToolName ?? null, plannedToolArgs: request.plannedToolArgs ?? null, allInputText: String(request.allInputText ?? '').slice(0, 400), finalText: String(request.finalText ?? '').slice(0, 200), toolOutput: request.toolOutput ? String(request.toolOutput).slice(0, 200) : null })) : []"
95+ - throw:
96+expr: "`direct reply marker missing: ${directReplyError?.message ?? directReplyError}; transcript=${formatTransportTranscript(state, { conversationId })}; requests=${JSON.stringify(directReplyDebugRequests)}`"
6797 - set: transcriptSummary
6898value:
6999expr: "await readSessionTranscriptSummary(env, sessionKey)"
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。