Skip to content

Commit 64582ce

Browse files
committed
Provide Serena's system prompt (instruction manual) lazily
At MCP connection time, provide only a one-sentence bootstrap prompt
1 parent bc41c84 commit 64582ce

5 files changed

Lines changed: 19 additions & 16 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ Status of the `main` branch. Changes prior to the next official version change w
2626
- `query_project`: Support use of project root instead of project name #1388
2727
- `list_queryable_projects`: Return both project names and project roots
2828
- Fix: `search_for_pattern` tool returned 1-based line numbers (in contrast to all other tools); cause: implementation of `text_utils.search_text`
29+
- Serena's system prompt (a.k.a. the 'Serena Instructions Manual') is now provided lazily.
30+
At MCP connection time, only a one-sentence bootstrap prompt is provided.
31+
The `initial_instructions` tool provides the full prompt on demand, keeping the initial context lean.
2932

3033
* JetBrains:
3134
- `Move` and `SafeDelete` tools: transform empty string to None (counteracts client errors)

src/serena/agent.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -891,8 +891,18 @@ def _format_prompt(self, prompt_template: str) -> str:
891891
template = JinjaTemplate(prompt_template)
892892
return template.render(available_tools=self._exposed_tools.tool_names, available_markers=self._exposed_tools.tool_marker_names)
893893

894+
def create_connection_prompt(self) -> str:
895+
"""
896+
Returns the bootstrap prompt to be sent at MCP connection time.
897+
898+
:return: the prompt
899+
"""
900+
return self.prompt_factory.create_connection_prompt()
901+
894902
def create_system_prompt(self, session_id: str = "global") -> str:
895903
"""
904+
Returns the 'Serena Instructions Manual', i.e. Serena's system prompt.
905+
896906
:param session_id: the client session ID for the case where this is run from a tool; "global" for the connection time case
897907
:return: the prompt
898908
"""
@@ -925,7 +935,6 @@ def create_system_prompt(self, session_id: str = "global") -> str:
925935
if self._active_project is not None and not self._project_prompt_status.is_project_activation_message_already_provided(session_id):
926936
system_prompt += "\n\n" + self.get_project_activation_message(session_id)
927937

928-
log.info("System prompt:\n%s", system_prompt)
929938
return system_prompt
930939

931940
def get_project_activation_message(self, session_id: str) -> str:

src/serena/generated/generated_prompt_factory.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,8 @@ class PromptFactory(PromptFactoryBase):
1717
def create_onboarding_prompt(self, *, system: Any) -> str:
1818
return self._render_prompt("onboarding_prompt", locals())
1919

20-
def create_think_about_collected_information(self) -> str:
21-
return self._render_prompt("think_about_collected_information", locals())
22-
23-
def create_think_about_task_adherence(self) -> str:
24-
return self._render_prompt("think_about_task_adherence", locals())
25-
26-
def create_think_about_whether_you_are_done(self) -> str:
27-
return self._render_prompt("think_about_whether_you_are_done", locals())
28-
29-
def create_summarize_changes(self) -> str:
30-
return self._render_prompt("summarize_changes", locals())
31-
32-
def create_prepare_for_new_conversation(self) -> str:
33-
return self._render_prompt("prepare_for_new_conversation", locals())
20+
def create_connection_prompt(self) -> str:
21+
return self._render_prompt("connection_prompt", locals())
3422

3523
def create_system_prompt(
3624
self,

src/serena/mcp.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ def create_mcp_server(
332332
# retain only FASTMCP_ prefix for already set environment variables.
333333
Settings.model_config = SettingsConfigDict(env_prefix="FASTMCP_")
334334
instructions = self._get_initial_instructions()
335+
log.info("MCP server initial instructions:\n%s", instructions)
335336
mcp = FastMCP(
336337
name="Serena",
337338
lifespan=self.server_lifespan,
@@ -357,4 +358,4 @@ async def server_lifespan(self, mcp_server: FastMCP) -> AsyncIterator[None]:
357358

358359
def _get_initial_instructions(self) -> str:
359360
assert self.agent is not None
360-
return self.agent.create_system_prompt()
361+
return self.agent.create_connection_prompt()

src/serena/resources/config/prompt_templates/system_prompt.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# in which case this prompt will be given as a regular message on the call of a simple tool which the agent
33
# is encouraged (via the tool description) to call at the beginning of the conversation.
44
prompts:
5+
connection_prompt: |
6+
CRITICAL: Before starting to work on a coding task, call the `initial_instructions` tool to read the 'Serena Instructions Manual'.
57
system_prompt: |
68
You have access to semantic coding tools upon which you rely heavily for all your work.
79
You operate in a resource-efficient and intelligent manner, always keeping in mind to not read or generate

0 commit comments

Comments
 (0)