docs: explain plugin config caller context

Document the optional ui, agent, and api caller context for plugin configuration hooks. Clarify the api default, backwards compatibility, explicit backend opt-in, and that caller context is not an authorization boundary.

Alessandro committed Aug 12, 2026 at 03:52 UTC 9cb6290aa9d4314015592b7668a0bcce7cacc356
2 files changed +50
plugins/README.md
+23
@@ -70,6 +70,29 @@ Plugins can also include an optional `hooks.py` at the plugin root. The framewor
70
71 In Docker, `hooks.py` normally affects `/opt/venv-a0`; the agent execution runtime is `/opt/venv`.
72
73 +### Configuration Hook Context
74 +
75 +Configuration hooks can distinguish why settings are being read or saved. Pass
76 +`caller="ui"` or `caller="agent"` to `get_plugin_config(...)` or
77 +`save_plugin_config(...)`; calls without it keep the compatible default,
78 +`"api"`.
79 +
80 +The hook receives this as `hook_context={"caller": ...}`:
81 +
82 +```python
83 +def get_plugin_config(default=None, hook_context=None, **kwargs):
84 + caller = (hook_context or {}).get("caller", "api")
85 + if caller == "ui":
86 + return redact_for_display(default)
87 + return default
88 +```
89 +
90 +Existing hooks need no change: hooks that ignore `hook_context`, including
91 +strict signatures without `**kwargs`, retain their previous behavior. Use the
92 +context only for behavior selection in plugin-controlled flows; it is not an
93 +authorization boundary. A `config.html` alone does not set the caller; the
94 +backend code loading or saving that configuration must pass it explicitly.
95 +
96 ## Plugin Index & Community Sharing
97
98 The **Plugin Index** at https://github.com/agent0ai/a0-plugins is the community-maintained registry of plugins available to all Agent Zero users.
skills/a0-create-plugin/SKILL.md
+27
@@ -177,6 +177,33 @@ save_plugin_config(
177 )
178 ```
179
180 +### Configuration Hook Caller Context
181 +
182 +Use caller context only when the same settings need different behavior for a
183 +known origin. An unlabeled call remains compatible and uses `"api"`; a
184 +plugin-controlled runtime path can opt in explicitly:
185 +
186 +```python
187 +settings = get_plugin_config("my-plugin", agent=agent, caller="agent") or {}
188 +```
189 +
190 +Its `hooks.py` receives `hook_context={"caller": ...}`. For example, a plugin
191 +can redact a stored credential for a UI-specific path while preserving its
192 +normal runtime configuration:
193 +
194 +```python
195 +def get_plugin_config(default=None, hook_context=None, **kwargs):
196 + caller = (hook_context or {}).get("caller", "api")
197 + return redact_for_display(default) if caller == "ui" else default
198 +```
199 +
200 +The available values are `"ui"`, `"agent"`, and `"api"`. Existing hooks do
201 +not need to change: the framework safely ignores this new argument for hooks
202 +that do not accept it. This is behavior metadata, never authorization; do not
203 +use it to grant or deny access to secrets or other protected data. A
204 +`config.html` alone does not set the caller; its backend load/save path must
205 +pass it explicitly.
206 +
207 ---
208
209 ## Directory Layout