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.
- Create an AdaptiveCardSurfaceEnvelope for SR-1042 and call the Surface render service with the source message. Prefer template/data separation for repeated layouts.
- Use SurfaceActions helpers for deterministic routed actions and validate the principal, request ID and requested operation on submission.
- Keep text-only channel fallbacks for A2A or clients without the renderer. Validate after template expansion and restrict URLs/actions through host policy.
services.AddFabrCoreSurfaceServices(options =>
{
options.DefinitionFilePath = "fabrcore-surface.json";
options.DefaultSurfaceDefinitionName = "default";
options.DefaultPlanningModelName = "planner";
});
builder.AddFabrCoreSurfaceFromConfig("fabrcore-surface.json", "crm-demo");
builder.Services.AddFabrCoreSurfaceComponents();
Test display and action separately
- 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.
- Add one explicitly authorized test action through trusted code. Invoke it and verify the handler receives the expected request ID and validates current state.
- 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.