diff --git a/apps/agent/agent/prompt.py b/apps/agent/agent/prompt.py
index 0e356ebd..85adab26 100644
--- a/apps/agent/agent/prompt.py
+++ b/apps/agent/agent/prompt.py
@@ -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.
+{agents_md_section}
**Important:**
- Use `{working_dir}` as your working directory for all operations
@@ -72,9 +73,20 @@ def construct_system_prompt(
working_dir: str,
linear_project_id: str = "",
linear_issue_number: str = "",
+ agents_md: 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"
+ "\n"
+ f"{agents_md}\n"
+ "\n"
+ )
return SYSTEM_PROMPT.format(
working_dir=working_dir,
linear_project_id=linear_project_id or "",
linear_issue_number=linear_issue_number or "",
+ agents_md_section=agents_md_section,
)
diff --git a/apps/agent/agent/server.py b/apps/agent/agent/server.py
index c5c97898..ea0bca67 100644
--- a/apps/agent/agent/server.py
+++ b/apps/agent/agent/server.py
@@ -42,6 +42,7 @@ SANDBOX_CREATING = "__creating__"
SANDBOX_CREATION_TIMEOUT = 180
SANDBOX_POLL_INTERVAL = 1.0
+from .utils.agents_md import read_agents_md_in_sandbox
from .utils.github import (
git_has_uncommitted_changes,
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")
if 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):
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
+ 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_project_id = linear_issue.get("linear_project_id", "")
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)
return create_deep_agent(
@@ -335,6 +340,7 @@ async def get_agent(config: RunnableConfig) -> Pregel: # noqa: PLR0915
repo_dir,
linear_project_id=linear_project_id,
linear_issue_number=linear_issue_number,
+ agents_md=agents_md,
),
tools=[http_request, fetch_url, commit_and_open_pr],
backend=sandbox_backend,
diff --git a/apps/agent/agent/utils/agents_md.py b/apps/agent/agent/utils/agents_md.py
new file mode 100644
index 00000000..6afd63e7
--- /dev/null
+++ b/apps/agent/agent/utils/agents_md.py
@@ -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