Skip to content

Add Activity Protocol adapter (Microsoft Copilot / Teams ingress) #247

Description

@jrosskopf

Background / why now. Triton's Microsoft-surface story was split across two
paths that each fall short: the MCP-App widget (rich, but M365-Copilot
declarative agents only — needs a paid Copilot seat, and Copilot Studio
can't render it) and A2A (works in Copilot Studio, but the UI is dropped
on the wire). The substrate interactive-UI epic chased the MCP-App widget and
hit that licensing/host wall. This issue is the pivot: an Activity Protocol
adapter emitting Adaptive Cards
reaches Copilot Studio (connected agent),
Teams, and M365 Copilot Chat over an open spec, with real interactive controls
and no paid-Copilot dependency. It supersedes the MCP-App-widget path for the
Microsoft surface (substrate #657 and children are being closed against this).

Add Activity Protocol adapter (Microsoft Copilot / Teams ingress)

Labels: adapter, enhancement, interop

Problem

Triton currently exposes MCP, A2A, REST and chat adapters, with A2UI as the
lowest-common-denominator UI wire format. None of these can deliver rich UI into
Microsoft Copilot.

Microsoft has two rendering paths into Copilot, and A2A is not one of them:

Path Wire format Reaches Notes
Activity Protocol Adaptive Card as Attachment Copilot Studio (connected agent), Teams, M365 Copilot Chat, WebChat, Agents Client SDK Open spec, no SDK required
MCP Apps HTML widget in sandboxed iframe M365 Copilot declarative agents only Toolkit-built agents; Copilot Studio does tool calls but no widgets
A2A text parts Copilot Studio orchestrator UI is dropped — see below

Copilot Studio's A2A connection is an orchestration channel only. Microsoft's own
integration table routes "agents built with Microsoft 365 Agents SDK" to Activity
Protocol, not A2A. Worse, Microsoft Agent Framework's A2A layer converts only
TextContent and UriContent to A2A parts and silently drops everything else
(DataContentDataPart is unimplemented, microsoft/agent-framework#2677), so
even a spec-legal structured payload would not survive the trip.

Consequence: without an Activity adapter, Triton is text-only on every Microsoft
surface.

Proposal

Add adapters/activity as a fourth ingress, siblings to the existing MCP/A2A/REST
adapters, with an A2UI → Adaptive Card 1.5 transpiler in the shared UI layer.

Scope — adapter

  • POST /api/messages accepting an Activity JSON object
  • Handle activity types: message, conversationUpdate, invoke,
    endOfConversation, typing; 200-ack anything else
  • invoke names: adaptiveCard/action (Action.Execute round-trip) and
    signin/tokenExchange (deferred, see below)
  • Inbound auth: validate Entra bearer JWT against the Bot Framework OpenID
    metadata endpoint; None mode for local dev
  • Outbound, synchronous: when inbound carries deliveryMode: "expectReplies",
    return reply activities in the HTTP response body — implement first,
    this is the path Copilot Studio's skill/connected-agent model has used
  • Outbound, asynchronous: POST {serviceUrl}/v3/conversations/{conversationId}/activities
    with a client-credentials token (scope https://api.botframework.com/.default)
  • Conversation/turn state keyed on conversationId + id, mapped onto the
    existing session abstraction (same role contextId plays for A2A)

Scope — UI transpile

  • A2UI basic catalog → Adaptive Card 1.5, emitted as an Attachment with
    contentType: application/vnd.microsoft.card.adaptive
  • Target 1.5, not 1.6: Copilot Studio accepts 1.6 but Teams and the D365
    chat widget cap at 1.5
  • Mapping (14 of 18 basic-catalog components are direct):
    • Row/Column → ColumnSet/Container
    • Card → Container with style, or the card root
    • Text/Image/Icon/Divider → TextBlock/Image/Icon†/separator
    • Video/AudioPlayer → Media
    • Button → Action.Submit (fire-and-forget) or Action.Execute (needs response)
    • TextField/CheckBox/DateTimeInput/MultipleChoice → Input.Text/Input.Toggle/
      Input.Date+Input.Time/Input.ChoiceSet
    • Slider → Input.Number (lossy, no track UI)
    • Tabs → stacked Containers + Action.ToggleVisibility (lossy)
    • Modal → Action.ShowCard (lossy, inline expansion not overlay)
    • List with template → expand server-side against the data model
  • Set fallbackText on every emitted card

Out of scope for this issue

  • MCP Apps widget path for M365 declarative agents — separate issue, different
    host, different capability matrix
  • Streaming (typing activities carrying a streaminfo entity) — nice for
    Copilot Chat, unnecessary for Copilot Studio delegation
  • Teams-specific channelData and Teams invoke names
  • SSO / on-behalf-of token exchange

Open question — blocks the transpiler, not the adapter

Does an orchestrating Copilot Studio agent relay a connected agent's card
attachments to the end user, or does it flatten them to text?

Under the old Bot Framework skill model attachments were forwarded. The current
connected-agent docs describe text round-trips only and say nothing about
attachments. Everything in "Scope — UI transpile" is wasted effort if the
orchestrator flattens.

Spike (timebox 1h): run CopilotStudioSamples/extensibility/agents-sdk/relay-bot
(or copilotstudio-skill) behind a dev tunnel, register it in Copilot Studio as a
Microsoft 365 Agents SDK agent with auth None, have it reply with a trivial
Adaptive Card, and observe what the orchestrator renders in the test canvas.

If it flattens, cards still reach the user via Azure Bot registration → Teams /
M365 Copilot Chat directly, bypassing the Copilot Studio orchestrator. The
adapter is worth building either way; only the deployment topology changes.

Notes / risks

  • No official Rust SDK for the Agents SDK. The spec in microsoft/Agents
    (specs/activity/protocol-activity.md, protocol-cards.md) is the only
    contract. Note it explicitly excludes card definitions — those live in the
    Adaptive Cards and Activity Protocol Cards specs and travel as attachments.
  • Legacy fixed-schema cards (Hero, Thumbnail, Receipt, SignIn, OAuth) are
    deliberately ignored. Teams already treats them as second class.
  • Local testing needs no Azure resources: the M365 Agents Playground (formerly
    Teams App Test Tool) speaks Activity Protocol to any local endpoint without a
    bot registration.

Acceptance criteria

  • Triton registers as a connected agent in Copilot Studio and completes a
    text round-trip
  • An A2UI surface with Row/Column/Text/Button/TextField renders as an
    Adaptive Card in at least one Microsoft host
  • A card button press arrives back as an invoke and mutates the A2UI data
    model
  • Spike result documented in this issue, transpiler scope confirmed or cut

† Adaptive Cards 1.6 / Teams extension — omit from the 1.5 baseline mapping.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    adapterIngress/egress adapterenhancementNew feature or requestinteropInteroperability / protocol integration

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions