Pluggable agent harness specification and registry (REQ-HARNESS-01).
A harness is a named persona: a plugin set plus pi.agent defaults. Three showcase harnesses
and one safety harness ship with Super-Pi-BEAM:
| Id | Module | Distinct because |
|---|---|---|
super-pi-code | SuperPi.Harness.Code | Mutates a repository, reversibly (checkpoints, optional auto-commit). |
super-pi-assistant | SuperPi.Harness.Assistant | Works with a human present, reaches the web and third-party services over MCP, has no filesystem. |
super-pi-librarian | SuperPi.Harness.Librarian | Runs with no human present (scheduler) and remembers across sessions (memory). |
super-pi-planner | SuperPi.Harness.Planner | Cannot write. |
The ids of earlier releases (super-pi-agent, -fast, -workspace, -auto, -interactive) still
resolve, to Code or Assistant, but list/0 no longer shows them.
Declaring a harness
defmodule MyApp.Harness.Triage do
alias SuperPi.Plugins
use SuperPi.Harness,
id: "my-triage",
name: "Triage",
description: "Sorts incoming tickets",
effort: "low",
mode: "accept-edits",
max_mode: "accept-edits",
workspace: %{"kind" => "none"},
tools: {:only, ["todo"]},
prompt: "You triage tickets.",
plugins: [Plugins.Todo, Plugins.Permissions]
endThe macro defines id/0, name/0, description/0, capabilities/0, extensions/1 and
agent_defaults/1, all overridable. Register the module with
config :super_pi, extra_harnesses: [MyApp.Harness.Triage].
| Option | Meaning |
|---|---|
:id, :name, :description | Required. Metadata for model listings and discovery. |
:plugins | Plugin specs (Module or {Module, opts}). Order matters for before_compact: the first plugin that does not answer :default ends the chain. |
:effort, :mode, :model | Defaults for pi.agent. See SuperPi.Harness.Defaults. |
:max_mode | Highest executionMode the harness allows ("plan", "accept-edits" or "auto"). Permissions enforces it. Defaults to :mode. |
:workspace | :local (default), :knowledge_paths or a "workspace" map such as %{"kind" => "none"}. |
:tools | :all, {:only, names} or {:except, names}. |
:prompt | Core system prompt. |
Summary
Callbacks
Default document configuration for the conversation agent
Machine-readable summary of the harness: id, plugins, tool loadout, workspace kind and modes.
Interfaces that must describe a harness to a client (ACP initialize, workspace.metadata,
GET /v1/models) call it through capabilities/1, which tolerates harnesses without it.
Short description for model listings and discovery
List of SuperPi.Extension modules active in this harness
Unique string identifier for the harness (e.g., 'super-pi-code')
Human-readable name
Functions
Capability summary of harness. A harness without capabilities/0 gets one built from its
metadata, so external :extra_harnesses modules keep working.
Default harness for entry points that receive no harness name (Gateway, RPC, MCP, CLI).
Strict form of resolve/1. An unknown name is an error, not a silent default.
Returns true if the given model name or ID corresponds to a registered harness.
Lists the harness modules to show to users: the four built-in ones and any configured via
:extra_harnesses. Resolution (resolve/1, harness?/1) is wider than this list: it also
accepts the ids of earlier releases.
Extensions of harness for a caller that is not the local user (Gateway, RPC, MCP, subagents).
Resolves a model name, alias, module, or harness ID to its corresponding Harness module.
Falls back to default/0 if unknown.
Callbacks
Default document configuration for the conversation agent
@callback capabilities() :: map()
Machine-readable summary of the harness: id, plugins, tool loadout, workspace kind and modes.
Interfaces that must describe a harness to a client (ACP initialize, workspace.metadata,
GET /v1/models) call it through capabilities/1, which tolerates harnesses without it.
@callback description() :: String.t()
Short description for model listings and discovery
List of SuperPi.Extension modules active in this harness
@callback id() :: String.t()
Unique string identifier for the harness (e.g., 'super-pi-code')
@callback name() :: String.t()
Human-readable name
Functions
Capability summary of harness. A harness without capabilities/0 gets one built from its
metadata, so external :extra_harnesses modules keep working.
@spec default() :: module()
Default harness for entry points that receive no harness name (Gateway, RPC, MCP, CLI).
Configure it with config :super_pi, default_harness: "<harness id>". The default is
super-pi-code, which carries the permission and safety plugins.
Strict form of resolve/1. An unknown name is an error, not a silent default.
A deployment that wants a fallback can set config :super_pi, fallback_harness: "<id>".
Returns true if the given model name or ID corresponds to a registered harness.
Lists the harness modules to show to users: the four built-in ones and any configured via
:extra_harnesses. Resolution (resolve/1, harness?/1) is wider than this list: it also
accepts the ids of earlier releases.
Extensions of harness for a caller that is not the local user (Gateway, RPC, MCP, subagents).
InlineBash runs !{...} shell commands from user input with no permission check, so a
remote caller must not get it. No built-in harness carries it, but a harness from :extra_harnesses may. Use this instead of harness.extensions([]) on those paths.
Resolves a model name, alias, module, or harness ID to its corresponding Harness module.
Falls back to default/0 if unknown.