Skip to content

feat(gastown): Custom per-role prompt instructions in town settings #1794

@jrf0110

Description

@jrf0110

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 test before calling gt_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_instructions field 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 Instructions section 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Should fix before soft launchenhancementNew feature or requestgt:containerContainer management, agent processes, SDK, heartbeatgt:coreReconciler, state machine, bead lifecycle, convoy flowgt:uiDashboard, settings, terminal, drawers

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions