From 6049405aedc324c0c15a6bd787abc96706690c2c Mon Sep 17 00:00:00 2001 From: Aran Yogesh Date: Wed, 15 Apr 2026 15:18:14 -0700 Subject: [PATCH] feat: add configurable default prompt file for org-level agent instructions [close OPE-36] (#1187) * feat: add configurable default prompt file for org-level agent instructions * linting * Update CUSTOMIZATION.md Co-authored-by: Brace Sproul * fix: address PR review feedback on default prompt --------- Co-authored-by: Brace Sproul --- CUSTOMIZATION.md | 39 +++++++++++++++++++++++++++++++++++++++ agent/prompt.py | 41 +++++++++++++++++++++++++++++++++++++++-- default_prompt.md | 3 +++ 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 default_prompt.md diff --git a/CUSTOMIZATION.md b/CUSTOMIZATION.md index 22dbf84f..e500b4bc 100644 --- a/CUSTOMIZATION.md +++ b/CUSTOMIZATION.md @@ -385,6 +385,45 @@ The system prompt is assembled in `agent/prompt.py` from modular sections. You c | `CODE_REVIEW_GUIDELINES_SECTION` | How the agent reviews code changes | | `COMMUNICATION_SECTION` | Formatting and messaging guidelines | +### Default prompt file + +Open SWE supports a `default_prompt.md` file for org-level instructions that apply to **every** agent run, regardless of which repository is being worked on. This is the recommended way to set default repository preferences, org conventions, and shared guidelines. + +The file is loaded at agent startup and injected into the system prompt between the task overview and repository setup sections. + +**Location:** [`default_prompt.md`](./default_prompt.md) in the project root. + +**Override:** Set the `DEFAULT_PROMPT_PATH` environment variable to use a different file: + +```bash +DEFAULT_PROMPT_PATH="/path/to/my-org-prompt.md" +``` + +**Format:** Write plain markdown. The content is injected as-is under a `### Custom Instructions` heading in the system prompt. Example: + +```markdown +# Default Prompt + +## Default Repository + +When no repository is specified, work on the **my-app** repository under **my-org**. + +## Organization Conventions + +- Use conventional commits: feat:, fix:, chore: +- Always tag the requesting user when work is complete +``` + +**Loading order:** Default prompt → System prompt sections → AGENTS.md (per-repo). If the file is missing or empty, it is silently skipped — no error is raised. + +**When to use `default_prompt.md` vs `AGENTS.md`:** + +| | `default_prompt.md` | `AGENTS.md` | +|---|---|---| +| Scope | All tasks, all repos | Single repository | +| Location | Open SWE project root | Target repo root | +| Use for | Default repo, org conventions | Repo-specific coding standards | + ### Using AGENTS.md Drop an `AGENTS.md` file in the root of any repository to add repo-specific instructions. The agent reads it from the sandbox at startup and appends it to the system prompt. This is the easiest way to encode conventions per-repo without modifying Open SWE's code. diff --git a/agent/prompt.py b/agent/prompt.py index 22fd26de..744935f9 100644 --- a/agent/prompt.py +++ b/agent/prompt.py @@ -1,5 +1,39 @@ +import logging +import os +from pathlib import Path + from .utils.github_comments import UNTRUSTED_GITHUB_COMMENT_OPEN_TAG +logger = logging.getLogger(__name__) + +DEFAULT_PROMPT_PATH = os.environ.get( + "DEFAULT_PROMPT_PATH", + str(Path(__file__).resolve().parent.parent / "default_prompt.md"), +) + + +def _load_default_prompt() -> str: + """Load custom prompt from the default prompt file. + + Returns empty string if the file doesn't exist or can't be read. + """ + try: + path = Path(DEFAULT_PROMPT_PATH) + if path.is_file(): + content = path.read_text().strip() + if content: + # Escape curly braces so .format() doesn't choke on them + escaped = content.replace("{", "{{").replace("}", "}}") + return f"""--- + +### Custom Instructions + +{escaped}""" + except Exception: + logger.warning("Failed to read default prompt file at %s", DEFAULT_PROMPT_PATH) + return "" + + WORKING_ENV_SECTION = """--- ### Working Environment @@ -282,9 +316,10 @@ When you have completed your implementation, follow these steps in order: Always call `commit_and_open_pr` followed by the appropriate reply tool once implementation is complete and code quality checks pass.""" -SYSTEM_PROMPT = ( +SYSTEM_PROMPT_TEMPLATE = ( WORKING_ENV_SECTION + TASK_OVERVIEW_SECTION + + "{default_prompt_section}" + REPO_SETUP_SECTION + FILE_MANAGEMENT_SECTION + TASK_EXECUTION_SECTION @@ -305,8 +340,10 @@ def construct_system_prompt( linear_project_id: str = "", linear_issue_number: str = "", ) -> str: - return SYSTEM_PROMPT.format( + default_prompt_section = _load_default_prompt() + return SYSTEM_PROMPT_TEMPLATE.format( working_dir=working_dir, linear_project_id=linear_project_id or "", linear_issue_number=linear_issue_number or "", + default_prompt_section=default_prompt_section, ) diff --git a/default_prompt.md b/default_prompt.md new file mode 100644 index 00000000..c41fa5b8 --- /dev/null +++ b/default_prompt.md @@ -0,0 +1,3 @@ +# Default Prompt + +When a repository is not explicitly mentioned, use `langchain-ai/langchainplus`. Always assume the organization is `langchain-ai`.