Skip to content

feat: system prompt playbook variable interpolation - #578

Open
angri450 wants to merge 2 commits into
TencentCloud:developfrom
angri450:feature/system-prompt-playbook-vars
Open

feat: system prompt playbook variable interpolation#578
angri450 wants to merge 2 commits into
TencentCloud:developfrom
angri450:feature/system-prompt-playbook-vars

Conversation

@angri450

@angri450 angri450 commented Sep 6, 2026

Copy link
Copy Markdown

背景

Octop 的 system_prompt(agents 表 persona)是静态模板:同一个模板在多个 agent 实例间复用,但实例名/工作目录/时间无法区分。吸收 openresearch-cli 的 playbook 插值设计(SYSTEM_PROMPT.md 渲染 {name}/{id}/{project_state}),让 persona 模板支持身份与环境的占位符,编译图时渲染。

改动

  • AgentManager._render_system_prompt:渲染 {agent_id} {agent_name} {date} {datetime} {work_dir} {model} 六个变量;未知 {xxx} 原样保留(模板写错变量名不静默丢失)
  • _build_harness_config:bootstrap 完成后非空 system_prompt 走渲染;default_model 只解析一次(渲染 + HarnessAgentConfig 复用)
  • PersonaLoader.renderstr.format 改为宽容替换——用户自定义 persona 里的 {date} 等变量此前直接 KeyError 炸 agent 创建,现原样保留给编译期渲染
  • 单测:渲染路径 + 未知占位符保留 + persona 宽容(tests/unit/agents/test_agent_manager.py、test_persona.py)
  • CHANGELOG [Unreleased] 记录

设计边界

  • 渲染时机 = 编译图时(agent 配置变更),不是每轮 turn;动态状态(项目事实/当前重点)继续走 workspace MEMORY.md 热索引(每轮全文注入)
  • 四文件(SOUL/USER/MEMORY/AGENTS)走 memory 通道,不参与本插值——变量只作用于 agents 表 system_prompt(persona 底座)

配套的上下文治理设计(本 PR 之外的本地补丁,供参考)

本 PR 是上下文治理的一部分,另外三块在 harness/deepagents 层(本机补丁,harness-agent 上游仓未公开,故不在此仓落地):

  1. 历史工具调用回收(ToolTrace):每次模型调用前把最近 N 轮之外的工具消息压成按轮次排序的轨迹摘要(工具名+参数+结果截断)——长会话上下文膨胀主因是历史工具结果每轮重复注入(实测占 ~45%)。环境变量 TOOL_TRACE_KEEP_ROUNDS / MAX_CHARS 等可配。
  2. 记忆分层:deepagents MemoryMiddleware 超阈值(MEMORY_INJECT_MAX_CHARS 缺省 4000 字符)文件只注入头部 + 索引提示——常驻四文件只放索引的纪律代码化。
  3. 草稿本多窗口隔离:MemoryMiddleware sources 支持 {thread_id} 占位符——SCRATCHPAD/{thread_id}.md 按对话窗口隔离,多窗口各注入各草稿。

测试计划

  • 本地单测通过(渲染 + persona 宽容 + 未知占位符保留)
  • 完整 make all 待 CI(本机未配 dev 环境)

Render {agent_id}/{agent_name}/{date}/{datetime}/{work_dir}/{model} in an
agent's system prompt when the harness graph is compiled, so a single
persona template stays accurate across instances (inspired by
openresearch-cli's playbook substitution). Unknown placeholders are left
untouched so template typos stay visible instead of silently vanishing.

- _render_system_prompt: module-level renderer in AgentManager
- _build_harness_config: render non-empty system_prompt after bootstrap;
  resolve default_model once and reuse for the render + config
- test: render path incl. unknown-placeholder preservation
- CHANGELOG: [Unreleased] entry
Copilot AI lite review requested due to automatic review settings September 6, 2026 08:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

system_prompt 的 {date}/{datetime} 渲染目前使用本机时区而非配置的 default_timezone,可能导致线上时间不一致且相关测试断言也偏弱。

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

该 PR 为 Octop 的智能体 system_prompt(agents.persona)引入“playbook 风格”的模板变量插值,在编译 harness 图(graph-compile)阶段将 agent 身份与环境信息渲染进最终 system prompt,以便同一 persona 模板在不同 agent 实例间复用且保持上下文准确。

Changes:

  • AgentManager._build_harness_config 中对非空 system_prompt{agent_id}/{agent_name}/{date}/{datetime}/{work_dir}/{model} 渲染,并将 default_model 解析结果复用。
  • 新增单测覆盖:渲染路径 + 未知占位符保留({foo} 不被吞掉)。
  • 更新 CHANGELOG 记录该能力(Unreleased)。
File summaries
File Description
src/octop/infra/agents/manager.py 新增 system_prompt 插值渲染函数,并在 build harness config 时应用渲染与复用 default_model
tests/unit/agents/test_agent_manager.py 增加 system_prompt 插值渲染行为与未知占位符保留的单测
CHANGELOG.md 记录 Unreleased 新增:system_prompt playbook 插值变量支持
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +112 to +135
def _render_system_prompt(
template: str,
*,
agent_id: str,
agent_name: str,
work_dir: str,
model: str | None,
) -> str:
"""Render ``{playbook}`` variables into an agent system prompt.

Inspired by openresearch-cli's playbook substitution: the persona system
prompt may reference the agent's own identity, working directory, and the
current date so a single template stays accurate across instances. Values
are filled once when the harness graph is compiled, not per turn.
"""
now = datetime.datetime.now()
substitutions = {
"agent_id": agent_id,
"agent_name": agent_name,
"date": now.strftime("%Y-%m-%d"),
"datetime": now.strftime("%Y-%m-%d %H:%M"),
"work_dir": work_dir,
"model": model or "",
}
Comment on lines +2635 to +2641
system_prompt = _render_system_prompt(
system_prompt,
agent_id=row.agent_id,
agent_name=row.name or row.agent_id,
work_dir=str(harness_workspace),
model=default_model,
)
assert "bot" in cfg.system_prompt # row.name
assert str(ws) in cfg.system_prompt
assert "gpt-4o-mini" in cfg.system_prompt
assert "20" in cfg.system_prompt # rendered date starts with 20xx
…ndering

PersonaLoader.render used str.format, which raises KeyError on any
placeholder beyond {agent_name}/{user_display}/{custom}. Playbook
variables rendered later by AgentManager._render_system_prompt
({date}/{work_dir}/{model}/...) written into a custom persona would
crash agent creation. Switch to str.replace for the three known
placeholders so unknown ones pass through for compile-time rendering.

- persona.py: render uses replace; empty custom drops the placeholder line
- test_persona.py: unknown-placeholder preservation + empty-custom case
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants