SharpOMatic.AGUI
10.0.5
See the version list below for details.
dotnet add package SharpOMatic.AGUI --version 10.0.5
NuGet\Install-Package SharpOMatic.AGUI -Version 10.0.5
<PackageReference Include="SharpOMatic.AGUI" Version="10.0.5" />
<PackageVersion Include="SharpOMatic.AGUI" Version="10.0.5" />
<PackageReference Include="SharpOMatic.AGUI" />
paket add SharpOMatic.AGUI --version 10.0.5
#r "nuget: SharpOMatic.AGUI, 10.0.5"
#:package SharpOMatic.AGUI@10.0.5
#addin nuget:?package=SharpOMatic.AGUI&version=10.0.5
#tool nuget:?package=SharpOMatic.AGUI&version=10.0.5
SharpOMatic.AGUI
Optional SharpOMatic extension that exposes an AG-UI compatible endpoint for running SharpOMatic workflows over SSE. It supports both stateless workflow runs and conversation-enabled workflows.
Usage
Register the package in your ASP.NET Core host:
builder.Services.AddSharpOMaticAgUi();
That defaults to /sharpomatic/api/agui.
In the DemoServer that is exposed as https://localhost:9001/sharpomatic/api/agui.
Choose a different base path if needed:
builder.Services.AddSharpOMaticAgUi("/banana");
Or override both the base path and the AG-UI child path:
builder.Services.AddSharpOMaticAgUi("/banana", "/integrations/chat");
The package adds the live POST endpoint on the combined path and a history POST endpoint at the same path plus /history.
Request requirements
For POST run requests:
threadIdis required.forwardedPropsmust contain exactly one ofworkflowIdorworkflowName.workflowNamemust match exactly one workflow.
The endpoint resolves the matching SharpOMatic workflow, chooses the correct execution mode, and streams SSE events translated from workflow stream events until the run completes, suspends, or fails.
Request context enrichment
Hosts can inspect each incoming AG-UI run request before the workflow starts by registering IAgUiNotification.
This is the recommended place to read headers such as Authorization, validate a bearer token, and add derived user or permission data into workflow context.
public sealed class MyAgUiNotification : IAgUiNotification
{
public Task OnRunStartingAsync(AgUiRunContextNotification notification)
{
var authorization = notification.Headers.TryGetValue("Authorization", out var values)
? values.FirstOrDefault()
: null;
// Validate the token with your application's auth service, then store derived values only.
notification.Context.Set("auth.userName", "Ada");
notification.Context.Set("auth.permissions", new[] { "workflow:run" });
notification.Agent.Set("auth.userName", "Ada");
return Task.CompletedTask;
}
}
builder.Services.AddScoped<IAgUiNotification, MyAgUiNotification>();
AgUiRunContextNotification provides the original AgUiRunRequest, a case-insensitive header snapshot, normalized ThreadId, resolved WorkflowId, whether the workflow is conversation-enabled, a mutable root context, and the mutable agent context.
For conversation-enabled workflows, root context values are merged into the loaded conversation context and agent is replaced for the current turn.
For non-conversation workflows, the same root context is passed directly to the workflow run.
Avoid writing raw bearer tokens or other secrets into workflow context because context is stored with run and conversation history. Prefer storing derived claims such as user id, display name, tenant, roles, or permissions.
Conversation history
Use POST <ag-ui-path>/history to reload persisted AG-UI messages, state, and resumable frontend tool metadata for a conversation-enabled workflow:
{
"threadId": "support-chat-001",
"workflowId": "11230021-5144-471a-8ec7-9b460354b745"
}
or:
{
"threadId": "support-chat-001",
"workflowName": "Support Chat"
}
The response body is a history envelope:
{
"messages": [],
"state": null,
"pendingFrontendTools": []
}
messages is an AG-UI Message[] that can be supplied to an AG-UI client as initial messages.
state is restored from the saved conversation checkpoint when available, otherwise from visible state stream events.
pendingFrontendTools contains at most the last unresolved SharpOMatic frontend tool call when the final restored assistant message is that tool call.
threadIdis required and maps to the SharpOMatic conversation id.- Specify exactly one of
workflowIdorworkflowName. - Unknown workflow id, unknown workflow name, unknown thread id, and workflow/thread mismatches return
404. - Malformed selectors, invalid GUIDs, and ambiguous workflow names return
400. - Non-conversation workflows return
{ "messages": [], "state": null, "pendingFrontendTools": [] }because they do not have conversation stream history.
The history reducer uses the same protocol id conventions as live SSE output for reasoning, tool result, and activity messages.
Step and custom stream events are not returned because AG-UI initialMessages accepts messages, not protocol events.
SSE event mapping
SharpOMatic translates workflow stream events into AG-UI SSE events:
TEXT_MESSAGE_START,TEXT_MESSAGE_CONTENT,TEXT_MESSAGE_ENDSTEP_STARTED,STEP_FINISHEDSTATE_SNAPSHOT,STATE_DELTAREASONING_START,REASONING_MESSAGE_START,REASONING_MESSAGE_CONTENT,REASONING_MESSAGE_END,REASONING_ENDTOOL_CALL_START,TOOL_CALL_ARGS,TOOL_CALL_END,TOOL_CALL_RESULTACTIVITY_SNAPSHOT,ACTIVITY_DELTARUN_STARTED,RUN_FINISHED,RUN_ERROR
TOOL_CALL_RESULT preserves both the result messageId and the linked toolCallId.
TOOL_CALL_START includes the tool name and can include parentMessageId when the model output supplies it.
Reasoning events use AG-UI-specific messageId values prefixed with reason: so they do not collide with assistant text messages when a model/provider reuses one response id for both.
Tool result messages use AG-UI-specific messageId values prefixed with tool: so tool messages stay distinct too, while the linked toolCallId remains unchanged.
Activity messages use AG-UI-specific messageId values prefixed with activity: so activity updates stay distinct from assistant, reasoning, and tool messages.
When batch-mode model calls are replayed without provider message ids, SharpOMatic synthesizes separate assistant messageId values for each distinct assistant text lifecycle and seeds them from the stream sequence so they remain unique across conversation turns.
Code-node stream-event helpers can mark events as silent, which keeps them in SharpOMatic stream history while suppressing their live AG-UI SSE emission.
Workflow selection
The recommended request shape is:
{
"threadId": "support-chat-001",
"messages": [],
"state": {},
"context": [],
"forwardedProps": {
"sharpomatic": {
"workflowId": "11230021-5144-471a-8ec7-9b460354b745"
}
}
}
workflowName can be used instead of workflowId:
{
"threadId": "support-chat-001",
"forwardedProps": {
"sharpomatic": {
"workflowName": "Support Chat"
}
}
}
For compatibility, the selector can also live directly under forwardedProps, but forwardedProps.sharpomatic is the preferred convention.
Execution modes
SharpOMatic resolves the target workflow first:
- non-conversation workflows are treated as stateless AG-UI targets
- conversation-enabled workflows use normal SharpOMatic conversation storage
For non-conversation workflows:
- the client must send the full AG-UI message history on every call
- SharpOMatic rebuilds
agent.chatfrom that history for the current run, except for the latest user text message exposed asagent.latestUserMessage threadIdremains protocol metadata only
For conversation-enabled workflows:
- the first call uses
threadIdas the SharpOMaticconversationId - later calls with the same
threadIdcontinue or resume that conversation - later AG-UI calls must be incremental only and send only the new message
- the controller exposes only the latest incoming AG-UI message at
agent.messagesand does not append it intoinput.chat
Workflow context
The controller maps selected request data into workflow context under agent:
agent.latestUserMessage: the final item inmessages, but only when that item is a user text messageagent.latestToolResult: the final item inmessages, but only when that item is a tool result message. Itscontentstays as the original string, and if that string is non-empty JSON then SharpOMatic also stores the parsed payload inagent.latestToolResult.value.agent.messages: for non-conversation workflows, the full incoming AG-UImessagesarray; for conversation-enabled workflows, only the latest incoming messageagent.chat: for non-conversation workflows, provider-neutralChatMessagehistory rebuilt from the incomingmessagesarray for the current runagent.state: the incoming AG-UIstatevalueagent.context: the incoming AG-UIcontextvalueagent._hidden.state: a hidden deep copy of the incoming AG-UIstate, used as the baseline forAddStateSyncAsync()and theState Syncnode
These values are passed through as structured JSON-compatible data, not as a single raw JSON string.
On each AG-UI start or resume, SharpOMatic updates the agent object.
If the workflow context already contains agent, the incoming AG-UI agent object replaces it entirely.
For non-conversation workflows, the controller converts supported AG-UI messages into provider-neutral ChatMessage entries at agent.chat for the current run.
For conversation workflows, input.chat is canonical model history owned by workflow nodes.
Use it as the recommended source for ModelCall.ChatInputPath, and set ModelCall.ChatOutputPath to input.chat when model responses should be replayed across turns.
The components that can create or change chat history are:
- the AG-UI controller, only for non-conversation workflows, from the incoming
messagesarray intoagent.chat - the Model Call node, when Chat Output Path is set, usually to
input.chat - the Frontend Tool Call node, only when Chat Persistence is not
None - the Backend Tool Call node, only when Chat Persistence is not
None
The AG-UI controller does not append incoming user text or frontend tool results to conversation input.chat.
Incoming user text is stored as silent stream history for conversation turns, but it is not a ChatMessage.
Frontend tool results are persisted by the Frontend Tool Call node according to its chat persistence setting, which defaults to None for new frontend tool-call nodes.
Supported agent.chat conversion in this version:
system→ChatRole.Systemdeveloper→ChatRole.Systemuser→ChatRole.User, except the latest user text message when it is exposed asagent.latestUserMessageassistanttext and tool calls →ChatRole.Assistanttoolresults →ChatRole.Tool
AG-UI reasoning and activity messages are ignored for chat conversion in this version.
Unsupported multimodal or non-string message content is rejected with RUN_ERROR.
SharpOMatic also includes protocol-aware workflow nodes for common AG-UI patterns:
- Frontend Tool Call for frontend-driven tool results that suspend and later resume the workflow
- Backend Tool Call for tool-call rendering when the workflow already knows the result
- Activity Sync and State Sync for structured activity or state updates
- Step Start and Step End for simple progress markers
Use the dedicated node and AG-UI docs for the detailed behavior of each node.
Frontend and backend tool-call nodes always emit AG-UI tool-call stream events for display.
Those stream events are separate from chat persistence.
With Chat Persistence set to None, the frontend can still render the tool call from stream history, but later model calls do not receive it through input.chat.
The Suspend node stores and resumes a checkpoint only.
It does not write input.chat and does not emit stream events.
On AG-UI resume, agent is updated with the latest user message or latest tool result before downstream nodes continue.
For conversation turns, SharpOMatic automatically stores agent.latestUserMessage as user text stream events before workflow nodes run.
Those events are marked with the transient silent flag for the current live AG-UI SSE stream, so the caller does not render its submitted message twice.
The underlying stream events are still persisted in SharpOMatic history, and the flag itself is not stored in the database.
Code nodes can also emit AG-UI tool-call, activity, state, step, and custom events through the Events.Add* helpers.
For the higher-level activity/state sync helpers and the full helper surface, see the AG-UI and Code Node docs.
| Product | Versions 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. |
-
net10.0
- SharpOMatic.Engine (>= 10.0.5)
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 |
|---|---|---|
| 10.0.6-rc.18 | 40 | 6/3/2026 |
| 10.0.6-rc.17 | 43 | 6/2/2026 |
| 10.0.6-rc.16 | 50 | 6/1/2026 |
| 10.0.6-rc.15 | 47 | 5/31/2026 |
| 10.0.6-rc.14 | 48 | 5/31/2026 |
| 10.0.6-rc.13 | 47 | 5/29/2026 |
| 10.0.6-rc.12 | 47 | 5/29/2026 |
| 10.0.6-rc.11 | 57 | 5/29/2026 |
| 10.0.6-rc.10 | 62 | 5/29/2026 |
| 10.0.6-rc.9 | 63 | 5/29/2026 |
| 10.0.6-rc.8 | 59 | 5/28/2026 |
| 10.0.6-rc.7 | 68 | 5/28/2026 |
| 10.0.6-rc.6 | 52 | 5/28/2026 |
| 10.0.6-rc.5 | 56 | 5/28/2026 |
| 10.0.5 | 108 | 5/28/2026 |
| 10.0.4 | 94 | 5/3/2026 |
| 10.0.4-alpha.12 | 59 | 4/29/2026 |
| 10.0.4-alpha.11 | 51 | 4/27/2026 |
| 10.0.4-alpha.10 | 59 | 4/26/2026 |