-
Notifications
You must be signed in to change notification settings - Fork 26
feat(gastown): Custom per-role prompt instructions in town settings #1794
Description
Summary
Allow users to add custom instructions to each agent role's system prompt via town settings. This lets users tailor agent behavior to their specific repo conventions, CI setup, and workflow preferences without modifying the gastown codebase.
Motivation
Real example: the Kilo cloud repo has a resource-intensive pre-push hook that jams up polecat agents. The user wants to tell polecats to git push --no-verify and tell the refinery to fix any linting errors it finds. Today there is no way to inject these instructions — the system prompts are hardcoded.
Other use cases:
- Tell polecats to always run
pnpm testbefore callinggt_done - Tell the refinery to be lenient on style nits and focus on correctness
- Tell the mayor to always suggest convoys instead of standalone beads
- Tell polecats to use a specific test framework or coding convention
- Tell the refinery to always create PRs (never direct merge)
- Repo-specific instructions: "This is a monorepo, always run tests from the package root"
Design
Town Config
// townConfig
custom_instructions?: {
polecat?: string; // Appended to polecat system prompt
refinery?: string; // Appended to refinery system prompt
mayor?: string; // Appended to mayor system prompt
};Each field is a free-text string (up to ~2000 chars) that gets appended to the role's system prompt as a dedicated section:
## Custom Instructions (from town settings)
<user's custom text here>
When the field is empty/null, nothing is appended (no empty section header).
Settings UI
Add a "Custom Instructions" section to town settings (below Agent Defaults, above Danger Zone):
Custom Instructions
Customize the system prompt for each agent role. These instructions
are appended to the default prompt and apply to all agents of that role.
Polecat Instructions
┌─────────────────────────────────────────────────────┐
│ Always push with --no-verify to skip the pre-push │
│ hook. Run `pnpm run lint` manually before calling │
│ gt_done to catch any issues. │
└─────────────────────────────────────────────────────┘
Refinery Instructions
┌─────────────────────────────────────────────────────┐
│ Fix any linting errors you find during review rather │
│ than requesting rework. Push the fix directly. │
└─────────────────────────────────────────────────────┘
Mayor Instructions
┌─────────────────────────────────────────────────────┐
│ │
└─────────────────────────────────────────────────────┘
Each textarea with a character counter (e.g., "142 / 2000"). Saved alongside other town config via the existing updateTownConfig mutation.
Prompt Injection
When building the agent's system prompt (in container/src/agent-runner.ts or the gastown context block injected by the container plugin), append the custom instructions if present:
const customInstructions = townConfig.custom_instructions?.[agent.role];
if (customInstructions?.trim()) {
systemPrompt += `\n\n## Custom Instructions (from town settings)\n\n${customInstructions}`;
}The custom instructions are injected AFTER the standard system prompt sections (role description, gastown context, convoy context, discovery docs) so they can override or supplement the defaults. They appear as the last section before the conversation begins.
Propagation
Custom instructions are part of townConfig, which is already passed to the container via X-Town-Config header and syncConfigToContainer. When instructions change:
- Polecats/refineries: Take effect on the next dispatch (new session gets the updated prompt). No restart needed.
- Mayor: Takes effect on the next session restart (model change, token refresh, or container restart). Could also be picked up on the next message if the prompt is rebuilt per-message — check how the mayor's gastown context injection works.
Scrollspy Nav
Add "Custom Instructions" to the SECTIONS array for the settings sidebar nav:
{ id: "custom-instructions", label: "Custom Instructions", icon: MessageSquareText }Acceptance Criteria
-
custom_instructionsfield added to town config schema (optional, backward compatible) - Settings UI shows per-role textarea inputs with character counter
- Custom instructions appended to the system prompt for the corresponding role
- Instructions appear as a
## Custom Instructionssection at the end of the prompt - Empty instructions do not inject anything (no empty section)
- Changes take effect on next agent dispatch (polecats/refineries) or session restart (mayor)
- Character limit enforced (2000 chars per role)
- Section appears in the settings scrollspy nav
References
- feat(gastown): Per-role model configuration in town settings — mayor, refinery, polecat #1512 — Per-role model configuration (similar per-role settings pattern)
- fix(gastown): Changing default model in town settings does not update the mayor'\''s running session #1438 — Mayor session restart on config change (propagation mechanism)
container/src/agent-runner.ts—buildKiloConfigContent, prompt assemblycontainer/plugin/— gastown context injection into agent sessions