mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-04 21:52:14 +00:00
Merge pull request #970 from langchain-ai/yogesh/support-agents.md
feat: inject AGENTS.md into system prompt
This commit is contained in:
commit
8297c61fe1
3 changed files with 53 additions and 1 deletions
|
|
@ -4,6 +4,7 @@ You are operating in a **remote Linux sandbox** at `{working_dir}`.
|
||||||
|
|
||||||
All code execution and file operations happen in this sandbox environment.
|
All code execution and file operations happen in this sandbox environment.
|
||||||
|
|
||||||
|
{agents_md_section}
|
||||||
|
|
||||||
**Important:**
|
**Important:**
|
||||||
- Use `{working_dir}` as your working directory for all operations
|
- Use `{working_dir}` as your working directory for all operations
|
||||||
|
|
@ -72,9 +73,20 @@ def construct_system_prompt(
|
||||||
working_dir: str,
|
working_dir: str,
|
||||||
linear_project_id: str = "",
|
linear_project_id: str = "",
|
||||||
linear_issue_number: str = "",
|
linear_issue_number: str = "",
|
||||||
|
agents_md: str = "",
|
||||||
) -> str:
|
) -> str:
|
||||||
|
agents_md_section = ""
|
||||||
|
if agents_md:
|
||||||
|
agents_md_section = (
|
||||||
|
"\nThe following text is pulled from the repository's AGENTS.md file. "
|
||||||
|
"It may contain specific instructions and guidelines for the agent.\n"
|
||||||
|
"<agents_md>\n"
|
||||||
|
f"{agents_md}\n"
|
||||||
|
"</agents_md>\n"
|
||||||
|
)
|
||||||
return SYSTEM_PROMPT.format(
|
return SYSTEM_PROMPT.format(
|
||||||
working_dir=working_dir,
|
working_dir=working_dir,
|
||||||
linear_project_id=linear_project_id or "<PROJECT_ID>",
|
linear_project_id=linear_project_id or "<PROJECT_ID>",
|
||||||
linear_issue_number=linear_issue_number or "<ISSUE_NUMBER>",
|
linear_issue_number=linear_issue_number or "<ISSUE_NUMBER>",
|
||||||
|
agents_md_section=agents_md_section,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ SANDBOX_CREATING = "__creating__"
|
||||||
SANDBOX_CREATION_TIMEOUT = 180
|
SANDBOX_CREATION_TIMEOUT = 180
|
||||||
SANDBOX_POLL_INTERVAL = 1.0
|
SANDBOX_POLL_INTERVAL = 1.0
|
||||||
|
|
||||||
|
from .utils.agents_md import read_agents_md_in_sandbox
|
||||||
from .utils.github import (
|
from .utils.github import (
|
||||||
git_has_uncommitted_changes,
|
git_has_uncommitted_changes,
|
||||||
is_valid_git_repo,
|
is_valid_git_repo,
|
||||||
|
|
@ -215,7 +216,6 @@ async def get_agent(config: RunnableConfig) -> Pregel: # noqa: PLR0915
|
||||||
encrypted_token = config["configurable"].get("github_token_encrypted")
|
encrypted_token = config["configurable"].get("github_token_encrypted")
|
||||||
if encrypted_token:
|
if encrypted_token:
|
||||||
github_token = decrypt_token(encrypted_token)
|
github_token = decrypt_token(encrypted_token)
|
||||||
logger.debug("Decrypted GitHub token")
|
|
||||||
|
|
||||||
if thread_id is None or not graph_loaded_for_execution(config):
|
if thread_id is None or not graph_loaded_for_execution(config):
|
||||||
logger.info("No thread_id or not for execution, returning agent without sandbox")
|
logger.info("No thread_id or not for execution, returning agent without sandbox")
|
||||||
|
|
@ -324,9 +324,14 @@ async def get_agent(config: RunnableConfig) -> Pregel: # noqa: PLR0915
|
||||||
|
|
||||||
SANDBOX_BACKENDS[thread_id] = sandbox_backend
|
SANDBOX_BACKENDS[thread_id] = sandbox_backend
|
||||||
|
|
||||||
|
if not repo_dir:
|
||||||
|
msg = "Cannot proceed: no repo was cloned. Set 'repo.owner' and 'repo.name' in the configurable config"
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
linear_issue = config["configurable"].get("linear_issue", {})
|
linear_issue = config["configurable"].get("linear_issue", {})
|
||||||
linear_project_id = linear_issue.get("linear_project_id", "")
|
linear_project_id = linear_issue.get("linear_project_id", "")
|
||||||
linear_issue_number = linear_issue.get("linear_issue_number", "")
|
linear_issue_number = linear_issue.get("linear_issue_number", "")
|
||||||
|
agents_md = await read_agents_md_in_sandbox(sandbox_backend, repo_dir)
|
||||||
|
|
||||||
logger.info("Returning agent with sandbox for thread %s", thread_id)
|
logger.info("Returning agent with sandbox for thread %s", thread_id)
|
||||||
return create_deep_agent(
|
return create_deep_agent(
|
||||||
|
|
@ -335,6 +340,7 @@ async def get_agent(config: RunnableConfig) -> Pregel: # noqa: PLR0915
|
||||||
repo_dir,
|
repo_dir,
|
||||||
linear_project_id=linear_project_id,
|
linear_project_id=linear_project_id,
|
||||||
linear_issue_number=linear_issue_number,
|
linear_issue_number=linear_issue_number,
|
||||||
|
agents_md=agents_md,
|
||||||
),
|
),
|
||||||
tools=[http_request, fetch_url, commit_and_open_pr],
|
tools=[http_request, fetch_url, commit_and_open_pr],
|
||||||
backend=sandbox_backend,
|
backend=sandbox_backend,
|
||||||
|
|
|
||||||
34
apps/agent/agent/utils/agents_md.py
Normal file
34
apps/agent/agent/utils/agents_md.py
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
"""Helpers for reading agent instructions from AGENTS.md."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import shlex
|
||||||
|
|
||||||
|
from deepagents.backends.protocol import SandboxBackendProtocol
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
async def read_agents_md_in_sandbox(
|
||||||
|
sandbox_backend: SandboxBackendProtocol,
|
||||||
|
repo_dir: str | None,
|
||||||
|
) -> str | None:
|
||||||
|
"""Read AGENTS.md from the repo root if it exists."""
|
||||||
|
if not repo_dir:
|
||||||
|
return None
|
||||||
|
|
||||||
|
safe_agents_path = shlex.quote(f"{repo_dir}/AGENTS.md")
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
result = await loop.run_in_executor(
|
||||||
|
None,
|
||||||
|
sandbox_backend.execute,
|
||||||
|
f"test -f {safe_agents_path} && cat {safe_agents_path}",
|
||||||
|
)
|
||||||
|
if result.exit_code != 0:
|
||||||
|
logger.debug("AGENTS.md not found at %s", safe_agents_path)
|
||||||
|
return None
|
||||||
|
content = result.output or ""
|
||||||
|
content = content.strip()
|
||||||
|
return content or None
|
||||||
Loading…
Add table
Reference in a new issue