This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Note: This is the Umbraco.AI.Agent.UI package. See the root CLAUDE.md for shared coding standards, build commands, and repository-wide conventions that apply to all packages.
Umbraco.AI.Agent.UI is a reusable frontend library that provides shared chat UI infrastructure for AI agent interactions. It was extracted from Umbraco.AI.Agent.Copilot to enable multiple chat interfaces (copilot sidebar, workspace chat, custom integrations) to share common components and services.
- Chat Components - Reusable chat UI elements (message display, input, status indicators)
- Tool Renderer System - Framework for rendering tool execution results
- Frontend Tool Execution - Client-side tool execution infrastructure
- Approval System - HITL (Human-in-the-Loop) approval workflows
- Run Controller - Orchestrates agent runs with streaming responses
- Context Contracts - Standard context APIs for chat and entity integration
- Interrupt Handlers - Handles tool execution and HITL interrupts
- Localization - Base localization strings for chat UI
- No backend C# code
- No copilot-specific UI (sidebar, header button)
- No AG-UI transport layer (provided by consumers)
- No Umbraco Composer
This package is consumed by:
- Umbraco.AI.Agent.Copilot - Copilot sidebar UI
- Future packages - Workspace chat, custom chat integrations
# Build frontend assets (from repository root)
npm run build:agent-ui
# Watch frontend during development
npm run watch:agent-ui
# Build .NET solution (minimal - just static assets)
dotnet build Umbraco.AI.Agent.UI/Umbraco.AI.Agent.UI.slnxUmbraco.AI.Agent.UI/
├── src/
│ └── Umbraco.AI.Agent.UI/
│ ├── Client/
│ │ ├── src/
│ │ │ ├── chat/ # Main chat module
│ │ │ │ ├── components/ # Reusable UI components
│ │ │ │ │ ├── chat.element.ts # Main chat container
│ │ │ │ │ ├── input.element.ts # Chat input field
│ │ │ │ │ ├── message.element.ts # Message display
│ │ │ │ │ ├── tool-renderer.element.ts # Tool result renderer
│ │ │ │ │ ├── agent-status.element.ts # Agent status indicator
│ │ │ │ │ ├── approval-base.element.ts # Base approval element
│ │ │ │ │ ├── hitl-approval.element.ts # HITL approval UI
│ │ │ │ │ └── approval/ # Approval elements
│ │ │ │ ├── services/ # Core services
│ │ │ │ │ ├── run.controller.ts # Orchestrates agent runs
│ │ │ │ │ ├── tool-renderer.manager.ts # Manages tool renderers
│ │ │ │ │ ├── frontend-tool.manager.ts # Manages frontend tools
│ │ │ │ │ ├── frontend-tool.executor.ts # Executes frontend tools
│ │ │ │ │ ├── interrupt-handler.registry.ts # Registers handlers
│ │ │ │ │ ├── hitl.context.ts # HITL context
│ │ │ │ │ └── handlers/ # Interrupt handlers
│ │ │ │ ├── extensions/ # Extension types
│ │ │ │ │ ├── uai-agent-tool-renderer.extension.ts
│ │ │ │ │ ├── uai-agent-frontend-tool.extension.ts
│ │ │ │ │ └── uai-agent-approval-element.extension.ts
│ │ │ │ ├── context.ts # Chat context API
│ │ │ │ ├── entity-context.ts # Entity context API
│ │ │ │ ├── types/ # TypeScript types
│ │ │ │ └── utils/ # Utility functions
│ │ │ ├── lang/ # Localization
│ │ │ ├── manifests.ts # Extension manifests
│ │ │ ├── exports.ts # Public API exports
│ │ │ └── index.ts # Package entry point
│ │ ├── public/
│ │ │ └── umbraco-package.json # Umbraco package manifest
│ │ ├── package.json
│ │ ├── tsconfig.json
│ │ └── vite.config.ts
│ └── Umbraco.AI.Agent.UI.csproj
├── Directory.Build.props
├── Umbraco.AI.Agent.UI.slnx
├── changelog.config.json
├── version.json
├── README.md
└── CLAUDE.md
Two standard context APIs for integrating chat UI:
Core chat context required by all consumers:
export interface UaiChatContextApi extends UmbContextMinimal {
// Agent run management
startRun(request: AGUIRunRequestModel): Promise<void>;
stopRun(): void;
regenerateLastMessage(): void;
// State observables
messages$: Observable<AGUIMessageClientModel[]>;
isRunning$: Observable<boolean>;
agentStatus$: Observable<string>;
}Consumers MUST implement this context to use the chat components.
Optional entity context for entity-aware chat (e.g., chat about a specific content item):
export interface UaiEntityContextApi extends UmbContextMinimal {
// Entity information
entityType$: Observable<string>;
entityId$: Observable<string>;
entityData$: Observable<unknown>;
}Consumers can optionally implement this for entity-specific features.
Tool renderers display the results of tool executions:
// Register a tool renderer
const manifest: ManifestUaiAgentToolRenderer = {
type: "uaiAgentToolRenderer",
alias: "MyToolRenderer",
name: "My Tool Result Renderer",
forToolName: "my_tool", // Tool this renders
element: () => import("./my-tool-renderer.element.js"),
};Rendering Flow:
- Agent executes a tool (backend or frontend)
- Tool result is streamed to the UI
UaiToolRendererManagerfinds the matching renderer by tool name- Renderer displays the result in the chat
Frontend tools execute in the browser:
// Register a frontend tool
const manifest: ManifestUaiAgentFrontendTool = {
type: "uaiAgentFrontendTool",
alias: "MyFrontendTool",
name: "My Frontend Tool",
meta: {
toolName: "my_tool",
description: "Does something in the browser",
parameters: {
type: "object",
properties: {
input: { type: "string" },
},
},
},
api: () => import("./my-tool.api.js"), // Execution logic
};Execution Flow:
- Agent requests a frontend tool
UaiToolExecutionHandlerintercepts the requestUaiFrontendToolExecutorcalls the tool's API- Result is sent back to the agent
- Agent continues with the result
Human-in-the-loop approval for agent actions:
// Register an approval element
const manifest: ManifestUaiAgentApprovalElement = {
type: "uaiAgentApprovalElement",
alias: "MyApprovalElement",
name: "My Approval Handler",
forToolName: "my_tool", // Tool requiring approval
element: () => import("./my-approval.element.js"),
};Approval Flow:
- Agent requests a tool that requires approval
UaiHitlInterruptHandlerdetects HITL interrupt- Matching approval element is rendered
- User approves/rejects the action
- Result is sent back to the agent
UaiRunController orchestrates agent runs:
const controller = new UaiRunController(this, {
transport: myTransport, // AG-UI transport layer
frontendToolManager: toolManager, // Optional: for frontend tools
interruptHandlers: [ // Optional: custom handlers
new CustomInterruptHandler(),
],
});
// Start a run
await controller.start({
agent: { name: "my-agent" },
messages: [{ role: "user", content: "Hello" }],
});
// Observe state
controller.messages$.subscribe(messages => {
console.log("Messages:", messages);
});Features:
- Streams agent responses via AG-UI protocol
- Automatically registers
UaiToolExecutionHandleriffrontendToolManageris provided - Merges custom interrupt handlers with built-in handlers
- Manages run lifecycle (start, stop, regenerate)
- Provides reactive state via RxJS observables
{
"peerDependencies": {
"@umbraco-ai/agent": "^1.0.0",
"@umbraco-cms/backoffice": "^17.1.0"
},
"dependencies": {
"rxjs": "^7.8.2"
}
}Note: This package does NOT include @ag-ui/client - consumers must provide their own AG-UI transport implementation.
None - this is a frontend-only package. The .csproj is a Razor Class Library that only serves static assets.
// Import API client and types from agent package
import { AgentsService } from "@umbraco-ai/agent";
import type { AGUIRunRequestModel, AGUIMessageClientModel } from "@umbraco-ai/agent";// Import components
import { UaiChatElement } from "@umbraco-ai/agent-ui";
// Import services
import { UaiRunController, UaiFrontendToolManager } from "@umbraco-ai/agent-ui";
// Import types
import type { UaiChatContextApi, ManifestUaiAgentToolRenderer } from "@umbraco-ai/agent-ui";Frontend assets compile to:
/App_Plugins/UmbracoAIAgentUI/umbraco-ai-agent-ui.js
The import map in umbraco-package.json registers:
@umbraco-ai/agent-ui->/App_Plugins/UmbracoAIAgentUI/umbraco-ai-agent-ui.js
This package is frontend-only. Testing approaches:
- Manual testing - Test via consumer packages (Copilot)
- Unit tests - Use vitest for component/service unit tests (if added)
- Integration testing - Test with demo site that has consumer packages installed
┌─────────────────────────────────────────────────────┐
│ Umbraco.AI.Agent │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Core │ │ Persistence │ │ Web │ │
│ │ (Services) │ │ (Database) │ │ (APIs) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ┌──────────────────────────────────────────────────┤
│ │ Web.StaticAssets (Agent Management UI) │
│ │ - Agent workspace, collection, editing │
│ └──────────────────────────────────────────────────┤
└─────────────────────────────────────────────────────┘
│
│ depends on (npm)
▼
┌─────────────────────────────────────────────────────┐
│ Umbraco.AI.Agent.UI (Reusable) │
│ ┌──────────────────────────────────────────────────┤
│ │ Shared Chat Infrastructure │
│ │ - Components, services, contexts │
│ └──────────────────────────────────────────────────┤
└─────────────────────────────────────────────────────┘
│
│ depends on (npm + runtime)
▼
┌─────────────────────────────────────────────────────┐
│ Umbraco.AI.Agent.Copilot │
│ ┌──────────────────────────────────────────────────┤
│ │ Copilot-Specific UI │
│ │ - Sidebar, header button, AG-UI transport │
│ └──────────────────────────────────────────────────┤
└─────────────────────────────────────────────────────┘
To create a new package that uses Agent.UI:
-
Add npm dependency:
{ "peerDependencies": { "@umbraco-ai/agent-ui": "^1.0.0" } } -
Implement
UaiChatContextApi:export class MyCustomChatContext extends UmbContextBase<MyHost> implements UaiChatContextApi { // Implement required methods and observables }
-
Provide AG-UI transport:
import { UaiRunController } from "@umbraco-ai/agent-ui"; const controller = new UaiRunController(this, { transport: new MyCustomTransport(), });
-
Use chat components:
import { UaiChatElement } from "@umbraco-ai/agent-ui"; // In your template html`<uai-chat></uai-chat>`;
- Create renderer element extending
LitElement - Create manifest with
type: 'uaiAgentToolRenderer' - Set
forToolNameto match the tool - Register in your consumer's manifests.ts
- Create tool API class implementing the tool interface
- Create manifest with
type: 'uaiAgentFrontendTool' - Provide the tool to
UaiFrontendToolManagerinUaiRunController - Register in your consumer's manifests.ts
- Build agent-ui:
npm run build:agent-ui - Run demo site with a consumer package (e.g., Copilot)
- Open browser dev tools to see console logs
- Check Network tab for AG-UI streaming requests
- .NET 10.0 (
net10.0) - Uses Central Package Management (
Directory.Packages.props) - TypeScript 5.x
- Vite 7.x for bundling