Understanding the Interface Section of plugin.json in OpenAI Plugins
The interface section in plugin.json serves as the contract between a plugin's metadata and the Codex runtime, controlling UI theming, capability declarations, and starter prompts while enabling the Composer to render plugin tiles and enforce security permissions.
The OpenAI Plugins repository defines the interface object within each plugin.json manifest as the single source of truth for how a plugin appears to users and what operations it advertises. This section bridges static plugin description with dynamic runtime behavior, driving everything from color schemes to capability gating.
What Is the Interface Section?
The interface object lives inside the plugin.json file located at plugins/<name>/.codex-plugin/plugin.json. It acts as the declarative contract that connects plugin metadata with both the Codex-Plugin runtime and the Composer UI components. According to the specification in .agents/skills/plugin-creator/references/plugin-json-spec.md, this section determines visual presentation, legal disclosures, and operational permissions.
Key Fields in the plugin.json Interface
Visual Branding and Icons
The branding fields control how the plugin appears in the Composer UI and Plugin Store:
brandColorandbrandColorDark: Hex color values theming the plugin tilecomposerIcon: Path to SVG/PNG assets displayed on the Composer toolbarlogoandlogoDark: Larger assets shown in plugin detail viewsscreenshots: Paths to PNG/SVG assets displayed in the store carousel
Capability Declarations
The capabilities array declares what operations the plugin can perform. Valid values include Read, Write, and Interactive. The runtime validates all incoming requests against these flags in plugins/plugin-eval/src/evaluators/plugin.js, preventing write operations on plugins that only declare Read access.
Starter Prompts and Descriptions
defaultPrompt: An array of starter messages (maximum 3 prompts, each ≤128 characters) displayed when users create new conversations with the pluginshortDescriptionandlongDescription: Text rendered in store listings and Composer detail panescategory: Human-readable grouping (e.g., Communication, Productivity) for store organization
Legal and External Links
privacyPolicyURL,termsOfServiceURL, andwebsiteURL: Required legal endpoints displayed to end-users before installation
How the Runtime Consumes the Interface Section
Manifest Loading and Validation
When a plugin installs, the Codex runtime loads plugins/<name>/.codex-plugin/plugin.json and executes validation logic in plugins/plugin-eval/src/evaluators/plugin.js. This validator checks that required fields exist and enforces the defaultPrompt constraints:
// Validation logic mirrors this implementation
function validateDefaultPrompt(iface) {
if (!Array.isArray(iface.defaultPrompt)) return false;
if (iface.defaultPrompt.length > 3) return false;
return iface.defaultPrompt.every(p => p.length <= 128);
}
Token Budget Estimation
The runtime uses defaultPrompt to reserve context window space. In plugins/plugin-eval/src/core/budget.js, the system concatenates the starter prompts and calls estimateTokenCount to calculate required allocations for new Composer conversations.
UI Rendering Pipeline
The Composer UI reads manifest.interface.* to:
- Paint plugin tiles using
brandColorandcomposerIcon - Display legal links and descriptions in detail views
- Render
defaultPromptstrings as clickable quick-start buttons
Capability Gating
Before executing any plugin action, the runtime checks manifest.interface.capabilities. A plugin declaring only "Read" receives an error when attempting write-oriented operations, enforcing the principle of least privilege.
Working with the Interface Section
Loading a Plugin Interface in JavaScript
import fs from 'fs';
import path from 'path';
function loadInterface(pluginName) {
const manifestPath = path.join(
__dirname,
'plugins',
pluginName,
'.codex-plugin',
'plugin.json'
);
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
return manifest.interface;
}
// Example usage
const zoomInterface = loadInterface('zoom');
console.log(zoomInterface.brandColor); // → "#0B5CFF"
console.log(zoomInterface.capabilities); // → ["Read", "Interactive"]
Enforcing defaultPrompt Constraints
function validateDefaultPrompt(iface) {
if (!Array.isArray(iface.defaultPrompt)) return false;
if (iface.defaultPrompt.length > 3) return false;
return iface.defaultPrompt.every(p => p.length <= 128);
}
if (!validateDefaultPrompt(zoomInterface)) {
throw new Error('defaultPrompt does not meet Codex requirements');
}
Rendering Starter Prompts in the UI
// React pseudo-code demonstrating Composer integration
function renderStarterPrompts(interface) {
return interface.defaultPrompt.map((prompt, i) => (
<button key={i} onClick={() => sendMessage(prompt)}>
{prompt}
</button>
));
}
Summary
- The
interfacesection inplugin.jsoncontrols both visual presentation and functional capabilities of OpenAI Plugins - Validation occurs in
plugins/plugin-eval/src/evaluators/plugin.js, enforcingdefaultPromptlimits (3 prompts max, 128 characters each) and verifying capability declarations - Token budgeting uses
defaultPromptcontent viaplugins/plugin-eval/src/core/budget.jsto manage context window allocation - Capability gating prevents unauthorized operations by matching runtime requests against declared
capabilities(Read/Write/Interactive) - UI components consume
brandColor,composerIcon, and description fields to render plugin tiles and detail views
Frequently Asked Questions
What happens if defaultPrompt exceeds 3 items or 128 characters?
The validator in plugins/plugin-eval/src/evaluators/plugin.js rejects the manifest during plugin installation. The runtime enforces these limits strictly to prevent token budget overflow and maintain UI consistency in the Composer's quick-start suggestions.
Can a plugin change its capabilities after installation?
No. The capabilities array is static and defined at build time in plugin.json. The runtime checks these flags before every operation, and modifying them requires repackaging and reinstalling the plugin with updated declarations.
Where does the Composer read the brand colors and icons?
The Composer UI reads manifest.interface.brandColor, manifest.interface.composerIcon, and related fields directly from the loaded manifest object. These values style the plugin tile in the toolbar and the detailed view in the Plugin Store.
How does the interface section relate to the rest of plugin.json?
While other sections of plugin.json define technical endpoints and authentication, the interface section specifically handles user-facing metadata. It remains the only portion read by both the UI rendering layer and the runtime security validator, making it the bridge between user experience and system enforcement.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →