Skip to content

Automated trigger mode (Service Bus)

The full PointOfContactAI runtime offers three chat-start modes in the Teams dashboard (Settings → User groups): start with the AI agent, start with a human, or “Start with listening for automated trigger”. This page explains the trigger mode and the optional Azure Service Bus routing it enables.

What the mode does

  • Without Service Bus configured (the default), trigger mode behaves exactly like “Start with AI agent”: every visitor message is answered by the AI inline, in the same request that received it. Selecting the mode changes nothing until a namespace is configured.
  • With Service Bus configured, each visitor turn that would run the AI is instead published to a queue and processed by a queue consumer inside the same runtime. The visitor’s message is persisted and echoed to all surfaces before the enqueue, so the visible chat experience is unchanged — only the AI turn moves off the HTTP request path. This gives per-conversation ordering across instances and a stable, versioned message contract that external automation can build against.

If publishing to the queue ever fails (namespace outage, misconfiguration), the runtime logs the failure and falls back to processing the turn inline — availability wins over queueing, and no visitor message is ever silently dropped.

Prerequisites

Provisioned by infra/provision-servicebus.sh:

  • A Service Bus namespace on the Standard SKU — required because the queue uses sessions and duplicate detection, neither of which Basic supports.
  • A session-enabled queue (default name chat-trigger) with duplicate detection on, maxDeliveryCount: 3, a 2-minute lock (the runtime auto-renews during long AI streams), and a 1-day message TTL.
  • Azure Service Bus Data Sender + Azure Service Bus Data Receiver role assignments for the Function App’s identity (when using the identity-based connection).

Configuration

Exactly one of two app settings on the Function App enables the path:

App settingForm
SERVICEBUS_CONNECTION__fullyQualifiedNamespaceIdentity-based (preferred) — the bare namespace host, e.g. pocai-servicebus.servicebus.windows.net, resolved via the app’s managed identity and the two role assignments above. No secret anywhere.
SERVICEBUS_CONNECTIONConnection string. Must be a real app setting or a Key Vault reference — the queue trigger resolves it when the app starts, before any lazy secret loading runs.

Optional: CHAT_TRIGGER_QUEUE overrides the queue name (default chat-trigger).

The configuration is read once at startup and gates both the sending side and the queue consumer together, so a host can never enqueue turns it cannot consume. Leave both settings unset to disable the path entirely — trigger mode then falls back to the inline AI path, byte-for-byte identical to “Start with AI agent”.

The message contract (v1 — stable)

Each queued visitor turn is one JSON message:

{
"v": 1,
"kind": "visitorMessage",
"sessionId": "",
"visitorMessageId": "msg_…",
"sequenceNumber": 7,
"text": "the visitor's message",
"widgetId": "wgt_… or null",
"enqueuedAt": "2026-07-06T12:34:56.000Z"
}

Service Bus system properties:

  • messageId = visitorMessageId — the persisted visitor message id, so the queue’s duplicate detection makes producer retries exact.
  • Service Bus session id = chat sessionId — chat conversations map 1:1 to Service Bus message sessions, giving strict per-conversation FIFO and a single active consumer per conversation.

This v1 envelope is a stable contract for external automation consumers: the existing fields will not change shape or meaning within v: 1. Additive optional fields may appear without a version bump; breaking changes bump v. Consumers should treat any message with an unknown v or kind as not-for-them and drop it rather than fail.

Delivery semantics and failure behavior

  • At-least-once, made idempotent. The runtime records the last processed turn’s sequence number on the session, so a redelivered message that was already processed is completed without re-running the AI — no duplicate replies, no duplicate error bubbles.
  • Terminal conditions complete silently: an unparseable or unknown-version envelope, a session that no longer exists, a turn already processed, or a session an agent claimed while the turn sat in the queue.
  • Transient failures redeliver: the message is abandoned and retried, up to the queue’s maxDeliveryCount of 3.
  • Dead-lettering with a visitor-facing notice: on the final delivery attempt, the runtime first posts the standard AI-error bubble into the chat and turns the “thinking” indicator off — the visitor is never left staring at a permanent typing indicator — and then lets the message dead-letter. The dead-letter queue is drained operationally (Azure portal / CLI); there is no in-app DLQ reader.

Known limitations

  • “Stop generating” across instances: cancelling an in-flight AI reply only aborts streams running on the instance that received the cancel request. A queued turn may stream from a different instance, where the cancel is a no-op.
  • Queued turns don’t interrupt each other: in inline mode, a second visitor message aborts a still-streaming first reply. In queue mode, per-conversation FIFO means the second turn runs after the first completes.
  • Mode changes take up to 60 seconds: chat-start-mode settings are cached briefly, so flipping the radio in Settings can take up to a minute to affect routing on warm instances. Both routes run identical processing, so the window is harmless.