home / skills / lookatitude / beluga-ai / go-interfaces

go-interfaces skill

/.claude/skills/go-interfaces

This skill helps design Go interfaces with registry, middleware, and hooks for Beluga AI v2, enabling extensible contracts and runtime customization.

npx playbooks add skill lookatitude/beluga-ai --skill go-interfaces

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
1.7 KB
---
name: go-interfaces
description: Go interface design with registry, middleware, and hooks for Beluga AI v2. Use when creating interfaces, extension contracts, or adding hooks/middleware.
---

# Go Interface Design

## Extension Contract (4 parts)

### 1. Interface (small, 1-4 methods)

```go
type ChatModel interface {
    Generate(ctx context.Context, msgs []schema.Message, opts ...GenerateOption) (*schema.AIMessage, error)
    Stream(ctx context.Context, msgs []schema.Message, opts ...GenerateOption) iter.Seq2[schema.StreamChunk, error]
    BindTools(tools []tool.Tool) ChatModel
    ModelID() string
}
```

### 2. Hooks (all fields optional, nil = skip)

```go
type Hooks struct {
    BeforeGenerate func(ctx context.Context, msgs []schema.Message) (context.Context, []schema.Message, error)
    AfterGenerate  func(ctx context.Context, resp *schema.AIMessage, err error) (*schema.AIMessage, error)
    OnError        func(ctx context.Context, err error) error
}
func ComposeHooks(hooks ...Hooks) Hooks { /* chain: each receives output of previous */ }
```

### 3. Middleware: `func(T) T`

```go
type Middleware func(ChatModel) ChatModel
func ApplyMiddleware(model ChatModel, mws ...Middleware) ChatModel {
    for i := len(mws) - 1; i >= 0; i-- { model = mws[i](model) }
    return model
}
```

### 4. Registry

See `go-framework` skill.

## Rules

- Accept interfaces, return structs.
- If interface > 4 methods, split it.
- Optional capabilities via type assertion: `if br, ok := r.(BatchRetriever); ok { ... }`
- Embed for composition: `type MyAgent struct { agent.BaseAgent; ... }`
- Hook naming: `Before<Action>` (modify input), `After<Action>` (modify output), `On<Event>` (observe/modify).
- Middleware applies first (outermost), hooks fire within execution.

Overview

This skill describes a compact Go interface design pattern for AI models, with a small interface, optional hooks, composable middleware, and a registry approach. It helps you build extensible, testable model adapters and agent components for Beluga AI v2 while keeping implementations minimal and orthogonal.

How this skill works

Define a small interface (1–4 methods) that accepts interfaces and returns concrete structs. Provide optional Hooks where nil fields are skipped, allowing pre/post processing and error observation. Wrap models with Middleware functions of type func(ChatModel) ChatModel that compose outer-to-inner. Register implementations in a registry for discovery and optional capability checks via type assertions.

When to use it

  • Creating adapter implementations for different LLM providers while keeping a stable contract.
  • Adding cross-cutting behavior (logging, metrics, retries) without changing model code via middleware.
  • Injecting request/response transformations or validation using Before*/After* hooks.
  • Designing agents or extensions that need optional capabilities discoverable by type assertion.
  • Composing features into agents via embedding and small focused interfaces.

Best practices

  • Keep interfaces tiny (1–4 methods); split larger interfaces into capability-specific sub-interfaces.
  • Accept interfaces in function signatures and return concrete structs to preserve implementation flexibility.
  • Name hooks with Before<Action>, After<Action>, and On<Event> to clarify intent and data flow.
  • Apply middleware outer-to-inner and ensure side effects are idempotent or context-aware.
  • Use type assertions for optional capabilities instead of bloating the primary interface.
  • Embed structs for composition (e.g., type MyAgent struct { BaseAgent; ... }) to reuse behavior.

Example use cases

  • Wrap a ChatModel with middleware that records latency and emits metrics without touching model code.
  • Compose hooks to sanitize inputs (BeforeGenerate) and redact outputs (AfterGenerate) across providers.
  • Register multiple model implementations and select one at runtime via a registry lookup.
  • Add a batching retriever as an optional capability and detect it with a type assertion.
  • Layer retry and backoff middleware around a Stream method to handle transient provider errors.

FAQ

Why keep interfaces small?

Small interfaces enforce separation of concerns, make mocking and testing easier, and allow optional features via additional sub-interfaces and type assertions.

How do middleware and hooks interact?

Middleware wraps the model call outer-to-inner. Within execution, hooks run: Before* can modify inputs, After* can modify outputs, and On* observes errors. ComposeHooks chains hooks so each receives the prior output.