Skip to content

Guided tour

FabrCore 2.0 · Release and package availability

These guides track the current 2.0 source. Stable 2.0.0 publication is pending; package commands show the release target. Until it is published, follow the source quick start or use a matching available prerelease set. Release migration · Runtime modes

MODULE 05 · LESSON 5.10

Render and handle Adaptive Cards

Return Adaptive Cards and route actions through trusted application code.

Lesson 30 of 86 · FabrCore 2.0

Overview

A deterministic card is appropriate when the agent already knows the data and layout. The card is a UI contract, not authorization. Surface validates the expanded envelope and routes actions back through the selected handler/agent. Model-planned cards are display-only unless trusted code adds explicit actions.

A card is a structured presentation contract

An Adaptive Card carries a defined layout and values so the client can render a request summary consistently. When trusted code already knows SR-1042's fields, construct the card deterministically. A model-planned card should not gain executable business actions merely because its generated JSON mentions them.

Action handling belongs to trusted code

A button press sends an action payload back to the selected handler/agent. Resolve the request again and validate the caller's permission before changing anything. The displayed status may have become stale since the card was rendered. A safe handler distinguishes malformed, unauthorized and already-completed actions instead of relying on the button's label.

Produce and handle a card

Download the Operations Desk source. The README lists project setup, package prerequisites and local ports.

  1. Create an AdaptiveCardSurfaceEnvelope for SR-1042 and call the Surface render service with the source message. Prefer template/data separation for repeated layouts.
  2. Use SurfaceActions helpers for deterministic routed actions and validate the principal, request ID and requested operation on submission.
  3. Keep text-only channel fallbacks for A2A or clients without the renderer. Validate after template expansion and restrict URLs/actions through host policy.
producer-side.md · reference snippet
services.AddFabrCoreSurfaceServices(options =>
{
    options.DefinitionFilePath = "fabrcore-surface.json";
    options.DefaultSurfaceDefinitionName = "default";
    options.DefaultPlanningModelName = "planner";
});
producer-side.md · reference snippet
builder.AddFabrCoreSurfaceFromConfig("fabrcore-surface.json", "crm-demo");
builder.Services.AddFabrCoreSurfaceComponents();

Test display and action separately

  1. Render a read-only SR-1042 summary card and compare its fields with the fixture record. Confirm an unsupported/malformed payload produces a controlled fallback rather than breaking the conversation.
  2. Add one explicitly authorized test action through trusted code. Invoke it and verify the handler receives the expected request ID and validates current state.
  3. Replay the action or change its request ID in a test. It must not perform an unauthorized or duplicate mutation merely because the card once appeared in the UI.

A rendered card verifies the presentation contract. Only the independently checked handler verifies the business action.

If the result is different

A card rendered on the server does not mean every channel can display it. Avoid telling an A2A caller that an invisible form was rendered.

Go deeper

Explore the related documentation.