You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Raised by @shivchander in review of #1492: registering a plugin agent role makes it valid (usable in AgentNode.role, the CLI, serialization roundtrips), but not behaved — at run time the role still needs its prompt resolved from somewhere, and shipping and resolving that prompt is left entirely to the plugin.
#1492 landed the floor of that ask: the three-tier resolution contract is documented in docs/plugins.md, a load-time warning (plugin_agent_role_prompt_missing) catches roles with no resolvable prompt before any CEO cycle starts, and resolve_prompt's FileNotFoundError now hints at plugin packaging when the role is plugin-registered. This issue is the rest: a sanctioned way to register a role's prompt alongside the role, parallel to how register_agent_role() sanctioned the enum extension.
Today's contract (what a plugin must do manually)
Roles resolve through the three-tier lookup in factory/agents/runner.py:resolve_prompt:
A plugin role has no tier 3, so the plugin must ship a prompt file and install it to tier 2 on first load (typically copying from its package data into ~/.factory/agents/prompts/). This is easy to get wrong across install methods — the exact failure mode the load-time warning now catches is prompt data files not making it into the built wheel.
The open design question
Where does a plugin-registered prompt sit in the resolution order? Options:
A. A new tier just for plugin prompts.PluginRegistry grows something like add_agent_role_prompts({role: path_or_text}), and resolve_prompt consults it between project overrides and the user-global tier (project overrides keep winning, so users can always retune a plugin's agent). Pros: no filesystem side effects at registration; prompts version with the plugin. Cons: resolve_prompt becomes dependent on plugin load state.
B. Sanctioned installation to the existing user-global tier. A helper that copies a packaged prompt into ~/.factory/agents/prompts/<role>.md on first load, with the plugin's ownership recorded so re-installs upgrade it and uninstalls can clean up. Pros: no change to resolution order. Cons: a write to the user's home from library code, and the ownership/cleanup bookkeeping that comes with it.
C. Keep the contract as-is. The warnings from #1492 may be enough: the failure is loud and early, and the packaging fix (include the data files, install on first load) is a one-time plugin fix. Worth deciding after seeing whether downstream plugins keep tripping on it.
Whichever direction, midstream's lightwell is the reference consumer: it currently installs its 7 CVE-role prompts to ~/.factory/agents/prompts/ from data/prompts/ and would migrate to whatever API lands here.
Acceptance criteria
A plugin can register a role and its prompt in one place, in its register() function.
The prompt resolves without the plugin manually copying files at import time.
Project overrides still win over whatever the plugin registers (users can retune any agent).
Summary
Raised by @shivchander in review of #1492: registering a plugin agent role makes it valid (usable in
AgentNode.role, the CLI, serialization roundtrips), but not behaved — at run time the role still needs its prompt resolved from somewhere, and shipping and resolving that prompt is left entirely to the plugin.#1492 landed the floor of that ask: the three-tier resolution contract is documented in docs/plugins.md, a load-time warning (
plugin_agent_role_prompt_missing) catches roles with no resolvable prompt before any CEO cycle starts, andresolve_prompt'sFileNotFoundErrornow hints at plugin packaging when the role is plugin-registered. This issue is the rest: a sanctioned way to register a role's prompt alongside the role, parallel to howregister_agent_role()sanctioned the enum extension.Today's contract (what a plugin must do manually)
Roles resolve through the three-tier lookup in
factory/agents/runner.py:resolve_prompt:<project>/.factory/agents/<role>.md~/.factory/agents/prompts/<role>.mdfactory/agents/prompts/<role>.md(builtins only)A plugin role has no tier 3, so the plugin must ship a prompt file and install it to tier 2 on first load (typically copying from its package data into
~/.factory/agents/prompts/). This is easy to get wrong across install methods — the exact failure mode the load-time warning now catches is prompt data files not making it into the built wheel.The open design question
Where does a plugin-registered prompt sit in the resolution order? Options:
A. A new tier just for plugin prompts.
PluginRegistrygrows something likeadd_agent_role_prompts({role: path_or_text}), andresolve_promptconsults it between project overrides and the user-global tier (project overrides keep winning, so users can always retune a plugin's agent). Pros: no filesystem side effects at registration; prompts version with the plugin. Cons:resolve_promptbecomes dependent on plugin load state.B. Sanctioned installation to the existing user-global tier. A helper that copies a packaged prompt into
~/.factory/agents/prompts/<role>.mdon first load, with the plugin's ownership recorded so re-installs upgrade it and uninstalls can clean up. Pros: no change to resolution order. Cons: a write to the user's home from library code, and the ownership/cleanup bookkeeping that comes with it.C. Keep the contract as-is. The warnings from #1492 may be enough: the failure is loud and early, and the packaging fix (include the data files, install on first load) is a one-time plugin fix. Worth deciding after seeing whether downstream plugins keep tripping on it.
Whichever direction, midstream's lightwell is the reference consumer: it currently installs its 7 CVE-role prompts to
~/.factory/agents/prompts/fromdata/prompts/and would migrate to whatever API lands here.Acceptance criteria
register()function.~/.factory/agents/prompts/manually is unchanged.