Introducing FabrCore Surface — Adaptive Card UX for Distributed Agents

Eric Brasher | May 29, 2026 at 9:15 AM CDT | 8 min read

FabrCore agents can already reason, call tools, send messages, coordinate with other agents, and persist their state. The next practical question is simpler and harder: how should an agent show useful work to a person inside a real application? FabrCore Surface is our experimental answer.

Surface is an Adaptive Cards bridge for FabrCore agents and Blazor apps. It lets agents send structured, validated UI to a user without generating arbitrary HTML, JavaScript, Razor, or app routes. The result is a narrow visual contract that product teams can render, secure, and maintain.

Surface Preview
validated card
Check this exception and show me the next action.
Adaptive Card Surface Envelope

Approve rush replacement order?

The agent found one policy exception and rendered the decision point as a host-validated card.

Request REQ-1048
Variance 7.8%
Route app + agent
Approve Ask follow-up Open record

Why Surface Exists

Chat is good for conversation, but a lot of business work is not naturally conversational. Approvals need buttons. Quotes need line items. Dispatch workflows need forms. Monitoring needs status panels. A document review might need a short list of issues, a confirmation button, and a link back to the source record.

The tempting approach is to let an agent produce UI directly. That is also the dangerous approach. If an AI can emit arbitrary markup or application commands, the host app now has to defend itself from every mistake the model can make. Surface takes the opposite path: agents produce Adaptive Card envelopes, and the host decides what is allowed.

Adaptive Cards are intentionally constrained. They are expressive enough for approvals, forms, lists, facts, and task cards, but they do not grant the model direct access to the app shell. That makes them a strong fit for agent-generated business UI.

The Surface Contract

Every rendered Surface payload is an AdaptiveCardSurfaceEnvelope. The envelope contains a version, an id, an Adaptive Card JSON object, optional template data, and metadata. It travels through normal FabrCore messaging as a ui.render message with the media type application/vnd.fabrcore.surface.adaptive-card+json.

That sounds technical because it is technical, but the reason is straightforward: the UI becomes a normal message. It can be routed, persisted, inspected, tested, and replayed using the same FabrCore infrastructure as any other agent event.

Agents can create the envelope deterministically when they already know the data and layout. They can also call PlanAndRenderAsync when a configured planner model should produce the card. Either way, Surface keeps the final artifact in the same contract.

Rendering in Blazor

On the client side, Surface provides two main experiences. DynamicAgentSurface is the embeddable component: drop it into a Blazor screen, bind it to a user handle, and it listens for valid Surface render messages. The command center is the full workspace experience, mapped at /surface, with agent directory, chat, live status, shared agents, Adaptive Card rendering, optional diagnostics, and a feature-gated Create Agent flow.

The command center intentionally separates delivery from response expectation. By default it sends chat work fire-and-forget while still using normal request messages, so an agent can process work asynchronously and publish status, progress cards, and final messages as separate events. That is a better shape for long-running agent work than forcing everything through one blocking request-response turn.

Actions Are Explicit

A card without actions is a report. A card with actions becomes workflow. Surface supports standard Adaptive Card actions such as Action.Execute and Action.Submit, but any meaningful side effect must route explicitly.

An action can route to the app, to the source agent, or to both. App-side work goes through an ISurfaceActionRegistry supplied by the host application. Agent-side work becomes a follow-up FabrCore message, usually built from an explicit message template and payload. Surface also provides SurfaceActions helpers so producers do not hand-assemble the routing shape.

This is the important boundary: Surface can carry the user intent, but the consuming app still owns authorization, data validation, and the actual mutation. That keeps business rules in trusted code instead of hiding them in generated UI.

Validation Before Rendering

Before a card reaches the browser, Surface validates the envelope and the expanded Adaptive Card. The policy covers schema version, payload size, nesting depth, allowed action types, optional verb restrictions, target-agent restrictions, URL safety, and Adaptive Cards parser compatibility.

Validation is not a replacement for domain authorization. It is the first gate. It keeps the visual contract inside expected bounds, then the app handler applies the business rules for whatever the user clicked.

What This Enables

Surface is useful anywhere an agent needs to move from “here is text” to “here is a structured thing you can act on.” A few examples:

  • Approval workflows where an agent summarizes a request and presents approve/reject actions.
  • Operational dashboards where agents publish live task status, warnings, and next actions.
  • Customer or case views where a domain agent returns a compact card with key facts and navigation actions.
  • Data collection where an agent asks for missing fields through an Adaptive Card form.
  • Agent creation and management where the Surface command center discovers available agent types, tools, plugins, aliases, and MCP servers before creating a configuration.

In each case, the user gets an interface that feels like application work, while the developer gets a message contract that stays testable and host-controlled.

Experimental Status

Surface is experimental. The core shape is clear: Adaptive Cards only, explicit action routing, validation-first rendering, and Blazor integration through embedded surfaces and the command center. The API and command center workflows will continue to evolve as we test it against real applications.

The design goal is not to make agents into front-end developers. It is to give agents a reliable way to present work inside applications that still belong to humans and software teams. That distinction matters. Surface is where we are drawing that line.

Learn More

Surface is built on FabrCore, our open source .NET framework for distributed AI agents. Read the Surface solution page or explore the FabrCore documentation.

About Vulcan365 AI: We build and maintain FabrCore — an open source .NET framework for distributed AI agents. We also provide consulting and development services for teams building AI agent systems. Based in Birmingham, Alabama.