Technique plugins¶
Technique plugins let you extend how OVI-CODE handles a task without forking or rebuilding the application. Each plugin is a native C++ dynamic library loaded at process startup through a versioned, dependency-free C ABI. It appears in setup, Settings, and the T technique cycle without linking against OVI-CODE internals.
A plugin controls an agent turn while the host supplies the configured provider, the existing ReAct/tool loop, and the conversation transcript. You can start with a small prompt customization or build a multi-pass workflow with its own settings and stopping criteria.
Plugins execute native code
A plugin has the same operating-system permissions as OVI-CODE. It is not sandboxed. Install only plugins whose source and publisher you trust.
What you can extend¶
| Capability | How a plugin uses it | Example custom workflow |
|---|---|---|
| Task instructions | Extend host->base_system_prompt before calling host->run_react |
A code review guided by your team's conventions |
| Turn orchestration | Run multiple ReAct passes and inspect host->last_assistant_text between them |
An implementation pass followed by critique and refinement |
| User-facing options | Declare typed V2 parameters and read them through host->get_parameter |
Configurable review depth, extra instructions, or pass count |
| Progress reporting | Write System or Error entries with host->emit |
Explain which workflow stage is running |
These are examples you can implement, not additional bundled techniques. Plugins reuse the selected provider and host workspace tools rather than requiring separate model-client or tool implementations.
The current public ABI extends agentic techniques; it does not provide a registry for adding providers, workspace tools, or TUI panels. The workspace sandbox applies to the host's file tools, not to a plugin's own native code.
Bundled example¶
OVI-CODE ships with the Deliberate example plugin. It is installed and loaded automatically, and fresh configurations select it as the default technique so you can see a plugin working immediately. Existing configurations keep their saved technique.
Deliberate adds explicit hypothesis and verification instructions before a normal ReAct pass. Its Verification depth and Show start message options are available under Settings → Plugins. You can select another technique at any time under Settings → Agent or by pressing T in chat Normal mode.
Discover plugins¶
Without an override, OVI-CODE searches:
- The
pluginsdirectory beside the executable. Source builds and portable release archives keep the bundled Deliberate module here. <install-prefix>/lib/ovi-code/pluginsfor CMake prefix installs.~/.ovi-code/pluginsfor plugins installed by the user.
Use a flag or environment variable to replace that search list with one directory. This also disables the bundled example for that run unless it is in the selected directory:
List loaded modules and loader errors without opening the TUI:
OVI-CODE loads .dylib and .so files once at startup. Restart after adding or
rebuilding a plugin.
Install and use a plugin¶
- Obtain or build a trusted plugin for your operating system and CPU
architecture. Put its
.dylibor.sofile in~/.ovi-code/plugins, creating the directory if needed, or use a directory from the search list above. - Run
ovi-code pluginsto check that the module loads and resolve any reported errors. - Start or restart OVI-CODE. Select the plugin during setup, under Settings → Agent, or with T in chat Normal mode.
- If the plugin declares options, customize them under Settings → Plugins. Values are saved per plugin and supplied to it during each turn.
Build the bundled example¶
The repository includes plugins/examples/deliberate.cpp, built by default:
The build-tree plugin directory is discovered automatically. Set
-DOVI_CODE_BUILD_EXAMPLE_PLUGINS=OFF when configuring CMake to omit the
example from both the build and installation.
Write a plugin¶
Plugins include the dependency-free public ABI header. Use the V2 descriptor to declare settings that appear under Settings → Plugins:
#include "ovicode/technique_plugin.h"
#include <string>
namespace {
int runTurn(void*, const OviCodeTechniqueHostV2* host,
const char* user_input) {
if (!host || !host->run_react || !user_input) return 0;
std::string system = host->base_system_prompt;
system += "\n\nCheck assumptions before every tool call.";
return host->run_react(host->context, system.c_str(), user_input);
}
const char* const modes[] = {"quick", "careful"};
const OviCodePluginParameterV2 parameters[] = {
{"mode", "Verification mode", "How thoroughly to check assumptions.",
OVI_CODE_PLUGIN_PARAMETER_CHOICE, "quick", modes, 2},
{"notes", "Extra instructions", "Additional text added to the prompt.",
OVI_CODE_PLUGIN_PARAMETER_STRING, "", nullptr, 0},
};
const OviCodeTechniquePluginV2 plugin{
OVI_CODE_TECHNIQUE_PLUGIN_API_VERSION_V2,
"verify-first",
"Verify First",
"Checks assumptions before acting",
parameters,
2,
nullptr,
nullptr,
runTurn,
};
} // namespace
extern "C" const OviCodeTechniquePluginV2*
ovi_code_get_technique_plugin_v2() {
return &plugin;
}
Plugin IDs must start with a lowercase letter or digit and contain only
lowercase letters, digits, ., _, or -. They must not duplicate another
plugin or built-in technique ID.
V1 plugins remain supported and continue exporting
ovi_code_get_technique_plugin_v1, but only V2 plugins can declare settings.
Define settings¶
Each V2 parameter has a stable key, user-facing label and description, a
type, and a default value. Supported types are STRING, SECRET, INTEGER,
NUMBER, BOOLEAN, and CHOICE. Choice parameters also provide an array of
accepted values. Keys follow the same character rules as plugin IDs and must be
unique within the plugin.
Values are stored per plugin in ~/.ovi-code/config.json. Read the effective
value during a turn with host->get_parameter:
const char* mode = host->get_parameter(host->context, "mode");
if (mode && std::string(mode) == "careful") {
// Enable the plugin's more thorough behavior.
}
The host validates values and falls back to the declared default if a manually
edited configuration contains an invalid value. Returned pointers remain valid
until run_turn returns. Secret parameters are masked in Settings, but are
stored in the same user-readable configuration file as provider keys.
Design a multi-pass workflow¶
A technique can do more than prepend instructions. For a review-and-refine plugin, for example:
- Start with
host->base_system_promptto retain the project's instructions. - Call
host->run_reactwith the user's request and your implementation instructions. - Read
host->last_assistant_text, then request another pass with review or refinement instructions when needed. - Stop when your completion criteria are met or the pass budget is exhausted.
Settings → Agent → Plugin passes caps the number of host ReAct passes a
plugin can request in one turn; host->iteration_limit exposes that budget.
Each pass also uses the configured tool-call limit. Respect failed callback
returns: run_react returns 0 on an error or cancellation, and emit returns
0 when the turn has been cancelled. Return control rather than continuing the
workflow after either failure.
Copy any assistant text you need to keep before the next run_react call,
because that call can invalidate the pointer returned by
last_assistant_text.
Runtime interface¶
| Field or callback | Purpose |
|---|---|
id, label, description |
Metadata shown and persisted by OVI-CODE |
create / destroy |
Optional process-lifetime plugin state |
run_turn |
Entry point for each user turn |
host->workspace |
Absolute active workspace path |
host->base_system_prompt |
Standard prompt plus project instructions |
host->run_react |
Run one complete model/tool pass |
host->last_assistant_text |
Inspect the latest assistant response |
host->emit |
Write System or Error transcript entries |
host->iteration_limit |
Maximum host-enforced passes for the turn |
host->get_parameter |
Read a V2 plugin setting or its default |
Pointers supplied by the host are valid only during run_turn; copy data that
must be retained. Never allow C++ exceptions to cross the exported C ABI.
See the exact declarations in
technique_plugin.h.