Plugin Actions
Understand command, api, execute, and allowWhenDisabled in plugin actions
Plugin Actions
Plugin actions are the most direct explicit capability surface of a plugin.
An action is mainly built from:
allowWhenDisabledcommandapiexecute
The core layer is execute
Minimal example:
actions: {
status: {
execute: async ({ context }) => {
return {
success: true,
data: {
workspace_path: context.workspace_path,
},
};
},
},
}execute is responsible for:
- receiving structured payload
- running the business logic
- returning
success / data / error / message
When an action is called by a Session tool, its parameters also include the explicit execution_context for that Session Turn. It may be absent for direct CLI, HTTP, or scheduler calls. Use execution_context.workspace_env and execution_context.agent_systems for the effective Step configuration; context.workspace_env is the current Workspace snapshot and context.instructions contains Agent instructions.
command
command handles CLI-side mapping.
It is a good place to define:
- help text
- commander arguments and options
- how CLI input becomes structured payload
api
api handles HTTP-side input mapping.
It is a good place to define:
- method
- path
- how an HTTP request becomes structured payload
allowWhenDisabled
This is one of the easiest plugin-specific details to miss.
It means:
- this action is still allowed even if the plugin is currently disabled
Typical cases:
statusinstallconfiguremodels
In other words, the actions you often need precisely because the plugin is not yet fully usable.
Without allowWhenDisabled: true, normal actions on a disabled plugin are blocked.
What context does execute receive
Plugin action execution is designed around the PluginCommandContext shape.
Practically, you can think of it as:
- a stable minimal execution context for plugin work
It includes the current Agent id, project root, logger, and resolved env. Product configuration for a Plugin is passed by the upstream host when constructing the Plugin instance; actions do not read or persist it through their context.
A slightly fuller example
actions: {
use: {
allowWhenDisabled: true,
command: {
description: "switch the default provider",
mapInput({ args }) {
return {
provider: String(args[0] || ""),
};
},
},
execute: async ({ payload }) => {
const provider = String((payload as { provider?: unknown }).provider || "").trim();
if (!provider) {
return {
success: false,
error: "provider is required",
message: "provider is required",
};
}
return {
success: true,
data: { provider },
};
},
},
}