NewHeap.Platform.AI.Chat.AspNet 10.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package NewHeap.Platform.AI.Chat.AspNet --version 10.0.0
                    
NuGet\Install-Package NewHeap.Platform.AI.Chat.AspNet -Version 10.0.0
                    
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="NewHeap.Platform.AI.Chat.AspNet" Version="10.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NewHeap.Platform.AI.Chat.AspNet" Version="10.0.0" />
                    
Directory.Packages.props
<PackageReference Include="NewHeap.Platform.AI.Chat.AspNet" />
                    
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 NewHeap.Platform.AI.Chat.AspNet --version 10.0.0
                    
#r "nuget: NewHeap.Platform.AI.Chat.AspNet, 10.0.0"
                    
#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 NewHeap.Platform.AI.Chat.AspNet@10.0.0
                    
#: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=NewHeap.Platform.AI.Chat.AspNet&version=10.0.0
                    
Install as a Cake Addin
#tool nuget:?package=NewHeap.Platform.AI.Chat.AspNet&version=10.0.0
                    
Install as a Cake Tool

NewHeap.Platform.AI.Chat.AspNet

ASP.NET Core assistant endpoints with server-sent event streaming and approval decisions for NewHeap AI.

Registration

Register the application's AI services and AddNewHeapPlatformAIAspNet first, then the assistant, and map the endpoints:

services.AddNewHeapPlatformAIAspNet(ai => ai.AddActiveDivisionScope("app.active-division.project.view"));
services.AddNewHeapAssistant(assistant => assistant
    .UsePostgreSql(connectionString, options => { options.Schema = "nhai"; options.RunMigrations = true; })
    .UseAccessPolicy("app.assistant.access")
    .UseChatProfile("project-assistant-chat")
    .UseAdminPolicy("app.assistant.admin")
    .UseDefaultApplicationContext(applicationContextAsset)
    .UseTimeZone("Europe/Amsterdam")
    .UseTurnContextProvider<ApplicationTurnContextProvider>()
    .ConfigureMcp(mcp => mcp.AllowedHosts.Add("planning.example.com"))
    .AddAgent(agent)
    .AddToolPresenter<ApplicationAssistantToolPresenter>()
    .AddBusinessAuditSink<ApplicationAssistantAuditSink>()
    .WithLimits(limits => limits.MaxToolCallsPerTurn = 8));

endpoints.MapNewHeapAssistant("/api/assistant");

Startup fails when the ASP.NET AI integration, the access or admin policy, an agent profile or policy is missing, or when the invocation gate or a durable manager was replaced after the assistant. AddNewHeapAssistant is idempotent. The assistant relies on the registered INhAiAuthenticatedInvocationContextResolver; a replaced resolver is used as is, and no tenant claim is required.

INhAssistantToolPresenter is optional. Use it for application-localized names and approval explanations sourced from authorized server-side data. Presentation is persisted beside, but never substituted for, the exact proposal evidence. The API returns it as optional approval.presentation; clients must support null for old approvals and tools without a presenter.

Configuration

Key Default Meaning
NewHeap:AI:Assistant:Enabled false Kill switch. Off: GET status returns { enabled: false, agents: [] }, all other endpoints 404.
NewHeap:AI:Assistant:AccessPolicy app.assistant.access Policy every endpoint requires, unless UseAccessPolicy sets one.
NewHeap:AI:Assistant:AdminPolicy app.assistant.admin Additional policy for admin/*, unless UseAdminPolicy sets one.
NewHeap:AI:Assistant:Mcp:RequireHttps true MCP servers must use https; plain http is allowed only to loopback in Development.
NewHeap:AI:Assistant:Mcp:AllowedHosts empty (any public host) Optional allow-list of MCP hosts. Link-local and metadata addresses are always blocked.
NewHeap:AI:Assistant:Mcp:ForwardUserTokenHosts empty Exact hosts that may receive the caller's token (forward-user-token).
NewHeap:AI:Assistant:Mcp:ToolListCacheDuration 00:05:00 Cache duration of remote tool lists.
NewHeap:AI:Assistant:Mcp:ConnectTimeout 00:00:10 Connect timeout for MCP servers.

Endpoints

Method and path Response
GET status AssistantStatus
GET agents agents whose required policy the caller satisfies
GET conversations?page=&itemsPerPage= { items, total }
POST conversations { agentId, title? } 201 conversation
GET conversations/{id} conversation with messages and pending approval; for an agent thread also kind: "thread" and thread with the subject, the caller's role and who may decide each open proposal
DELETE conversations/{id} 204; the conversation is archived and hidden
POST conversations/{id}/messages { text, clientMessageId, clientContext? } text/event-stream; 409 when the conversation is not idle
POST conversations/{id}/approvals/{approvalId}/decide { decision, expectedProposalHash, reason? } text/event-stream of the resumed turn
POST conversations/{id}/cancel 202
GET / PUT preferences the caller's style preferences

Administration endpoints additionally require the admin policy:

Method and path Response
GET / PUT context, GET context/versions application context; PUT takes expectedVersion
GET tools local and bridge tools that selectors can match
GET / POST agents, PUT / DELETE agents/{id}, POST agents/{id}/reset code and admin agents; updates take expectedVersion, code agents are reset instead of deleted
GET / POST mcp-servers, PUT / DELETE mcp-servers/{id} MCP servers; secrets are write-only (hasSecret)
POST mcp-servers/{id}/test, POST mcp-servers/{id}/sync connection test and tool sync; sync returns 502 when the server is unreachable or rejects the credentials
GET mcp-servers/{id}/tools, PUT mcp-servers/{id}/tools/{remoteName} synced tools; activate them and set their effect

Agent threads and runs (see ConfigureAgent, AddSubjectType and AddTrigger) add these endpoints. Access follows the caller's role on the subject, which the subject's INhAiSubjectAccessResolver decides on every request; people without a role receive 404.

Method and path Response
GET threads?agentId=&subjectType=&subjectId= the agent's thread about the subject, the caller's role and whether the caller may start the agent
POST threads/start { agentId, subjectType, subjectId, message? } 202 trigger receipt; needs the participant role
GET threads/{id}/runs runs, newest first, with status, failure class, usage and proposal count
GET threads/{id}/consultations?page=&itemsPerPage= who consulted the agent through which assistant, newest first, with outcome, usage and proposal count; never the question or the answer
GET threads/{id}/proposals proposals with their decision and execution state and the application's presentation
GET threads/{id}/memory the thread's working memory, its schema version and last change
GET threads/{id}/artifacts the files the agent's tools saved, with name, version, size and restricted
GET threads/{id}/artifacts/{artifactId}/content the file's content; 404 when it is restricted for the caller
POST runs/{runId}/cancel 202; needs the participant role
POST runs/{runId}/retry { mode: resume or restart } 202 trigger receipt; needs the approver role
GET approvals/inbox?subjectType=&agentId=&divisionId=&runId=&page=&itemsPerPage= pending proposals the caller may decide, by expiry
POST approvals/{id}/decisions { decision, expectedProposalHash?, reason? } the decided proposal; 403 with assistant-four-eyes-required or assistant-approval-policy-denied
POST approvals/decisions { approvalIds, decision, reason? } one outcome per proposal
POST approvals/{id}/resolve { action: re-execute or mark-resolved, reason? } the proposal after a person resolved an execution with an unknown outcome
PUT approvals/{id}/feedback { category, text? } the caller's feedback on a rejected, expired, withdrawn or stale proposal; 403 for people who neither decided it nor approve on the subject, 409 with assistant-feedback-not-accepted for a pending or approved proposal
POST approvals/feedback { approvalIds, category, text? } one outcome per proposal; the records are marked as bulk feedback
GET subjects/{type}/{id}/work?agentId= the caller's role, every agent with a thread on the subject (and the requested agent) and their open proposals with the caller's live decision right
POST subjects/{type}/summary { subjectIds } per subject (at most 200): open proposals, proposals the caller may decide and whether a run is active, in one query
POST threads/open { agentId, subjectType, subjectId } the agent's thread about the subject, created without a run; creating needs the participant role

POST triggers/{triggerId} fires a webhook trigger without a user. Sign {timestamp}.{deliveryId}.{body} with HMAC-SHA256 and the trigger's secret and send X-NH-Timestamp (Unix seconds), X-NH-Delivery and X-NH-Signature (sha256= plus the lowercase hex digest). It returns 202 with a receipt, 401 with assistant-webhook-signature-invalid for a missing, stale or wrong signature, 400 when the body names no subject and 413 above 64 KB. Administrators stop or resume an agent with POST admin/agents/{id}/kill-switch { engaged }.

Administrators review why people reject an agent's proposals. For proposals made in a period (from, to; the last 30 days by default, at most 366 days), GET admin/agents/{id}/feedback/summary counts approved, rejected, expired and withdrawn proposals per tool and agent version, with the rejection rate, the feedback categories and the number of different people who gave feedback. GET admin/agents/{id}/feedback lists the feedback with the proposal's presentation, filtered by scopeKey, toolId, category and agentVersion, and GET admin/agents/{id}/feedback/export streams it as JSON Lines with each proposal's tool input (limit, at most 50,000). The export holds subject data and is audited as AdminAgentFeedbackExported.

The generated consultation tools of every AllowConsultation registration are an attested tool catalog of this package. They run through the shared invoker with the asking person's rights and return the shared NhAiToolResult shape to the model, { success, data } or { success: false, code, message }, with codes such as assistant-consult-subject-unavailable. The startup validator checks that each consulted subject type has a resolver and each consultation policy exists. An INhAiToolDiscoveryPolicy that allows tool prefixes must allow assistant.consult. and assistant.request..

A message to a thread while a run is active returns 202 with a receipt; the next run receives it. Turns that a person types in a thread are bound to the request like chat turns and their approvals are inline.

GET conversations/{id} of a thread returns kind: "thread" and thread (NhAssistantConversationThreadDto): the subject, the caller's live role and, per open proposal (NhAssistantThreadDecisionDto), its runId, canDecide and a reasonCode such as assistant-four-eyes-required, checked like the decision itself. Clients decide a proposal with a run, and a deferred proposal of a consultation (consultationId), through POST approvals/{id}/decisions; an inline proposal without a run belongs to a person's turn and resumes it through POST conversations/{id}/approvals/{approvalId}/decide. User messages carry authorKind: person, or trigger for text a trigger wrote into the thread.

The live hub requires the assistant access policy like the endpoints. Browsers send no custom headers with WebSockets and server-sent events, so a policy that needs the active division reads it from the divisionId query value: the NewHeap JWT handler copies it to X-NH-ActiveDivisionId on /hub paths. The Angular client sends it through NhAssistantConfig.getHubQueryParameters.

For agent threads the hub also sends AgentWorkChanged (NhAssistantLiveAgentWorkDto): a run, a proposal or its feedback changed. It goes to the thread's participants and to everyone in the subject's member snapshot, carries only identifiers and a reason (run, proposal or feedback), and lets clients reload the agent-run endpoints they show. Proposals are presented in every supported UI culture of RequestLocalizationOptions; each endpoint returns the presentation of the request's culture.

An application's own back-end reads the same agent work through INhAssistantSubjectWork: GetAsync (one subject) and SummarizeAsync (badges for a list) take the caller's actor id and principal, and GetForRequestAsync and SummarizeForRequestAsync resolve both from the current request. They apply the endpoints' access checks, so a project endpoint can include the project's suggestions without calling the assistant over HTTP.

Every error of preferences and admin/* has the body { code, messageKey, errors? }. Validation errors return 400 with code assistant-validation and errors keyed by camelCase field name (values required, invalid, too-long, not-found); blocked hosts return 400 with assistant-mcp-host-blocked. A caller without the admin policy receives 403 with assistant-forbidden, unknown objects 404 with a specific *-not-found code and stale versions 409. MCP secrets are protected with ASP.NET Data Protection; persist the key ring across restarts and nodes.

clientContext is { route, title?, entities?: [{ type, id, label? }] } (route 200, title 120, five entities, dash-case type, id 64, label 120 characters). The server cuts off long text and ignores a value of the wrong shape instead of answering 400.

JSON is camelCase through one source-generated NhAssistantJsonSerializerContext. Errors outside the stream use { code, messageKey } with messageKey = nh-assistant.errors.<code>. Conversations are visible to their owner only; other callers receive 404.

Streaming

Each event is written as event: <name>, data: <json> and an empty line: turn.started, message.delta, tool.started, tool.completed, approval.required, turn.completed or error. A : keep-alive comment follows every 15 seconds without events, and the stream closes after turn.completed or error. Response buffering is disabled and X-Accel-Buffering: no is set for reverse proxies. A client disconnect cancels the turn and releases the conversation. Browser clients use fetch streaming, because EventSource cannot send an Authorization header.

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
11.0.2 0 10/15/2026
11.0.1 0 10/15/2026
11.0.0 0 10/15/2026
10.1.0 29 10/14/2026
10.0.1 33 10/14/2026
10.0.0 39 10/14/2026
9.0.0 80 10/10/2026
8.1.0 84 10/7/2026
8.0.0 718 10/2/2026
7.14.2 83 10/1/2026
7.14.1 92 9/30/2026
7.14.0 342 9/29/2026
7.13.1 185 9/28/2026
7.13.0 110 9/27/2026
7.12.0 138 9/25/2026
7.11.0 129 9/25/2026
7.10.0 104 9/25/2026
7.9.0 117 9/24/2026
7.8.2 115 9/24/2026
7.8.1 99 9/24/2026
Loading failed