Home / Docs / Server

Server

Server

The FabrCore server hosts your agents on an Orleans cluster. It provides REST and WebSocket APIs for client communication and background services for housekeeping.

Extension Methods

AddFabrCoreServer

Configures FabrCore server infrastructure including Orleans, services, and streaming.

Program.cs
var builder = WebApplication.CreateBuilder(args);

// Basic setup
builder.AddFabrCoreServer();

// With additional assemblies for custom agents
builder.AddFabrCoreServer(new FabrCoreServerOptions
{
    AdditionalAssemblies = new List<Assembly>
    {
        typeof(MyCustomAgent).Assembly
    }
});

What it configures:

  • Orleans silo with clustering, persistence, and reminders
  • IFabrCoreRegistry (singleton) — Agent, plugin, and tool discovery
  • IFabrCoreChatClientService (singleton) — Chat client factory
  • IEmbeddings (singleton) — Embedding generation with cached client
  • IFileStorageService (singleton) — File storage with TTL
  • FileCleanupBackgroundService — Automatic file cleanup
  • AgentRegistryCleanupService — Automatic agent registry cleanup

UseFabrCoreServer

Registers FabrCore middleware, including the WebSocket endpoint for real-time agent communication.

Program.cs
var app = builder.Build();

app.UseFabrCoreServer();

// Or with options
app.UseFabrCoreServer(new FabrCoreServerOptions
{
    AdditionalAssemblies = new List<Assembly> { typeof(MyAgent).Assembly }
});

Complete Startup Example

Program.cs — Full Setup
var builder = WebApplication.CreateBuilder(args);

builder.AddFabrCoreServer(new FabrCoreServerOptions
{
    AdditionalAssemblies = new() { typeof(MyAgent).Assembly }
});

builder.Services.AddControllers();

var app = builder.Build();

app.UseFabrCoreServer();
app.MapControllers();

await app.RunAsync();

FabrCoreRegistry

FabrCoreRegistry automatically discovers agents, plugins, and tools at startup by scanning loaded assemblies for alias attributes. No manual registration lists needed — decorate your classes and they're available.

Loading Additional Assemblies

If your agents, plugins, or tools are in separate assemblies, pass them via AdditionalAssemblies. This ensures the registry scans those assemblies at startup:

Program.cs — Assembly Loading
builder.AddFabrCoreServer(new FabrCoreServerOptions
{
    AdditionalAssemblies = new List<Assembly>
    {
        typeof(MyCustomAgent).Assembly,
        typeof(MyPluginLibrary).Assembly
    }
});
You Don't Need Custom Discovery

FabrCore handles discovery for agents ([AgentAlias]), plugins ([PluginAlias]), and tools ([ToolAlias]) automatically. For application-level concerns like UI components or middleware, use ASP.NET Core's built-in AddApplicationPart() instead of building custom scanning systems.

How Discovery Works

Assembly Scan Find Alias Attributes Index by Alias Ready to Resolve
AttributeTargetDescription
[AgentAlias("name")]ClassRegisters a FabrCoreAgentProxy under one or more aliases
[PluginAlias("name")]ClassRegisters an IFabrCorePlugin for agent use
[ToolAlias("name")]MethodRegisters a static method as a callable tool

All attributes support AllowMultiple = true, so a single component can have multiple aliases:

Multi-Alias Example
[AgentAlias("assistant")]
[AgentAlias("my-assistant")]
public class AssistantAgent : FabrCoreAgentProxy
{
    // Reachable via either alias
}

Registry API

MethodReturnsDescription
GetAgentTypes()List<RegistryEntry>All discovered agents with their aliases
GetPlugins()List<RegistryEntry>All discovered plugins with their aliases
GetTools()List<RegistryEntry>All discovered tools with their aliases
FindAgentType(alias)Type?Resolve an agent alias to its concrete type

Discovery REST Endpoint

The registry is exposed via a built-in REST endpoint, allowing clients to discover available agents, plugins, and tools at runtime:

MethodEndpointDescription
GET/fabrcoreapi/DiscoveryReturns all registered agents, plugins, and tools
Discovery Response
{
  "agents": [
    { "typeName": "MyApp.AssistantAgent", "aliases": ["assistant", "my-assistant"] }
  ],
  "plugins": [
    { "typeName": "MyApp.WeatherPlugin", "aliases": ["weather"] }
  ],
  "tools": [
    { "typeName": "MyApp.MathTools.Add", "aliases": ["add-numbers"] }
  ]
}
Dev Experience

The discovery endpoint makes it easy to verify your agents, plugins, and tools are correctly registered. Hit /fabrcoreapi/Discovery during development to confirm everything was picked up by the assembly scan — no guesswork needed.

REST API

All endpoints are prefixed with /fabrapi.

Agent API

MethodEndpointDescription
POST/fabrapi/Agent/createCreate one or more agents for a user
GET/fabrapi/Agent/health/{handle}Get agent health status
POST/fabrapi/Agent/chat/{handle}Send a message and receive a response

All Agent API endpoints require the x-user header to identify the user.

Create Agent — Request
POST /fabrapi/Agent/create
x-user: user123

[{
  "handle": "my-agent",
  "agentType": "MyAgent",
  "models": "default",
  "systemPrompt": "You are a helpful assistant."
}]

Diagnostics API

MethodEndpointDescription
GET/fabrapi/Diagnostics/agentsList all registered agents
GET/fabrapi/Diagnostics/agents/{key}Get specific agent info
GET/fabrapi/Diagnostics/agents/statisticsAgent count statistics
POST/fabrapi/Diagnostics/agents/purgePurge deactivated agents

File & Embeddings API

MethodEndpointDescription
POST/fabrapi/File/uploadUpload a file (multipart/form-data)
GET/fabrapi/File/{fileId}Download a file
GET/fabrapi/File/{fileId}/infoGet file metadata
POST/fabrapi/EmbeddingsGenerate a vector embedding for a single text
POST/fabrcoreapi/embeddings/batchGenerate embeddings for multiple texts in a single request (up to 2,048 items)

Batch Embeddings

The batch endpoint accepts a list of items, each with a caller-provided id and text:

POST /fabrcoreapi/embeddings/batch — Request
{
  "items": [
    { "id": "item-1", "text": "First document to embed" },
    { "id": "item-2", "text": "Second document to embed" },
    { "id": "item-3", "text": "Third document to embed" }
  ]
}
Response
{
  "results": [
    { "id": "item-1", "vector": [0.0123, -0.0456, ...], "dimensions": 1536 },
    { "id": "item-2", "vector": [0.0789, -0.0321, ...], "dimensions": 1536 },
    { "id": "item-3", "vector": [0.0654, -0.0987, ...], "dimensions": 1536 }
  ]
}

Validation Rules

ConditionError (400)
Items is null or empty"Items list must not be empty."
Any item has empty id"Item at index {i} has an empty Id."
Any item has empty text"Item at index {i} (Id='{id}') has empty Text."
More than 2,048 items"Batch size {n} exceeds maximum of 2048."
Error Handling

All endpoints return consistent error responses: 200 (Success), 400 (Bad Request), 404 (Not Found), 500 (Internal Server Error).

WebSocket API

Real-time communication with agents via WebSocket at the /ws endpoint.

JavaScript — Connect
// Browser
const ws = new WebSocket('wss://your-server/ws?userid=user123');

// Send a message
ws.send(JSON.stringify({
  toHandle: "my-agent",
  fromHandle: "user123",
  message: "Hello, agent!"
}));

Authentication requires either the x-fabr-userid header or the userid query parameter.

Orleans Streaming

FabrCore uses Orleans streams for agent communication:

StreamNamespacePurpose
AgentChatAgentChatRequest/response messaging
AgentEventAgentEventFire-and-forget events

Background Services

ServiceIntervalDescription
FileCleanupBackgroundServiceConfigurableRemoves expired files and orphaned entries
AgentRegistryCleanupServiceEvery 6 hoursPurges agents deactivated more than 7 days ago
Documentation