Upstream connectors are Triage’s intake surfaces: where the diagnostic questions are asked and the intent is born. They are never composerID destinations. composerID carries the decision downstream. Surface status follows the registry:
- Microsoft Teams: Beta. Bot Framework, Adaptive Cards, Microsoft Entra ID SSO.
- Slack: Roadmap. Same gateway; the Block Kit renderer ships in the reference implementation.
- Google Chat: Roadmap. Same gateway; the Cards v2 renderer ships in the reference implementation.
- ServiceNow: Roadmap. Service Portal widget and Employee Center; the decision publishes back into the same instance.
How it fits together
Nothing about the diagnostic moves into the chat platform. The questions, the scoring, the routing and the audit spine stay where they live today. The Intake Gateway only translates between chat cards and the same decision API the web intake uses. Solid arrows are the forward path. Dashed arrows are the return path: the publish receipt becomes a deep link on the completion card, and an enrichment request returns to the same thread as another card.Three components
Teams app package
A manifest, icons and a Microsoft Entra app registration. Installed once per tenant from the org catalog and authorised with a single admin consent. Nothing is deployed inside the tenant; the package only points at the gateway.
Intake Gateway
Receives bot activities, verifies the requester through Entra ID SSO, renders questions as Adaptive Cards and translates submissions back into answers. It holds the conversation position and nothing else. Renderer-agnostic: Slack and Google Chat are the same core with a different renderer.
Decision core, unchanged
The gateway calls the same evaluate contract as the web intake. Scoring, routing, anti-gaming pattern detection and Compliance File generation run server-side and are identical wherever the questions were asked.
From first question to published record
Steps 1 to 8 are the upstream connector. From step 9 the flow is standard composerID publishing: the five stages in How integrations work.1
The requester opens the bot
The requester opens the Triage bot in Teams, or is pointed at it the moment they ask for work in a channel. Where it runs: Teams.
2
Identity is verified
Entra ID SSO verifies the requester silently; there is no separate login. Contextual data is fetched in the background where the tenant tier allows. Where it runs: the gateway, against Entra ID.
3
The first question arrives
An Adaptive Card carries the prompt, embedded guidance and choice answers. Where it runs: gateway to Teams.
4
The answer locks
The answer is submitted and the card is replaced in place by its locked state: no inputs remain. Where it runs: the gateway.
5
The next question arrives
One card per question, in fixed order, for however many questions the tenant’s diagnostic defines. Where it runs: gateway to Teams.
6
The decision core scores and routes
On the final answer the gateway hands the complete answer set to the decision core. Scoring and routing produce the channel decision. Where it runs: the Triage decision core.
7
The Intent Record is minted
One traceable Intent ID. The Compliance File records the intake surface and the verified requester identity on the audit spine. Where it runs: the Triage decision core.
8
The completion card is sent
The card shows the recommended channel, confidence, rationale and the
intent:// chip. Where it runs: gateway to Teams.9
composerID preflights and publishes
composerID preflights the intent against the destination’s tenant requirements and publishes it into the system or systems of record, idempotently. Where it runs: composerID.
10
The receipt returns to the thread
The completion card gains a deep link to the created record. If a destination needs a missing field, the enrichment request returns to the same thread as another card. Where it runs: composerID to gateway to Teams.
The card lifecycle keeps the diagnostic honest
The intake has deliberate properties, and they are what make the decision defensible. Each one maps to a card mechanic, so the chat surface enforces them by construction rather than by policy.One question per screen
One question per screen
One card per message. The next question only arrives after the current one is answered.
Answers lock on submission
Answers lock on submission
The submission replaces the card with a version that has no input elements left. There is nothing to edit.
Anti-gaming pattern detection
Anti-gaming pattern detection
Runs server-side in the decision core: identical to the web intake, invisible to the surface.
Abandonment leaves no record
Abandonment leaves no record
If the thread goes quiet mid-flow, partial answers are not persisted: no Compliance File, no Intent Record.
Identity and tenancy
Identity
Entra ID SSO verifies the requester silently: the person answering is the person signed in to Teams. That verified identity rides the audit spine into the Compliance File, so “who asked for this?” is answered by the record.Tenancy
The app package is published to the tenant’s org catalog and authorised with one admin consent. Per-tenant configuration (the question set, tiers, contextual data sources) lives in Triage, not in the package, so updating the diagnostic never means reinstalling the app.Where composerID takes over
The trigger: a completed assessment becomes an intent
Triage tells composerID that a decision was made the same way a destination tells it that a record changed: a signed webhook.POST /triggers/triage/{tenant} accepts the completion event, verifies the X-Signature-HMAC-SHA256-1 header against the tenant’s webhook signing key, and mints the intent. The Intent ID is derived from the assessment response id, so if Triage delivers the same completion twice, the second delivery returns the existing intent rather than creating another.
$TENANT and $WEBHOOK_KEY are the tenant and webhook_signing_key from minting sandbox credentials. The answers land in the intent payload through the tenant’s question map, the rank-1 channel becomes payload.channel, and the provenance (response id, score, completion time) is recorded under payload.source, never the diagnostic content itself.
The sandbox reads the completed assessment from the delivery (
data.response). A deployment connected to a Triage tenant fetches it by responseId instead, and the delivery need carry only the id. The endpoint reference has the full shapes.{intent_id}-{version}-{destination}, external IDs and a receipt on the timeline, then the webhook and reconciliation contract that keeps the record truthful. Publishing and Events document each stage. Two returns are specific to the chat surface.
The deep link
When the publish receipt lands, the completion card is updated with a link straight to the record composerID created. The requester watches their ask become a requisition, an SOW or an agreement without leaving the thread.The enrichment loop
If preflight finds a gap the diagnostic did not cover (a cost centre, a location code), theenrichment_request comes back to the same thread as another card.
Run the reference implementation
Theupstream/ package is the executable version of this page: standard-library Python, no network, the same conventions as the adapter spine. It is a sandbox, and its contract tests pin the intake properties above.
Next steps
Microsoft Teams
Bot Framework, Adaptive Card versions, Entra ID SSO and proactive messages.
Destination catalogue
Every downstream system composerID publishes into, with its coverage status.
How integrations work
The five publishing stages that begin once the Intent ID exists.