Skip to content

Sanctioned way to register a plugin agent role's prompt alongside the role #1497

Description

@lambdabaa

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, 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:

  1. Project override: <project>/.factory/agents/<role>.md
  2. User-global: ~/.factory/agents/prompts/<role>.md
  3. Factory default: factory/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. 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).
  • The load-time warning from feat: sanctioned AgentRole extension for plugin agent roles #1492 becomes unreachable for plugins using the new API (registering a prompt alongside the role satisfies the check by construction).
  • Behavior for plugins that keep installing to ~/.factory/agents/prompts/ manually is unchanged.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions