HPD-Events 0.5.6

dotnet add package HPD-Events --version 0.5.6
                    
NuGet\Install-Package HPD-Events -Version 0.5.6
                    
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="HPD-Events" Version="0.5.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="HPD-Events" Version="0.5.6" />
                    
Directory.Packages.props
<PackageReference Include="HPD-Events" />
                    
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 HPD-Events --version 0.5.6
                    
#r "nuget: HPD-Events, 0.5.6"
                    
#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 HPD-Events@0.5.6
                    
#: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=HPD-Events&version=0.5.6
                    
Install as a Cake Addin
#tool nuget:?package=HPD-Events&version=0.5.6
                    
Install as a Cake Tool

HPD.Events

HPD.Events is the shared event foundation for HPD frameworks. It provides semantic class events, fan-out coordination, caller-owned inboxes, inbox-backed async streams, request/response sessions, replay helpers, process-local struct event lanes, local wake signals, and dependency-injection registration.

The package is intentionally infrastructure-only. Domain packages own their event types, authorization, redaction, transport projection, tenancy, and persistence policy.

Install

dotnet add package HPD-Events

Event Families

HPD.Events has five related surfaces:

  • Semantic class events: Event, IEventCoordinator, EventCoordinator, IEventBus
  • Async stream contracts: AsyncStream<TItem>, IAsyncStreamSource<TRequest,TItem>, IEventStreamSource<TEvent>
  • Replay helpers: IReplaySource<TEvent>, IEventStore<TEvent>, ReplayTimeline<TEvent>
  • Struct events: HPD.Events.Struct for process-local hot-path samples and frames
  • Signals and mailboxes: HPD.Events.Signals for local event-loop wakeups

Use the smallest surface that matches the job. Do not use struct events as a faster semantic bus, and do not use signals as a domain event model.

Semantic Events

Create domain events by inheriting from Event.

public sealed record NodeCompletedEvent : Event
{
    public required string GraphId { get; init; }
    public required string NodeId { get; init; }
    public required bool Succeeded { get; init; }
    public required TimeSpan Duration { get; init; }
}

Event includes routing and timing fields:

  • Channel
  • Kind
  • Direction
  • SequenceNumber
  • EventFlowId
  • CanInterrupt
  • Timestamp
  • ExchangeTimestampNs

Event does not include an arbitrary Extensions, Metadata, or Properties bag. If data matters to the event, put it on the event as a typed property.

Annotations

Use annotations only for sparse scalar metadata that is not part of the primary event fact, such as diagnostic or projection hints.

public sealed record DiagnosticEvent : Event, IAnnotatedEvent
{
    public required string Message { get; init; }

    public IReadOnlyList<EventAnnotation> Annotations { get; init; } =
    [
        new()
        {
            Key = "display",
            Value = EventAnnotationValue.FromBoolean(true),
            Visibility = EventAnnotationVisibility.Public
        }
    ];
}

Annotation values are source-generation-friendly scalars: string, integer, number, or boolean. Annotation visibility is only a projection hint, not an authorization policy.

Coordinator

EventCoordinator is the primary semantic event facade. It implements:

  • IEventCoordinator
  • IEventBus
  • IEventPublisher
  • IEventObserverBus
  • IEventInboxSource
  • IRequestResponseBus
  • IHierarchicalEventBus
using HPD.Events.Core;

using var events = new EventCoordinator();

using var subscription = events.Subscribe<NodeCompletedEvent>(evt =>
{
    Console.WriteLine($"{evt.NodeId}: {evt.Succeeded}");
    return ValueTask.CompletedTask;
});

events.Emit(new NodeCompletedEvent
{
    GraphId = "graph-1",
    NodeId = "node-1",
    Succeeded = true,
    Duration = TimeSpan.FromMilliseconds(42)
});

Handlers run from subscriber mailboxes. Publishing means the event was accepted into matching mailboxes; it does not mean every handler has finished.

Inboxes

Use EventInbox<TEvent> for low-level local consumption when the caller should own the reader loop and subscription lifetime.

await using var inbox = events.CreateInbox<NodeCompletedEvent>();

events.Emit(new NodeCompletedEvent
{
    GraphId = "graph-1",
    NodeId = "node-1",
    Succeeded = true,
    Duration = TimeSpan.Zero
});

await foreach (var evt in inbox.Reader.ReadAllAsync(cancellationToken))
{
    Console.WriteLine(evt.NodeId);
    break;
}

Use direct inboxes for private loops, deterministic tests, request-local observation, and code that needs exact subscription ownership.

Event Streams

Use IEventStreamSource<TEvent> or EventStreamSource<TEvent> for public, host-facing, transport-facing, UI-facing, connector-facing, and framework-facing live event feeds.

var source = new EventStreamSource<NodeCompletedEvent>(events);

var opened = await source.OpenAsync(new EventStreamRequest<NodeCompletedEvent>
{
    StreamId = "graph.nodes",
    Channel = EventChannel.Synchronous,
    Capacity = 1024,
    Backpressure = AsyncStreamBackpressureMode.Wait
}, cancellationToken);

if (!opened.Succeeded || opened.Value is null)
    throw new InvalidOperationException(opened.Error?.Message);

await foreach (var evt in opened.Value.Items.WithCancellation(cancellationToken))
{
    Console.WriteLine(evt.NodeId);
}

Event streams are live and inbox-backed. They are not replayable, resumable, durable, authorized, redacted, or transport-specific. Higher-level packages add those policies.

Dependency Injection

Use AddHPDEvents() for host integration.

using HPD.Events.DependencyInjection;

services.AddHPDEvents();

The default lifetime is singleton. This is the right default for app-level event spines.

Use scoped registration for request-local event buses, such as auth endpoint/audit flows.

services.AddHPDEvents(options =>
{
    options.Lifetime = HPDEventsServiceLifetime.Scoped;
});

Optional registrations are enabled by default:

services.AddHPDEvents(options =>
{
    options.RegisterStructEvents = true;
    options.RegisterEventStreams = true;
});

All class-event interfaces resolve through the same EventCoordinator instance within the selected lifetime.

Request/Response

Request/response sessions are events with correlation fields.

public sealed record ApprovalRequest : Event, IRequestEvent
{
    public required string RequestId { get; init; }
    public required string SourceName { get; init; }
    public required string Prompt { get; init; }
}

public sealed record ApprovalResponse : Event, IResponseEvent
{
    public required string RequestId { get; init; }
    public required string SourceName { get; init; }
    public required bool Approved { get; init; }
}
using var responder = events.Subscribe<ApprovalRequest>(request =>
{
    events.Respond(new ApprovalResponse
    {
        RequestId = request.RequestId,
        SourceName = "operator",
        Approved = true
    });

    return ValueTask.CompletedTask;
});

var response = await events.RequestAsync<ApprovalRequest, ApprovalResponse>(
    new ApprovalRequest
    {
        RequestId = Guid.NewGuid().ToString("N"),
        SourceName = "workflow",
        Prompt = "Continue?"
    },
    TimeSpan.FromSeconds(30),
    cancellationToken);

Hierarchy

Coordinators can bubble events to a parent coordinator.

using var parent = new EventCoordinator();
using var child = new EventCoordinator();

child.SetParent(parent);

Use hierarchy for nested runtimes, agent subflows, graph execution trees, and workflow scopes that need parent-level observation.

Event Flows

Event flows group interruptible events.

using var flow = events.EventFlows.Create();

events.Emit(new NodeCompletedEvent
{
    EventFlowId = flow.EventFlowId,
    GraphId = "graph-1",
    NodeId = "node-1",
    Succeeded = true,
    Duration = TimeSpan.Zero
});

flow.Interrupt();

Events with CanInterrupt = false still deliver after interruption.

Replay

Replay is separate from live delivery.

var store = new InMemoryEventStore<NodeCompletedEvent>();
await store.AppendAsync(new NodeCompletedEvent
{
    GraphId = "graph-1",
    NodeId = "node-1",
    Succeeded = true,
    Duration = TimeSpan.Zero
});

var timeline = ReplayTimeline<NodeCompletedEvent>
    .Create()
    .AddSource("store", store);

await foreach (var evt in timeline.ReadAsync(ReplayReadOptions.All, cancellationToken))
{
    Console.WriteLine(evt.NodeId);
}

A replay source can publish into an event publisher, but the coordinator is not a durable event store.

Struct Events

Use HPD.Events.Struct for process-local hot-path samples and frames.

using HPD.Events.Struct;

public readonly record struct QueueDepthSample(int Depth) : IStructEvent
{
    public EventKind Kind => EventKind.Diagnostic;
    public long SequenceNumber => 0;
    public long TimestampNs => 0;
}

using var hub = new StructEventHub();
var route = hub.Route<QueueDepthSample>();
using var inbox = route.CreateInbox();
var emitter = route.CreateEmitter();

emitter.Emit(new QueueDepthSample(12));

if (inbox.TryRead(out var sample))
    Console.WriteLine(sample.Depth);

Struct events are not automatically serialized, replayed, transported, or mirrored into semantic class events.

Signals And Mailboxes

Use signals and mailboxes for local scheduling loops.

var signal = new EventSignal();
signal.Signal();
await signal.WaitAsync(cancellationToken);

await using var mailbox = new EventLoopMailbox<string>();
mailbox.TryWrite("work");
await mailbox.WaitToReadAsync(cancellationToken);

Signals and mailboxes are coordination primitives, not semantic event feeds.

Boundaries

HPD.Events does not provide:

  • ASP.NET endpoints
  • SSE/WebSocket/SignalR/gRPC transports
  • authorization
  • tenant filtering
  • redaction
  • durable event sourcing
  • domain event types
  • automatic class-event/struct-event bridges

Build those in consuming packages where domain policy is known.

Native AOT

The package is AOT-compatible. The local AOT smoke test exercises class events, inboxes, event streams, request/response, replay, event store, struct events, signals, source-generated JSON, annotations, and DI.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  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 (20)

Showing the top 5 NuGet packages that depend on HPD-Events:

Package Downloads
HPD-Agent.Framework

A middleware-driven agentic AI framework built on Microsoft.Extensions.AI for building intelligent, tool-using agents.

HPD-Graph.Abstractions

Core abstractions for HPD-Graph - a universal DAG execution engine. Domain-agnostic interfaces and types for building workflow orchestration systems.

HPD-Graph.Core

Core implementation of HPD-Graph - a universal DAG execution engine with support for parallel execution, checkpointing, and content-addressable caching.

HPD-Agent.MultiAgent

Fluent multi-agent orchestration library built on HPD-Graph. Zero-ceremony agent workflows with unified event streaming.

HPD-Agent.Sandbox.Local

Direct local host sandbox backend for HPD Agent process execution.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.5.6 603 7/4/2026
0.5.5 1,021 6/21/2026
0.5.0 1,811 6/11/2026