Portal Community

Startup Sequence

1
AddOctopus() called in Program.cs The DI container configuration begins. Octopus core services are registered.
2
Plugin.OnRegister() called for each plugin (in registration order) Each plugin registers its services. The DI container is not yet built — services cannot be resolved.
3
DI container built (builder.Build()) All registered services are compiled into the service provider.
4
Plugin.OnStartAsync() called for each plugin (in registration order) Plugins resolve services, apply migrations, register tools. Application is not yet accepting requests.
5
Application starts accepting requests All plugins fully initialised. Agents can handle conversations.

Shutdown Sequence

1
Shutdown signal received SIGTERM, Ctrl+C, or host shutdown. Application stops accepting new requests.
2
In-flight requests drain Active conversations complete (up to graceful shutdown timeout, default 30s).
3
Plugin.OnStopAsync() called in reverse registration order Plugins clean up in reverse order to dependency order. Last-registered plugin stops first.
4
DI container disposed All IDisposable singleton services are disposed.

OnStartAsync — Common Patterns

public async Task OnStartAsync(IServiceProvider sp, CancellationToken ct)
{
    // Pattern 1: Apply EF Core migrations
    using var scope = sp.CreateScope();
    var db = scope.ServiceProvider.GetRequiredService<OctopusDbContext>();
    await db.Database.MigrateAsync(ct);

    // Pattern 2: Register MCP tools (must happen before first request)
    var registry = sp.GetRequiredService<MCPToolRegistry>();
    registry.Register(new MCPTool { ... });

    // Pattern 3: Create vector collection if it doesn't exist
    var qdrant = sp.GetRequiredService<IQdrantClient>();
    await EnsureCollectionsExistAsync(qdrant, ct);

    // Pattern 4: Warm up a cache or connection
    var cache = sp.GetRequiredService<IMyCache>();
    await cache.WarmUpAsync(ct);
}

OnStopAsync — Clean Shutdown

public async Task OnStopAsync(CancellationToken ct)
{
    // Flush any buffered writes
    await _writer.FlushAsync(ct);

    // Close external connections gracefully
    await _externalClient.DisconnectAsync(ct);

    // Signal background tasks to stop
    _backgroundCts.Cancel();
    await _backgroundTask;  // Wait for completion

    // Dispose resources
    _qdrantClient?.Dispose();
}