Plugins [plugins]¶
Plugins are executable processes that extend cookie agent without loading code into the engine process. Install a plugin by obtaining its executable from its author and configuring the executable path. Plugin logs are written to the engine's standard error stream.
For SDK usage, extension hooks, event delivery, publishing, and protocol contracts, see Plugin development.
Configure and enable a plugin¶
Configure each plugin under [plugins.<name>] in user or workspace
config.toml. A workspace entry replaces a user entry with the same name.
The map defaults to empty. Names must be nonempty, at most 128 bytes, and contain
no control characters. The following is a complete illustrative config.toml;
the executable and working directory must exist when the engine starts.
[plugins.example]
command = "/opt/cookie-plugins/example"
args = ["--stdio"]
env = { EXAMPLE_MODE = "local" }
cwd = "/workspace"
enabled = true
producer_messaging = false
interception_timeout_ms = 2000
startup_timeout_ms = 10000
shutdown_grace_ms = 3000
tool_timeout_ms = 30000
command is required. args and env default to empty collections, enabled
defaults to true, and cwd is optional. All timeout values must be positive.
A disabled entry is not started but is still validated.
Plugin processes receive only the variables in env; the engine clears its
inherited environment, including PATH, before adding those configured values.
Configure PATH explicitly when the plugin itself needs it.
Each enabled plugin starts when the engine opens. Set enabled = false to keep
an installed plugin configured without starting it. Configuration changes take
effect when the engine next starts.
Producer messages¶
Plugins that send messages to the model must explicitly declare producer support.
Enable it only for trusted plugins with producer_messaging = true; this setting
defaults to false independently of plugin tool permissions. A plugin must register
for the destination session before sending. Registrations may outlive a turn and
must be explicitly closed by the plugin. There is no registration expiry.
Each message chooses steer (the next safe model request) or queue (a subsequent
run). Sending to an idle session can start a run. A successful send acknowledges
durable acceptance, not model execution or completion of an external action.
Retries use the plugin's stable message key; changing the configured plugin name
changes its durable deduplication identity.
A plugin can explicitly discard its own waiting message by session and message receipt, even after unregistering or reconnecting under the same configured name. The session actor durably claims a message before request preparation and hooks. That reservation removes the message from waiting, and discard rejects until the claim is released, even if no network request has been sent. A claim is not proof that the provider received or executed a request. After failed preparation or cancellation, releasing the claim may return an unconsumed message to waiting; consumed messages cannot return or be discarded. Repeated discard of an already discarded message is harmless. Discard does not close a producer registration, cancel a run, or undo effects of a message already delivered. A rejected discard does not establish exactly-once execution or external effects.
The old session-publishing API cannot authorize model-bound messages. Plugins using that API must migrate to explicit producer registration and sends. Ordinary observational bus publication is unaffected.
Allow plugin tools¶
Plugin tools remain hidden until the agent's policy or a session overlay has
any allow or ask rule for the plugin action; the gate is action-level and
does not match individual resource patterns. Calls still check the plugin's
declared permission and resource, and unmatched calls are denied. The plugin
author should document these names. For example:
The first rule allows issue_read for any primary resource; the second asks
before issue_delete. See Permissions for policy precedence
and session overrides.
Status and restart behavior¶
Plugin state progresses through disconnected, connecting, and connected,
or to failed with a diagnostic reason. A plugin failure does not stop the
engine or other plugins. Crashed plugins remain failed until the engine
restarts.
Producer readiness is tracked separately as starting, ready, failed, or
disabled, and is inspectable through session.producers. During startup the
plugin restores pending work from its own storage or external service and registers
fresh producer IDs before explicitly completing recovery. Recovery has no timeout;
an indefinitely starting plugin can hold goal continuations indefinitely.
Failed or disabled producer plugins leave external work unknown, not complete. The runtime surfaces recovery diagnostics and goal readiness remains blocked; neither state finishes goal checklist items. Accepted messages recover from the session log independently of plugin restoration. The engine cannot distinguish a plugin with no pending work from one that lost its own state, so restart recovery is only as complete as the plugin's own durable records.
During shutdown, the engine requests plugin shutdown, waits for the configured grace period, and then terminates the process if needed.
Accepted fields¶
Plugin definitions are layered by plugin name. A workspace definition replaces the complete same-name user definition without merging nested fields. The replacement keeps that user's position in authored order, which is also the interception order; workspace-only plugins append in workspace-authored order. Plugin authors can use the development guide for protocol and tool contracts.
| Key | Type | Default | Description |
|---|---|---|---|
command |
string | (required) | Plugin executable. |
args |
array of strings | empty | Command arguments. |
env |
map of strings | empty | Complete child environment; inherited variables are cleared. |
cwd |
string | (none) | Child working directory. |
enabled |
boolean | true |
Whether the plugin starts with the engine. |
producer_messaging |
boolean | false |
Opt in to the producer messaging protocol capability, allowing the plugin to register producers and send model-bound messages. |
interception_timeout_ms |
integer | 2000 |
Positive timeout for interception requests. |
startup_timeout_ms |
integer | 10000 |
Positive timeout for initialization. |
shutdown_grace_ms |
integer | 3000 |
Positive graceful shutdown period before termination. |
tool_timeout_ms |
integer | 30000 |
Positive timeout for each plugin tool call. |
Plugin entries reject unknown fields. command must be present and nonempty,
cwd must be nonempty when set, and every timeout must be greater than zero.
These rules apply even when enabled = false; disabling an entry prevents
startup but does not bypass configuration validation.
The child receives only the variables in env. It does not inherit the
engine's environment, including PATH; use an absolute command and configure
PATH explicitly when the executable or its children need it.
Plugin commands are trusted local code, not a sandbox. Review workspace plugin configuration before opening the workspace. Tool permissions do not prevent configured startup or independently authorize interception hooks. See security boundaries.