Skip to content

Extending formae

formae is designed to be highly extensible. It uses a flexible yet simple plugin model to allow engineers to add support for technologies that aren't yet supported.

Policy

The following policy defines the architectural and licensing expectations for plugins.

Plugins are independent works developed and distributed separately from formae components.

Plugins execute as separate processes or remote services and communicate with formae components exclusively through documented public interfaces. Plugins are not loaded, linked, or executed in-process.

Plugin developers may license their plugins under any license of their choosing, including open-source or proprietary licenses. Such licenses apply only to the plugin itself and do not affect the licensing of formae components or other plugins.

Plugins must not impose license terms, usage restrictions, or distribution obligations on formae components, their source code, or their users beyond those explicitly agreed in writing.

No formae component is a derivative work of any plugin, and no plugin is a derivative work of any formae component.

Plugin SDK

The formae Plugin SDK lets you extend formae to manage any infrastructure that exposes any sort of an API. Plugins implement CRUD operations (Create, Read, Update, Delete) and discovery for resource types that formae doesn't support out of the box.

When to Build a Plugin

Build a plugin when you need formae to manage resources in a system it doesn't already support:

  • An infrastructure platform (SFTP servers, databases, message queues)
  • A SaaS platform with an API (monitoring tools, CI/CD systems, DNS providers)
  • Internal systems with custom APIs
  • Any system where resources have a lifecycle (create, modify, delete)

How Plugins Work

Plugins run as separate processes that communicate with the formae agent. When the agent starts, it discovers installed plugins and spawns them. Each plugin announces its capabilities (supported resource types, rate limits) and the agent routes operations to the appropriate plugin.

┌─────────────────────────┐      ┌─────────────────────────┐
│     formae agent        │      │    Your Plugin          │
│                         │      │                         │
│  • Discovers plugins    │ ───► │  • Announces types      │
│  • Routes requests      │      │  • Handles CRUD         │
│  • Enforces rate limits │ ◄─── │  • Returns results      │
└─────────────────────────┘      └─────────────────────────┘

This architecture provides:

  • Isolation - Plugin crashes don't affect the agent
  • Independent updates - Update plugins without updating formae
  • Simplicity - Your plugin just implements a Go interface

What You'll Build

After scaffolding a formae plugin project, you'll implement two things:

  1. Resource schemas (schema/pkl/*.pkl) - Define your resource types in PKL
  2. ResourcePlugin interface (plugin.go) - Implement CRUD operations and discovery
type ResourcePlugin interface {
    // Configuration
    RateLimit() RateLimitConfig
    LabelConfig() LabelConfig
    DiscoveryFilters() []MatchFilter

    // CRUD + Discovery
    Create(context.Context, *CreateRequest) (*CreateResult, error)
    Read(context.Context, *ReadRequest) (*ReadResult, error)
    Update(context.Context, *UpdateRequest) (*UpdateResult, error)
    Delete(context.Context, *DeleteRequest) (*DeleteResult, error)
    Status(context.Context, *StatusRequest) (*StatusResult, error)
    List(context.Context, *ListRequest) (*ListResult, error)
}

Prerequisites

Before building a plugin, you should be familiar with:

  • Go programming - Structs, interfaces, error handling, JSON marshaling
  • Your target system's API - How to authenticate and perform CRUD operations
  • PKL basics - For defining resource schemas (see PKL cheatsheet)

Getting Started

The Tutorial walks you through building a complete SFTP File plugin from scratch. You'll learn:

  1. How to scaffold a plugin project
  2. How to define resource schemas in PKL
  3. How to implement CRUD operations with proper error handling
  4. How to write tests using TDD
  5. How to run conformance tests in CI

For quick reference, see: