Portal Community

Requesting a First-Party Plugin

First-party plugins are built and maintained by the BizFirstAI core team. They receive full support, security reviews, and version compatibility guarantees. To request a first-party plugin:

  1. Visit the BizFirstAI Community and open a new Plugin Request topic.
  2. Describe the integration target (e.g. "Zendesk"), the use cases it enables, and an estimate of how many of your users would benefit.
  3. List the external APIs or SDKs you expect the plugin to use, and whether OAuth or API-key auth applies.
  4. The core team reviews all requests monthly and updates the priority queue in the Roadmap Overview.
Upvoting accelerates delivery. When multiple customers request the same plugin, it rises in the priority queue. Add a reaction or reply to existing requests rather than opening duplicates.

What Makes a Strong Plugin Request

ElementGood ExampleWeak Example
Integration target"Zendesk Support — ticket creation and status updates""A ticketing plugin"
Use case"Agents that triage inbound support requests and auto-assign to the right team""Would be useful for support"
Affected users"We have 200 agents handling 5,000 tickets/month""Many people use Zendesk"
API availability"Zendesk REST API v2 — well-documented, OAuth 2.0"Not mentioned
Proposed toolsticket_create, ticket_update, ticket_searchNot mentioned

Contributing a Community Plugin

Community plugins implement IOctopusPlugin and are distributed as NuGet packages. The Octopus host loads them at startup alongside first-party plugins — they are first-class citizens in the plugin system.

Step 1: Scaffold the project

dotnet new classlib -n MyCompany.Octopus.ZendeskPlugin
cd MyCompany.Octopus.ZendeskPlugin
dotnet add package BizFirstAI.Octopus.PluginSdk

Step 2: Implement IOctopusPlugin

using BizFirstAI.Octopus.Plugins;

public class ZendeskPlugin : IOctopusPlugin
{
    private readonly ILogger<ZendeskPlugin> _logger;
    private ZendeskClient? _client;

    public ZendeskPlugin(ILogger<ZendeskPlugin> logger)
        => _logger = logger;

    public void OnRegister(IServiceCollection services,
                           IOctopusConfig config)
    {
        services.Configure<ZendeskPluginConfig>(
            config.GetSection("ZendeskPlugin"));
        services.AddSingleton<IZendeskClient, ZendeskClient>();
    }

    public async Task OnStartAsync(IOctopusPluginContext context,
                                   CancellationToken ct)
    {
        var cfg    = context.Config.GetSection<ZendeskPluginConfig>("ZendeskPlugin");
        var token  = await context.CredentialResolver
                                  .GetPasswordAsync(cfg.CredentialId);

        _client = new ZendeskClient(cfg.Subdomain, cfg.Email, token);

        context.ToolRegistry.Register(ZendeskToolDefinitions.All,
                                      new ZendeskToolHandler(_client,
                                          context.TenantContext));

        _logger.LogInformation("ZendeskPlugin started for subdomain {Sub}",
                               cfg.Subdomain);
    }

    public Task OnStopAsync(CancellationToken ct)
    {
        _client?.Dispose();
        return Task.CompletedTask;
    }
}

Step 3: Define your tools

public static class ZendeskToolDefinitions
{
    public static IEnumerable<MCPTool> All =>
    [
        new MCPTool
        {
            Name        = "ticket_create",
            Description = "Create a new Zendesk support ticket. " +
                          "Returns the ticket ID and URL.",
            InputSchema = JsonDocument.Parse("""
            {
              "type": "object",
              "properties": {
                "subject":     { "type": "string",
                                 "description": "Ticket subject line" },
                "description": { "type": "string",
                                 "description": "Full ticket body" },
                "priority":    { "type": "string",
                                 "enum": ["low","normal","high","urgent"],
                                 "description": "Ticket priority" },
                "requester_email": { "type": "string", "format": "email",
                                     "description": "Email of the requester" }
              },
              "required": ["subject", "description"]
            }
            """)
        },
        new MCPTool
        {
            Name        = "ticket_search",
            Description = "Search Zendesk tickets by keyword or status.",
            InputSchema = JsonDocument.Parse("""
            {
              "type": "object",
              "properties": {
                "query":  { "type": "string",
                            "description": "Search query (Zendesk search syntax)" },
                "status": { "type": "string",
                            "enum": ["open","pending","solved","closed"],
                            "description": "Filter by status (optional)" }
              },
              "required": ["query"]
            }
            """)
        }
    ];
}

Step 4: Register in the host

// Program.cs in your Octopus host project
builder.Services.AddOctopus(octopus =>
{
    octopus.AddPlugin<SqlServerPlugin>();
    octopus.AddPlugin<SemanticKernelPlugin>();
    octopus.AddPlugin<ZendeskPlugin>();   // community plugin
});

Community vs First-Party: What's Different

AspectFirst-Party PluginCommunity Plugin
MaintenanceBizFirstAI core teamPlugin author / community
Security reviewFull internal review before releaseAuthor's responsibility
Version compatibilityGuaranteed across minor versionsAuthor must update on SDK breaks
DistributionBundled with Octopus SDKSeparate NuGet package
Support channelBizFirstAI support portalPlugin author's GitHub / community
Design principlesRequiredRequired (same rules apply)

Plugin Submission to the Community Registry

Once your community plugin is published on NuGet, you can submit it to the BizFirstAI community plugin registry so other operators can discover it:

  1. Publish your NuGet package with the tag octopus-plugin and a README describing its tools and configuration.
  2. Open a Community Plugin Submission thread on the community portal with your package name, tool list, and a link to your source repository.
  3. The community team verifies the package implements IOctopusPlugin correctly and adds it to the public registry listing.
  4. Include a SECURITY.md in your repository describing how you handle credentials and tenant isolation — this is a listing requirement.
Security is your responsibility. Community plugins are not vetted by BizFirstAI for security. Operators who install community plugins should review the source code, particularly credential handling and tenant isolation, before deploying to production.

Plugin SDK Versioning

SDK VersionOctopus VersionBreaking Changes
1.x1.0 – 1.xBaseline — IOctopusPlugin v1 interface
2.x (planned)2.0+Extended context in OnStartAsync; new ITelemetryContext
SDK stability commitment. The IOctopusPlugin interface is considered stable. Breaking changes require a major SDK version bump with a minimum 6-month deprecation window.