How to Implement Read/Write/Interactive Capabilities in OpenAI Codex Plugins
To implement Read/Write/Interactive capabilities in plugins, declare the required permissions in the capabilities array of your .codex-plugin/plugin.json manifest and enforce them at runtime using the ensureCapability() function from @openai/plugin-runtime.
Implementing Read/Write/Interactive capabilities in plugins requires understanding the permission model defined in the openai/plugins repository. These three capability types control whether a Codex plugin can retrieve data, modify resources, or prompt users for additional input during execution.
Understanding the Three Capability Types
The Codex runtime recognizes three distinct permission levels that govern what actions a plugin can perform on external services.
Read Capability
The Read capability grants a plugin permission to retrieve data without mutating resources. This is the most restrictive permission level, suitable for operations like fetching calendar events, reading documents, or pulling analytics data. When you implement Read/Write/Interactive capabilities in plugins that only retrieve information, declare only ["Read"] in your manifest.
Write Capability
The Write capability allows a plugin to create, update, or delete resources on the target service. Any skill that adds spreadsheet rows, creates tickets, or uploads files requires this permission. The runtime strictly enforces that mutations cannot occur without an explicit Write declaration in the manifest.
Interactive Capability
The Interactive capability enables a plugin to prompt users for additional input during a session, such as requesting confirmation before a write operation or presenting UI widgets. This capability is required for any skill that needs user interaction beyond the initial prompt.
Declaring Capabilities in the Plugin Manifest
The capabilities array resides in the interface object of your .codex-plugin/plugin.json file. The Codex runtime parses this manifest to determine which operations a plugin may perform.
For example, the minimal-plugin fixture declares both Interactive and Write capabilities in plugins/plugin-eval/fixtures/minimal-plugin/.codex-plugin/plugin.json:
{
"interface": {
"capabilities": ["Interactive", "Write"]
}
}
Production plugins follow similar patterns. The Twilio developer-kit plugin, located at plugins/twilio-developer-kit/.codex-plugin/plugin.json, lists Read and Write capabilities:
{
"interface": {
"capabilities": ["Read", "Write"]
}
}
Enforcing Capabilities at Runtime
The Codex runtime automatically blocks any operation that exceeds the declared capabilities. To implement Read/Write/Interactive capabilities in plugins safely, use the ensureCapability() function to explicitly check permissions before executing sensitive operations.
Write Operations
Before creating or modifying resources, verify the Write capability:
// src/skills/updateRecord.ts
import { ensureCapability } from "@openai/plugin-runtime";
export async function updateRecord(id: string, payload: Record<string, any>) {
// Runtime rejects this call if the plugin lacks Write
await ensureCapability("Write");
const result = await myServiceApi.put(`/records/${id}`, payload);
return result;
}
Read Operations
For read-only operations, enforce the Read capability:
// src/skills/getRecord.ts
import { ensureCapability } from "@openai/plugin-runtime";
export async function getRecord(id: string) {
await ensureCapability("Read");
const data = await myServiceApi.get(`/records/${id}`);
return data;
}
Interactive Workflows
When requiring user confirmation, check for the Interactive capability:
// src/skills/updateRecord.ts
import { ensureCapability } from "@openai/plugin-runtime";
export async function updateRecord(id: string, payload: Record<string, any>) {
await ensureCapability("Write");
// Optional interactive confirmation
if (await ensureCapability("Interactive")) {
const confirmed = await askUser(`Overwrite record ${id}?`);
if (!confirmed) return { status: "cancelled" };
}
const result = await myServiceApi.put(`/records/${id}`, payload);
return result;
}
Capability Design Best Practices
When you implement Read/Write/Interactive capabilities in plugins according to the openai/plugins source code, follow these principles:
- Request minimal permissions: Only declare capabilities your plugin actually needs. The principle of least privilege reduces security risk and user friction.
- Separate read and write skills: Design read-only skills that can be reused across plugins without requiring Write permissions.
- Use Interactive sparingly: Mark Interactive only when skills truly require user input during execution, as unnecessary prompts increase friction.
- Document capabilities: Include capability requirements in your skill's README, as demonstrated in
plugins/zoom/skills/zoom-apps-sdk/SKILL.md, so downstream developers understand the permission model.
Summary
- Declare Read, Write, and Interactive capabilities in the
capabilitiesarray of.codex-plugin/plugin.json. - The minimal-plugin fixture at
plugins/plugin-eval/fixtures/minimal-plugin/.codex-plugin/plugin.jsondemonstrates Interactive and Write declarations. - The Twilio plugin at
plugins/twilio-developer-kit/.codex-plugin/plugin.jsonshows Read and Write combinations. - Enforce capabilities at runtime using
ensureCapability()from@openai/plugin-runtime. - Always validate Write permissions before mutations and Interactive permissions before user prompts.
- Follow the principle of least privilege by requesting only necessary capabilities.
Frequently Asked Questions
What happens if a plugin attempts a write without the Write capability?
The Codex runtime blocks the operation and returns a "capability missing" error. The ensureCapability("Write") call will fail before your code executes the API request, preventing unauthorized mutations.
Can a plugin declare all three capabilities simultaneously?
Yes. You can declare "capabilities": ["Read", "Write", "Interactive"] in your manifest if your plugin requires all permission types. However, best practices recommend declaring only the minimal set needed for your specific use case.
Where is the capability enforcement logic implemented in the openai/plugins repository?
The enforcement logic is built into the core plugin framework within the generic plugin loader in plugins/**/.codex-plugin/. While the runtime handles checks automatically, the explicit ensureCapability() calls in your skills make the requirements transparent in logs and error messages.
How do I implement user confirmation prompts in a skill?
To create an interactive skill, first declare "Interactive" in your .codex-plugin/plugin.json capabilities array. Then use await ensureCapability("Interactive") in your skill code to verify you can prompt the user, followed by functions like askUser() to request confirmation or additional input.
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 →