Incursa.OpenAI.ChatKit.AspNetCore 3.0.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package Incursa.OpenAI.ChatKit.AspNetCore --version 3.0.2
                    
NuGet\Install-Package Incursa.OpenAI.ChatKit.AspNetCore -Version 3.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Incursa.OpenAI.ChatKit.AspNetCore" Version="3.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Incursa.OpenAI.ChatKit.AspNetCore" Version="3.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Incursa.OpenAI.ChatKit.AspNetCore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Incursa.OpenAI.ChatKit.AspNetCore --version 3.0.2
                    
#r "nuget: Incursa.OpenAI.ChatKit.AspNetCore, 3.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Incursa.OpenAI.ChatKit.AspNetCore@3.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Incursa.OpenAI.ChatKit.AspNetCore&version=3.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Incursa.OpenAI.ChatKit.AspNetCore&version=3.0.2
                    
Install as a Cake Tool

Incursa.OpenAI.ChatKit.AspNetCore

Incursa.OpenAI.ChatKit.AspNetCore is the ASP.NET Core integration package for Incursa.OpenAI.ChatKit.

It adds:

  • MapChatKit<TServer, TContext>(...) for HTTP and SSE endpoint handling
  • AddOpenAIChatKitApi(...) and AddOpenAIChatKitHosted(...) for explicit frontend hosting modes
  • Razor tag helpers for mounting the ChatKit frontend from MVC or Razor views
  • packaged CSS and JavaScript assets under _content/Incursa.OpenAI.ChatKit.AspNetCore/chatkit
  • a thin vanilla-JS bootstrap around the upstream <openai-chatkit> web component
  • options for shared UI defaults across a site or application

Install

Use this package together with the core runtime package:

dotnet add package Incursa.OpenAI.ChatKit
dotnet add package Incursa.OpenAI.ChatKit.AspNetCore

What this package is for

  • exposing a ChatKit-compatible endpoint from ASP.NET Core
  • rendering the ChatKit frontend from Razor layouts, pages, or views
  • shipping a repo-managed browser runtime without hand-written page bootstrapping

What this package is not for

  • replacing the core Incursa.OpenAI.ChatKit runtime
  • generating ChatKit UI assets during normal dotnet build
  • forcing a specific MVC or Razor Pages structure on your app

Endpoint mapping

Register your server and map the ChatKit endpoint:

using Incursa.OpenAI.ChatKit;
using Incursa.OpenAI.ChatKit.AspNetCore;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<DemoChatKitServer>();

WebApplication app = builder.Build();
app.MapChatKit<DemoChatKitServer, Dictionary<string, object?>>(
    "/chatkit",
    _ => new Dictionary<string, object?>());

app.Run();

Razor UI wrapper

Register shared UI defaults for a custom ChatKit API endpoint:

builder.Services.AddOpenAIChatKitApi("/api/chatkit", "contoso-domain-key", configure: options =>
{
    options.DefaultHeight = "760px";
    options.StartScreen.Greeting = "How can I help today?";
    options.Theme.ColorScheme = "dark";
    options.Theme.Typography.BaseSize = 16;
    options.Theme.Color.Accent.Primary = "#8B5CF6";
    options.Header.LeftAction = new ChatKitHeaderActionOptions
    {
        Icon = "sidebar-left",
        OnClickHandler = "window.chatkit.onHeaderAction",
    };
    options.Disclaimer.Text = "AI may make mistakes. Verify important details.";
    options.Disclaimer.HighContrast = true;
    options.EntityHandlers = "window.chatkitEntities";
    options.Entities.ShowComposerMenu = true;
});

Then use the tag helpers from a layout or view:

@addTagHelper *, Incursa.OpenAI.ChatKit.AspNetCore

<incursa-chatkit-assets />

<incursa-chatkit-api
    id="workspace-assistant"
    class="chatkit-page"
    api-url="/api/chatkit"
    domain-key="contoso-domain-key"
    theme-base-size="16"
    theme-color-accent-primary="#8B5CF6"
    header-left-action-icon="sidebar-left"
    header-left-action-handler="window.chatkit.onHeaderAction"
    disclaimer-text="AI may make mistakes. Verify important details."
    disclaimer-high-contrast="true">
</incursa-chatkit-api>

Use <incursa-chatkit-api> when your application maps a custom ChatKit endpoint with MapChatKit(...). This is the explicit wrapper for self-hosted or custom API integrations.

For example, if your app maps a protected ChatKit endpoint at /api/chatkit, keep that route on the server side:

app.MapChatKit<MyChatKitServer, MyChatKitContext>(
    "/api/chatkit",
    MyChatKitContext.FromHttpContext)
    .RequireAuthorization();

Then point the Razor host at that API endpoint:

<incursa-chatkit-api
    api-url="/api/chatkit"
    domain-key="contoso-domain-key" />

Direct API mode requires a domain key. Configure it either in AddOpenAIChatKitApi(...) or on the <incursa-chatkit-api> tag helper.

The wrapper also mirrors the richer upstream theme and header options:

  • theme-base-size, theme-font-family, and theme-font-family-mono
  • theme-color-grayscale-*, theme-color-accent-*, and theme-color-surface-*
  • header-left-action-* and header-right-action-* for callback-backed header buttons

For start-screen prompts, the wrapper accepts either plain text or rich UserMessageContent[] values through the .NET options model.

Client tool handlers

To expose ChatKit onClientTool through the Razor wrapper, register a browser-side object whose keys match your server-side ClientToolCall.name values, then point the tag helper at that object:

<script>
  window.chatkitClientTools = {
    async get_selected_canvas_nodes({ name, params }) {
      const nodes = myCanvas.getSelectedNodes(params.project);
      return {
        nodes: nodes.map((node) => ({ id: node.id, kind: node.type }))
      };
    }
  };
</script>
<incursa-chatkit-assets />
<incursa-chatkit-api
    api-url="/api/chatkit"
    domain-key="contoso-domain-key"
    client-tool-handlers="window.chatkitClientTools">
</incursa-chatkit-api>

client-tool-handlers accepts a dotted browser lookup path such as window.chatkitClientTools or app.chatkit.clientTools. Each resolved handler receives the upstream ChatKit tool-call object { name, params } and must return JSON-compatible data. If the lookup path or named tool handler is missing, the packaged runtime throws a clear browser error instead of silently ignoring the tool call.

Composer configuration

The wrapper can also project ChatKit composer attachments, tool pickers, model pickers, dictation, and custom upload strategies from AddOpenAIChatKitApi(...) or AddOpenAIChatKitHosted(...):

builder.Services.AddOpenAIChatKitApi("/api/chatkit", "contoso-domain-key", options =>
{
    options.Composer.Attachments.Enabled = true;
    options.Composer.Attachments.MaxCount = 10;
    options.Composer.Attachments.MaxSize = 100 * 1024 * 1024;
    options.Composer.Tools.Add(new ChatKitComposerTool
    {
        Id = "summarize",
        Label = "Summarize",
        Icon = "book-open",
    });
    options.Composer.Models.Add(new ChatKitComposerModel
    {
        Id = "gpt-4.1",
        Label = "Quality",
        Description = "Higher-quality responses",
        Default = true,
    });
    options.Composer.Dictation.Enabled = true;
    options.UploadStrategy.Type = "direct";
    options.UploadStrategy.UploadUrl = "/files";
});
<incursa-chatkit-api
    api-url="/api/chatkit"
    domain-key="contoso-domain-key"
    composer-attachments-enabled="true"
    composer-attachments-max-count="10"
    composer-dictation-enabled="true"
    upload-strategy-type="direct"
    upload-strategy-upload-url="/files">
</incursa-chatkit-api>

composer.attachments is omitted unless attachments are configured. When enabled, the runtime forwards the attachment limits and accepted file type map into useChatKit(...). composer.tools, composer.models, and composer.dictation are serialized from the .NET options model without any browser-side patching.

Entity handlers

To expose ChatKit entities through the Razor wrapper, register a browser-side object with the upstream callback names and point the tag helper at that registry:

<script>
  window.chatkitEntities = {
    async onTagSearch(query) {
      return searchDocuments(query).map((document) => ({
        id: document.id,
        title: document.title,
        group: "Documents",
        icon: "document",
        interactive: true,
        data: {
          source: "document"
        }
      }));
    },
    onClick(entity) {
      openDocument(entity.id);
    },
    async onRequestPreview(entity) {
      return {
        preview: buildEntityPreview(entity)
      };
    }
  };
</script>
<incursa-chatkit-assets />
<incursa-chatkit-api
    api-url="/api/chatkit"
    domain-key="contoso-domain-key"
    entity-handlers="window.chatkitEntities"
    entity-show-composer-menu="true">
</incursa-chatkit-api>

entity-handlers accepts a dotted browser lookup path such as window.chatkitEntities or app.chatkit.entityHandlers. The runtime looks for optional onTagSearch(query), onClick(entity), and onRequestPreview(entity) functions on that object and validates the returned entity list and preview payload shape before passing them to ChatKit.

When the user submits tagged content, the core server receives UserMessageTagContent entries alongside regular text content. That lets you convert upstream @ tags directly into your server-side domain model:

using System.Text.Json.Nodes;
using Incursa.OpenAI.ChatKit;

IReadOnlyList<UserMessageTagContent> tags = input.Content
    .OfType<UserMessageTagContent>()
    .ToList();

foreach (UserMessageTagContent tag in tags)
{
    string? source = tag.Data.TryGetValue("source", out JsonNode? value)
        ? value?.GetValue<string>()
        : null;

    // Map the submitted entity tag into your own search, retrieval, or routing flow.
}

Header title

The header title area can be disabled independently from the header itself:

builder.Services.AddOpenAIChatKitHosted(options =>
{
    options.Header.Enabled = true;
    options.Header.TitleEnabled = false;
    options.Header.TitleText = "Assistant";
});
<incursa-chatkit-hosted
    session-endpoint="/api/chatkit/session"
    action-endpoint="/api/chatkit/action"
    header-title-enabled="false"
    header-title="Assistant">
</incursa-chatkit-hosted>

Use header-title-enabled="false" when you want the header shell to remain visible but the title slot to be hidden.

OpenAI-hosted mode

If the frontend should use OpenAI-hosted ChatKit through local session and action endpoints, register hosted mode explicitly and use <incursa-chatkit-hosted>:

builder.Services.AddOpenAIChatKitHosted(options =>
{
    options.SessionEndpoint = "/api/chatkit/session";
    options.ActionEndpoint = "/api/chatkit/action";
});
<incursa-chatkit-assets />
<incursa-chatkit-hosted
    session-endpoint="/api/chatkit/session"
    action-endpoint="/api/chatkit/action">
</incursa-chatkit-hosted>

<incursa-chatkit-hosted> is the explicit wrapper for the hosted getClientSecret flow. Use it when your app issues the browser a ChatKit client secret instead of exposing a custom ChatKit API endpoint directly.

Widget actions

To expose upstream widgets.onAction through the Razor wrapper, register a browser-side function and point the tag helper at that lookup path:

<script>
  window.chatkitOnWidgetAction = async (action, widgetItem) => {
    if (action.type !== "save_profile") {
      return;
    }

    await saveProfile(action.payload, widgetItem.id);
  };
</script>
<incursa-chatkit-assets />
<incursa-chatkit-hosted
    session-endpoint="/api/chatkit/session"
    widget-action-handler="window.chatkitOnWidgetAction"
    forward-widget-actions="false">
</incursa-chatkit-hosted>

widget-action-handler accepts a dotted browser lookup path such as window.chatkitOnWidgetAction or app.chatkit.widgets.onAction. The runtime resolves that function each time a widget action fires and passes the upstream (action, widgetItem) arguments unchanged.

Supported patterns:

  • Server-only: omit widget-action-handler and keep widget forwarding enabled so actions post to action-endpoint.
  • Client-only: set widget-action-handler and disable forwarding with forward-widget-actions="false".
  • Client-then-server: set both widget-action-handler and action-endpoint. The runtime invokes the client callback first and forwards the same action to the endpoint only if the client callback succeeds.

In direct API mode (<incursa-chatkit-api>), widget-action-handler still works for client-handled widget actions. Local action-endpoint forwarding remains unavailable in that mode.

Updating packaged UI assets

Source vs generated files

The JavaScript pieces in this package fall into two buckets:

  • Handwritten source:
    • ClientApp/chatkit-runtime/src/entry.js
    • ClientApp/chatkit-runtime/src/runtimeHost.js
    • ClientApp/chatkit-runtime/src/clientToolHandlers.js
    • ClientApp/chatkit-runtime/src/entityHandlers.js
    • ClientApp/chatkit-runtime/src/widgetActionHandlers.js
    • ClientApp/chatkit-runtime/src/runtime.css
  • Generated bundle:
    • wwwroot/chatkit/chatkit.js
    • wwwroot/chatkit/chatkit.css

The browser startup flow is:

  1. <incursa-chatkit-assets /> renders the upstream CDN script and the local module bundle.
  2. The CDN script defines the upstream <openai-chatkit> custom element.
  3. The local bundle finds each data-incursa-chatkit-host element rendered by the Razor tag helper.
  4. The local bundle parses data-incursa-chatkit-config, creates <openai-chatkit>, and calls setOptions(...).
  5. Optional browser callback registries such as client-tool-handlers, entity-handlers, and widget-action-handler are resolved from dotted lookup paths like window.chatkit.clientTools.

This package intentionally carries both:

  • editable frontend source in ClientApp/chatkit-runtime
  • generated package assets in wwwroot/chatkit

When the packaged ChatKit bootstrap or related npm dependencies need to move forward:

cd src/Incursa.OpenAI.ChatKit.AspNetCore/ClientApp/chatkit-runtime
npm install
npm run build

<incursa-chatkit-assets /> renders both the upstream ChatKit CDN script that defines <openai-chatkit> and the local package bootstrap that applies your serialized Razor config with setOptions(...).

Commit both the dependency file changes and the regenerated files under wwwroot/chatkit.

  • Incursa.OpenAI.ChatKit: core ChatKit models, routing, stores, and server runtime
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.5 111 3/24/2026
3.0.3 84 3/20/2026
3.0.2 88 3/20/2026
3.0.1 86 3/19/2026
3.0.0 94 3/19/2026
2.0.1 86 3/19/2026
2.0.0 84 3/19/2026
1.0.16 86 3/19/2026
1.0.15 92 3/18/2026
1.0.14 80 3/18/2026
1.0.13 85 3/18/2026