The system host
The system host is the .NET project that carries a System’s topology declaration and runs it locally. intropy sys create renders it from the workspace’s scaffold records. Why a declared topology exists, and what it deliberately leaves out, is Systems and topology; this page lists what the host contains and the verbs it answers to. The distribution tutorial creates a host and walks these files in a scaffolded workspace.
Declaration files
Section titled “Declaration files”The declaration is split across small files, one per kind of declaration, each name defined exactly once.
Topics are typed by the contract they carry, shared from the workspace’s contracts project:
using Intropy.Topology;using Contracts;
public static class Topics{ /// <summary>Order messages on topic 'orders' (pubsub 'pubsub').</summary> public static readonly TopicRef<Order> Orders = TopicRef<Order>.Define("pubsub", "orders");}Ports are the named interfaces edge Components reach the outside world through. The name is the whole declaration; what it leaves out is Ports and adapters:
using Intropy.Topology;
public static class Ports{ public static readonly PortRef OrderExtractorSource = PortRef.Define("order-extractor-source"); public static readonly PortRef OrderLoaderDestination = PortRef.Define("order-loader-destination");}Services are the platform services Components call through Dapr service invocation:
using Intropy.Topology;
public static class Services{ public static readonly ServiceRef Idempotency = ServiceRef.Define("idempotency-service"); public static readonly ServiceRef BusinessIncidents = ServiceRef.Define("business-incident-service");}The system definition wires them together:
using Intropy.Topology;
/// <summary>The order-flow system: what exists, and what connects it.</summary>public sealed class OrderFlowSystem : ISystemDefinition{ public string SystemName => "order-flow";
public void Define(SystemBuilder builder) { builder.AddExtractor("order-extractor") .From(Ports.OrderExtractorSource) .Publishes(Topics.Orders) .Uses(Services.Idempotency) .Uses(Services.BusinessIncidents); builder.AddLoader("order-loader") .Subscribes(Topics.Orders) .To(Ports.OrderLoaderDestination) .Uses(Services.Idempotency) .Uses(Services.BusinessIncidents); }}Builder surface
Section titled “Builder surface”Each Add* method returns a builder that exposes only that Component kind’s legal edges; wiring a loader to publish does not compile. There is no AddTopic or AddPort: a ref enters the model when a Component uses it, and a ref no Component uses never enters the topology.
| Component kind | Legal edges on its builder |
|---|---|
AddExtractor |
.From(port), .Publishes(topic), .Uses(service) |
AddLoader |
.Subscribes(topic), .To(port), .Uses(service) |
AddTransactionalIntegration |
.From(port), .To(port), .Uses(service) |
A transactional-integration Component moves messages through an internal, component-owned queue between its receive and send halves. The queue is minted into the model as internal-<component> so deployment can provision it; it is not a System Topic, and no other Component can touch it.
The development definition
Section titled “The development definition”The development definition substitutes local stand-ins for the things the topology only names: Mock backs a Service with an OpenAPI mock, and Files resolves a Port to a folder.
using Intropy.Topology.Generation;
public sealed class OrderFlowDevelopment : IDevelopmentDefinition{ public void Define(DevelopmentBuilder development) { development.Mock(Services.Idempotency).FromOpenApi("mocks/idempotency-service.openapi.yaml"); development.Mock(Services.BusinessIncidents).FromOpenApi("mocks/business-incident-service.openapi.yaml"); development.Files(Ports.OrderExtractorSource).RootPath("./test/order-extractor-source"); development.Files(Ports.OrderLoaderDestination).RootPath("./test/order-loader-destination"); }}The host’s entry point dispatches the same discovered model to different backends, selected by verb:
using System.Reflection;using Intropy.Topology.Aspire;using Intropy.Topology.Generation;
var assembly = Assembly.GetExecutingAssembly();
return args is ["run", ..] or [] ? await IntropyAspire.RunAsync(assembly, args) : IntropyGenerate.Run(assembly, args);run(or F5) translates the topology into .NET Aspire resources: one process per Component, a Redis broker, a Dapr sidecar each, and the development definition’s mocks and folders. The Quick start walks through it.checkvalidates the topology and reports every diagnostic at once.graphprints the model as interchange JSON (topology.intropy.io/v1, kindSystemTopology). This document is the contract the deployment tooling consumes; the runtime concepts page picks up the story from there.generatewrites the Dapr component YAML and per-component configuration the model implies.
Packages
Section titled “Packages”Intropy.Topology is the DSL and model with zero runtime dependencies, Intropy.Topology.Generation adds the check/graph/generate verbs and the development definition, and Intropy.Topology.Aspire is the local-run backend.