DRYL COMPONENTS
Color mode: System — switch to light
3.16.0
Agents

AI Canvas

AI-aware

DrylAiCanvas lets the AI answer with a live, clickable artifact instead of prose — and clicking inside it continues the conversation.

How it works

create_artifact streams a curated DRYL component tree — KPI stats, charts, a region picker — that builds itself node by node into the canvas. Click a button inside the artifact and the interaction routes back through the chat as the next turn: update_artifact patches the canvas in place, inserting new nodes and retitling existing ones with a staggered FLIP glide.

You hand DrylCanvasTools.All to a real agent; each tool call runs its own JSON sub-generation on a tool-less generator agent, streaming the artifact into the canvas.

Where the innovation lies: the answer is an interface, not text — and interacting with it is a first-class conversational turn. The model builds UI, the user manipulates it, and the manipulation feeds the model's next response.

Every patch has exactly one movement. An inserted node enters, a moved node glides, a removed node exits — and a node whose content changed pulses an accent ring, so no update happens off-screen. Numbers in stat nodes count up to their new value, the header carries a live element count while the artifact streams, and replacing the whole artifact morphs the old tree into the new one instead of cutting. The expand button grows the canvas into a fullscreen overlay through the same view transition.

csharp
// The canvas tools get their own tool-less generator agent for the JSON sub-generation.
var tools = DrylCanvasTools.Create(_run, generatorAgent);
var agent = new ChatClientAgent(chatClient, tools: tools.All);
razor
<DrylAiCanvas Run="_run" OnInteraction="HandleInteraction" />

@* A click inside the artifact becomes the next user turn: *@
@* Ask(interaction.ToPromptMessage()) — the model answers with update_artifact. *@

Interactive canvas artifacts with DrylAiCanvas

The AI answers with a live, clickable artifact instead of prose. create_artifact streams a curated DRYL component tree — KPI stats, a line chart, a region picker — that builds itself node by node into DrylAiCanvas. Click a button inside the artifact and the interaction routes back through the chat as the next turn: update_artifact patches the canvas in place, inserting a bar chart and retitling the chart with a staggered FLIP glide. Fully scripted here — in your app you hand DrylCanvasTools.All to a real agent.

Artifact
Idle
No artifact yet
Ask the assistant to create one.

In your language

Every text the canvas shows or announces is a parameter with the English wording as its default: the empty state, the fallback title and the error title, the status pill, and the aria-live announcements a screen reader speaks while the artifact builds.

razor
<DrylAiCanvas Run="_run"
              EmptyTitle="Noch nichts gezeichnet"
              EmptyText="Bitte den Assistenten, etwas zu zeigen."
              FallbackTitle="Leinwand"
              IdleText="Bereit" WorkingText="Denkt nach"
              BuildingText="@(n => $"Baut · {n} Elemente")"
              ReadyText="@(n => "Fertig")"
              BuildingAnnouncement="Leinwand wird gebaut…"
              ReadyAnnouncement="Leinwand fertig."
              UpdatedAnnouncement="@(n => $"Leinwand aktualisiert, {n} Änderungen.")"
              FailedAnnouncement="Leinwand fehlgeschlagen." />

A canvas that opens on demand

If the canvas lives in a dialog or a side panel that opens only when the assistant starts drawing, the first generation would not know how wide it is. Open the surface in DrylCanvasTools.BeforeGenerate and wait for the canvas to measure itself with DrylCanvasRun.WaitForSurfaceAsync — no guessed delay, and a canvas that never mounts cannot hold the generation hostage.

csharp
var tools = DrylCanvasTools.Create(run, generator);
tools.BeforeGenerate = async ct =>
{
    await OpenCanvasDialogAsync();                                  // your surface
    await run.WaitForSurfaceAsync(TimeSpan.FromSeconds(1.5), ct);  // false = no surface; generate anyway
};
An unhandled error has occurred. Reload x

Reconnecting to the server…

Attempt /

Next try in s