akka-hosting-actor-patterns
Patterns for building entity actors with Akka.Hosting - GenericChildPerEntityParent, message extractors, cluster sharding abstraction, akka-reminders, and ITimeProvider. Supports both local testing and clustered production modes.
Install / Use
npx skills add Aaronontheweb/dotnet-skills --skill akka-hosting-actor-patternsInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
Customer SupportSupported Platforms
Our assessment of akka-hosting-actor-patterns
akka-hosting-actor-patterns scores 93/100 on our quality scale, 90th of 334 Customer Support skills we index (top 27%).
Its SKILL.md is 19 KB long, well organised into 24 sections with 16 code examples: a thorough specification that gives an agent plenty to work with.
With 1,183 GitHub stars, it is one of the more widely adopted skills in the catalogue.
Maintenance, license and trust
- The repository was last updated 15 days ago, so akka-hosting-actor-patterns is actively maintained.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
akka-hosting-actor-patterns compared with similar skills
All 4 of these similar skills score higher than akka-hosting-actor-patterns; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| akka-hosting-actor-patterns (this skill)by Aaronontheweb | 93 | 1.2k | 15d ago | SKILL.md |
| LocalAIby mudler | 100 | 49.4k | today | MCP Server |
| algorithmic-artby anthropics | 100 | 177.9k | 10d ago | SKILL.md |
| pptxby anthropics | 100 | 177.9k | 10d ago | SKILL.md |
| designby nextlevelbuilder | 100 | 130.2k | 12d ago | SKILL.md |
Frequently asked questions
- How do I install akka-hosting-actor-patterns?
- Run
npx skills add Aaronontheweb/dotnet-skills --skill akka-hosting-actor-patterns. The install tabs above show the steps for each supported agent. - Which AI agents does akka-hosting-actor-patterns work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is akka-hosting-actor-patterns safe to use?
- It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is akka-hosting-actor-patterns still maintained?
- The repository was last updated 15 days ago, so akka-hosting-actor-patterns is actively maintained.
Skill content
View source on GitHubname: akka-hosting-actor-patterns description: Patterns for building entity actors with Akka.Hosting - GenericChildPerEntityParent, message extractors, cluster sharding abstraction, akka-reminders, and ITimeProvider. Supports both local testing and clustered production modes. invocable: false
Akka.Hosting Actor Patterns
When to Use This Skill
Use this skill when:
- Building entity actors that represent domain objects (users, orders, invoices, etc.)
- Need actors that work in both unit tests (no clustering) and production (cluster sharding)
- Setting up scheduled tasks with akka-reminders
- Registering actors with Akka.Hosting extension methods
- Creating reusable actor configuration patterns
Core Principles
- Execution Mode Abstraction - Same actor code runs locally (tests) or clustered (production)
- GenericChildPerEntityParent for Local - Mimics sharding semantics without cluster overhead
- Message Extractors for Routing - Reuse Akka.Cluster.Sharding's IMessageExtractor interface
- Akka.Hosting Extension Methods - Fluent configuration that composes well
- ITimeProvider for Testability - Use ActorSystem.Scheduler instead of DateTime.Now
Execution Modes
Define an enum to control actor behavior:
/// <summary>
/// Determines how Akka.NET should be configured
/// </summary>
public enum AkkaExecutionMode
{
/// <summary>
/// Pure local actor system - no remoting, no clustering.
/// Use GenericChildPerEntityParent instead of ShardRegion.
/// Ideal for unit tests and simple scenarios.
/// </summary>
LocalTest,
/// <summary>
/// Full clustering with ShardRegion.
/// Use for integration testing and production.
/// </summary>
Clustered
}
GenericChildPerEntityParent
A lightweight parent actor that routes messages to child entities, mimicking cluster sharding semantics without requiring a cluster:
using Akka.Actor;
using Akka.Cluster.Sharding;
/// <summary>
/// A generic "child per entity" parent actor.
/// </summary>
/// <remarks>
/// Reuses Akka.Cluster.Sharding's IMessageExtractor for consistent routing.
/// Ideal for unit tests where clustering overhead is unnecessary.
/// </remarks>
public sealed class GenericChildPerEntityParent : ReceiveActor
{
public static Props CreateProps(
IMessageExtractor extractor,
Func<string, Props> propsFactory)
{
return Props.Create(() =>
new GenericChildPerEntityParent(extractor, propsFactory));
}
private readonly IMessageExtractor _extractor;
private readonly Func<string, Props> _propsFactory;
public GenericChildPerEntityParent(
IMessageExtractor extractor,
Func<string, Props> propsFactory)
{
_extractor = extractor;
_propsFactory = propsFactory;
ReceiveAny(message =>
{
var entityId = _extractor.EntityId(message);
if (entityId is null) return;
// Get existing child or create new one
Context.Child(entityId)
.GetOrElse(() => Context.ActorOf(_propsFactory(entityId), entityId))
.Forward(_extractor.EntityMessage(message));
});
}
}
Message Extractors
Create extractors that implement IMessageExtractor from Akka.Cluster.Sharding:
using Akka.Cluster.Sharding;
/// <summary>
/// Routes messages to entity actors based on a strongly-typed ID.
/// </summary>
public sealed class OrderMessageExtractor : HashCodeMessageExtractor
{
public const int DefaultShardCount = 40;
public OrderMessageExtractor(int maxNumberOfShards = DefaultShardCount)
: base(maxNumberOfShards)
{
}
public override string? EntityId(object message)
{
return message switch
{
IWithOrderId msg => msg.OrderId.Value.ToString(),
_ => null
};
}
}
// Define an interface for messages that target a specific entity
public interface IWithOrderId
{
OrderId OrderId { get; }
}
// Use strongly-typed IDs
public readonly record struct OrderId(Guid Value)
{
public static OrderId New() => new(Guid.NewGuid());
public override string ToString() => Value.ToString();
}
Akka.Hosting Extension Methods
Create extension methods that abstract the execution mode:
using Akka.Cluster.Hosting;
using Akka.Cluster.Sharding;
using Akka.Hosting;
public static class OrderActorHostingExtensions
{
/// <summary>
/// Adds OrderActor with support for both local and clustered modes.
/// </summary>
public static AkkaConfigurationBuilder WithOrderActor(
this AkkaConfigurationBuilder builder,
AkkaExecutionMode executionMode = AkkaExecutionMode.Clustered,
string? clusterRole = null)
{
if (executionMode == AkkaExecutionMode.LocalTest)
{
// Non-clustered mode: Use GenericChildPerEntityParent
builder.WithActors((system, registry, resolver) =>
{
var parent = system.ActorOf(
GenericChildPerEntityParent.CreateProps(
new OrderMessageExtractor(),
entityId => resolver.Props<OrderActor>(entityId)),
"orders");
registry.Register<OrderActor>(parent);
});
}
else
{
// Clustered mode: Use ShardRegion
builder.WithShardRegion<OrderActor>(
"orders",
(system, registry, resolver) =>
entityId => resolver.Props<OrderActor>(entityId),
new OrderMessageExtractor(),
new ShardOptions
{
StateStoreMode = StateStoreMode.DData,
Role = clusterRole
});
}
return builder;
}
}
Composing Multiple Actors
Create a convenience method that registers all domain actors:
public static class DomainActorHostingExtensions
{
/// <summary>
/// Adds all order domain actors with sharding support.
/// </summary>
public static AkkaConfigurationBuilder WithOrderDomainActors(
this AkkaConfigurationBuilder builder,
AkkaExecutionMode executionMode = AkkaExecutionMode.Clustered,
string? clusterRole = null)
{
return builder
.WithOrderActor(executionMode, clusterRole)
.WithPaymentActor(executionMode, clusterRole)
.WithShipmentActor(executionMode, clusterRole)
.WithNotificationActor(); // Singleton, no sharding needed
}
}
Using ITimeProvider for Scheduling
Register the ActorSystem's Scheduler as an ITimeProvider for testable time-based logic:
public static class SharedAkkaHostingExtensions
{
public static IServiceCollection AddAkkaWithTimeProvider(
this IServiceCollection services,
Action<AkkaConfigurationBuilder, IServiceProvider> configure)
{
// Register ITimeProvider using the ActorSystem's Scheduler
services.AddSingleton<ITimeProvider>(sp =>
sp.GetRequiredService<ActorSystem>().Scheduler);
return services.ConfigureAkka((builder, sp) =>
{
configure(builder, sp);
});
}
}
// In your actor, inject ITimeProvider
public class SubscriptionActor : ReceiveActor
{
private readonly ITimeProvider _timeProvider;
public SubscriptionActor(ITimeProvider timeProvider)
{
_timeProvider = timeProvider;
// Use _timeProvider.GetUtcNow() instead of DateTime.UtcNow
// This allows tests to control time
}
}
Akka.Reminders Integration
For durable scheduled tasks that survive restarts, use akka-reminders:
using Akka.Reminders;
using Akka.Reminders.Sql;
using Akka.Reminders.Sql.Configuration;
using Akka.Reminders.Storage;
public static class ReminderHostingExtensions
{
/// <summary>
/// Configures akka-reminders with PostgreSQL storage.
/// </summary>
public static AkkaConfigurationBuilder WithPostgresReminders(
this AkkaConfigurationBuilder builder,
string connectionString,
string schemaName = "reminders",
string tableName = "scheduled_reminders",
bool autoInitialize = true)
{
return builder.WithLocalReminders(reminders => reminders
.WithResolver(sys => new GenericChildPerEntityResolver(sys))
.WithStorage(system =>
{
var settings = SqlReminderStorageSettings.CreatePostgreSql(
connectionString,
schemaName,
tableName,
autoInitialize);
return new SqlReminderStorage(settings, system);
})
.WithSettings(new ReminderSettings
{
MaxSlippage = TimeSpan.FromSeconds(30),
MaxDeliveryAttempts = 3,
RetryBackoffBase = TimeSpan.FromSeconds(10)
}));
}
/// <summary>
/// Configures akka-reminders with in-memory storage for testing.
/// </summary>
public static AkkaConfigurationBuilder WithInMemoryReminders(
this AkkaConfigurationBuilder builder)
{
return builder.WithLocalReminders(reminders => reminders
.WithResolver(sys => new GenericChildPerEntityResolver(sys))
.WithStorage(system => new InMemoryReminderStorage())
.WithSettings(new ReminderSettings
{
MaxSlippage = TimeSpan.FromSeconds(1),
MaxDeliveryAttempts = 3,
RetryBackoffBase = TimeSpan.FromMilliseconds(100)
}));
}
}
Custom Reminder Resolver for Child-Per-Entity
Route reminder callbacks to GenericChildPerEntityParent actors:
using Akka.Actor;
using Akka.Hosting;
using Akka.Reminders;
/// <summary>
/// Resolves reminder targets to GenericChildPerEntityParent actors.
/// </summary>
public sealed class GenericChildPerEntityResolver : IReminderActorResolver
{
private readonly ActorSystem _system;
public GenericChildPerEntityResolver(ActorSystem system)
{
_system = system;
}
public IActorRef ResolveActorRef(ReminderEntry entry)
{
var registry = ActorRegistry.For(_system);
return entry.Key switch
{
var k when k.StartsWith("order-") =>
registry.Get<OrderActor>(),
var k when k.StartsWith("subscription-") =>
registry.Get<SubscriptionActor>(),
_ => throw new InvalidOperationException(
$"Unknown reminder key format: {entry.Key}")
};
}
}
Singleton Actors (Not Sharded)
For actors that should only have one instance:
public static AkkaConfigurationBuilder WithEmailSenderActor(
this AkkaConfigurationBuilder builder)
{
return builder.WithActors((system, registry, resolver) =>
{
var actor = system.ActorOf(
resolver.Props<EmailSenderActor>(),
"email-sender");
registry.Register<EmailSenderActor>(actor);
});
}
Marker Types for Registry
When you need to reference actors that are registered as parents:
/// <summary>
/// Marker type for ActorRegistry to retrieve the order manager
/// (GenericChildPerEntityParent for OrderActors).
/// </summary>
public sealed class OrderManagerActor;
// Usage in extension method
registry.Register<OrderManagerActor>(parent);
// Usage in controller/service
public class OrderService
{
private readonly IActorRef _orderManager;
public OrderService(IRequiredActor<OrderManagerActor> orderManager)
{
_orderManager = orderManager.ActorRef;
}
public async Task<OrderResponse> CreateOrder(CreateOrderCommand cmd)
{
return await _orderManager.Ask<OrderResponse>(cmd);
}
}
DI Scope Management in Actors
Truncated for display — read the full file on GitHub.
Related Skills
LocalAI
49.4kLocalAI is the open-source AI engine. Run any model - LLMs, vision, voice, image, video - on any hardware. No GPU required.
algorithmic-art
177.9kCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems.
pptx
177.9kUse this skill any time a .pptx or .potx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx or .potx file (even if the extracted content will be used elsewhere, like in an em…
design
130.2kComprehensive design skill: brand identity, design tokens, UI styling, logo generation (55 styles, Gemini, Atlas Cloud, or MuAPI AI), corporate identity program (50 deliverables, CIP mockups), HTML presentations (Chart.js), banner design (22 styles, social/ads/web/print), icon design (15 styles, SVG…
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
