WebSocket v2
Authenticated real-time agent connectivity
WebSocket v2 is FabrCore's live principal transport. It carries typed agent operations and durable agent-to-principal deliveries, while HTTP remains responsible for provisioning agents and applying blueprints.
Raw AgentMessage frames, query/header principal selection, MessageType: "command", and createagent are removed. Migrate to FabrCore.Client.WebSocket or implement the v2 ticket, handshake, envelope, delivery, and acknowledgement protocol.
Install the typed client
dotnet add package FabrCore.Client.WebSocket --version 1.7.1
Connection flow
- Authenticate the client's
HttpClientthrough the application's ASP.NET Core authentication. POST /fabrcoreapi/ws/ticket. The Host resolves the authenticated principal and returns a single-use ticket valid for 30 seconds by default.- Open
/wsofferingfabrcore.v2andfabrcore.ticket.<token>as subprotocols. - Send
hellofirst with a stableclientIdand the last persisted checkpoint. - Process ordered
deliveryframes and acknowledge committed sequence numbers.
The Host overwrites sender/source fields with the authenticated principal. Bare agent targets are scoped to that principal; qualified targets pass through normal ACL enforcement. The System principal cannot connect.
Typed .NET client
Use a stable client id for the same logical browser profile, service instance, or device. Replace the in-memory checkpoint store when checkpoints must survive application restarts.
using FabrCore.Client.WebSocket;
var client = new FabrCoreWebSocketClient(
authenticatedHttpClient,
new FabrCoreWebSocketClientOptions
{
HostUri = new Uri("https://agents.example.com"),
ClientId = "ops-console-browser-42"
},
checkpointStore);
client.ResyncRequired += (_, gap) =>
{
// Rebuild application state through HTTP queries.
};
await client.ConnectAsync(cancellationToken);
await foreach (var delivery in client.ReadDeliveriesAsync(cancellationToken))
{
await ApplyToLocalState(delivery.Message, cancellationToken);
await client.AcknowledgeAsync(delivery.Sequence, cancellationToken);
}
Send a request/response message
var response = await client.SendMessageAndReceiveAsync(
new AgentMessage
{
ToHandle = "assistant",
Message = "Summarize today's incidents."
},
cancellationToken);
Supported operations
| Operation | Typed method | Purpose |
|---|---|---|
message.send | SendMessageAsync / SendMessageAndReceiveAsync | Explicit asynchronous or request/response message delivery. |
event.send | SendEventAsync | Publish an event. |
agent.reset | ResetAgentAsync | Soft-reset an existing agent. |
agent.health.get | GetAgentHealthAsync | Read agent health at the requested detail level. |
agents.tracked.list | GetTrackedAgentsAsync | List agents tracked for the connected principal. |
agent.tracked.check | IsAgentTrackedAsync | Check one tracked handle. |
agents.shared.list | GetSharedAgentsAsync | List ACL-visible shared agents. |
Creation, reconfiguration, hard eviction, blueprint application, and arbitrary provisioning are deliberately excluded. Use the Host REST APIs for those lifecycle operations.
Durable delivery, replay, and gaps
- Agent-to-principal messages are persisted before the v2 client is notified.
- Delivery is ordered and at-least-once for each stable
clientId. - A reconnect resumes after the lower of the server acknowledgement and client checkpoint. Duplicates are possible; silent skips are not.
- A new client id starts at the current tail rather than replaying another client's backlog.
- If retention removed a required record, the server emits
gap; rebuild application state through HTTP before continuing. - Queue saturation closes the socket with status 1013 instead of silently dropping durable deliveries.
- Mutating client requests are not automatically retried after an indeterminate disconnect.
Host configuration
{
"FabrCore": {
"Host": {
"AllowedWebSocketOrigins": ["https://app.example.com"]
},
"WebSocket": {
"TicketLifetime": "00:00:30",
"MaxConcurrentRequests": 8,
"RequestTimeout": "00:05:00",
"DeliveryRetention": "1.00:00:00",
"MaxDeliveriesPerPrincipal": 10000,
"MaxClientsPerPrincipal": 16,
"InactiveClientExpiration": "1.00:00:00",
"AllowDevelopmentPrincipalSelection": false
}
}
}
Production browser origins must be explicitly allowed. Headless clients may omit the Origin header. Keep development principal selection disabled outside local development.
v1 migration checklist
- Provision agents through HTTP or blueprints before connecting.
- Replace raw WebSocket construction with the typed client or the documented v2 handshake.
- Remove
x-fabrcore-userhandle,userhandle, and query-string identity selection. - Choose asynchronous versus request/response behavior explicitly.
- Persist checkpoints and make delivery handling idempotent.
- Implement HTTP resynchronization for
ResyncRequired.