
Dify Agent Prompt Layer 详解如何为一次 Agent Run 组装系统提示词与用户输入【免费下载链接】difyBuild Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.项目地址: https://gitcode.com/GitHub_Trending/di/difyDify Agent 采用“层Layer”架构组织每次运行run的能力单元其中 Prompt Layertype id 为plain.prompt负责为当前 run 提供系统提示词片段prefix/suffix与用户输入片段user。本文以 Prompt Layer 用户手册 为核心结合 PromptLayer 源码实现、运行器校验逻辑 和 compositor 聚合逻辑讲清楚它的配置字段、组装时序、空 prompt 拒绝规则以及它与 history layer 的协作边界帮助你在构建 create-run 请求时正确编排 prompt 片段。Prompt Layer 的定位与适用场景在 Dify Agent 的请求体中Prompt Layer 是一个普通的RunLayerSpectype id 为plain.prompt。它承载三类内容本次 run 应发送的系统指令prefix以及可选的suffix当前用户输入user。这是 run API 提交用户输入的唯一入口——API 不接受顶层user_prompt字段。这一点可以从运行器代码得到印证runner.py 在进入 run 后直接读取run.user_prompts由所有层聚合而来并以此作为 pydantic-ai 的 run 输入请求体中并不存在独立的用户输入字段。Prompt Layer 与其他层如模型层、工具层平级参与构图源码注释说明了它的定位它是构建在agenton.layers.types之上的小型具体实现刻意保持与 compositor 图构建无关以便在配置、示例和更高层的动态层中复用见 basic.py。配置字段说明PromptLayerConfig的完整字段定义在 basic.py字段类型含义prefixstr或list[str]收集在其他 prompt 内容之前的系统提示词片段。userstr或list[str]当前 run 的用户消息片段。suffixstr或list[str]收集在 prefix 内容之后的系统提示词片段。三个字段默认值均为空列表。另外需要注意两个源码层面的约束配置类使用了model_config ConfigDict(extraforbid)即请求中传入未知字段会被 Pydantic 校验直接拒绝这是一个常见的报错来源字符串与列表两种写法都合法。PromptLayer提供了prefix_prompts/suffix_prompts/user_prompts三个属性将字符串归一化为单元素列表后再参与聚合见 basic.py因此调用方无论传str还是list[str]运行时的处理路径是一致的。测试用例 test_basic.py 也验证了PLAIN_PROMPT_LAYER_TYPE_ID plain.prompt以及PromptLayer.type_id与该常量一致确认了 type id 的稳定性。系统提示词的组装顺序当图中存在多个会贡献 prompt 的层时聚合顺序由 compositor 决定。从 run.py 的prompts属性 可以看到按 slot 顺序收集所有层的prefix片段以倒序收集所有层的suffix片段每个片段经过所在层的wrap_prompt包装允许层对片段做二次加工最后统一交给prompt_transformer处理。这意味着prefix位于系统提示词的前部suffix位于尾部倒序收集 suffix 的设计使得后声明的层的 suffix 更靠近 prefix 内容、先声明的层的 suffix 排在最末尾。如果你的 run 中只有 prompt layer 一个系统提示词来源这套细节不会产生影响只有在多层同时贡献系统片段例如 Dify 内置的知识检索层也会贡献user_prompts见 knowledge 层实现时才需要关注顺序。基本用法手册给出的最小示例用一个RunLayerSpec声明名为prompt的层config 中分别传入一条系统指令和一条用户输入from agenton_collections.layers.plain import PLAIN_PROMPT_LAYER_TYPE_ID, PromptLayerConfig from dify_agent.protocol import RunLayerSpec prompt_layer RunLayerSpec( nameprompt, typePLAIN_PROMPT_LAYER_TYPE_ID, configPromptLayerConfig( prefixYou are a concise assistant., userSummarize the incident in one paragraph., ), )这里nameprompt是约定俗成的名字而非保留字运行时不对层名做保留但官方示例如 run_server_sync_client.py与调度器测试test_run_scheduler.py都使用prompt作为该层的名称建议保持一致以便他人阅读。type则必须是PLAIN_PROMPT_LAYER_TYPE_ID即字符串plain.prompt运行时按 type id 反查层工厂来实例化写错 type 会导致构图失败。多片段写法列表形式的 prefix / user / suffix当调用方希望把若干提示词片段保持独立而仍然只发送一个 run时使用列表prompt_layer RunLayerSpec( nameprompt, typePLAIN_PROMPT_LAYER_TYPE_ID, configPromptLayerConfig( prefix[ You are an incident response assistant., Prefer concrete mitigation steps., ], user[ Database latency is elevated., Return the likely severity and next actions., ], suffixDo not invent metrics that are not provided., ), )列表写法在多片段场景下的实际收益体现在两处系统侧prefix列表中的每个片段会按顺序拼接进系统提示词流suffix同理放在尾部。像“角色设定 回答风格偏好”这类天然分段的指令用列表比手动用换行拼接更清晰也便于后续按来源增删片段。用户侧user列表中的多个片段最终会一起作为 run 输入。从 agent_factory.py 的normalize_user_input可以看到运行时的归一化规则只有当聚合结果恰好是“单个字符串”时才作为str传入 pydantic-ai否则整体以列表形式传入从而保留多部分multi-part提示词的语义。空用户输入的拒绝机制手册指出当有效用户 prompt 为空或仅含空白字符时Dify Agent 会拒绝 create-run 请求。这条规则的实现在 user_prompt_validation.pyEMPTY_USER_PROMPTS_ERROR run.user_prompts must not be empty def has_non_blank_user_prompt(user_prompts: Sequence[UserContent]) - bool: for prompt in user_prompts: if isinstance(prompt, str): if prompt.strip(): return True else: return True return False关键细节有三点校验发生在 run 入口内部即 compositor 构建完成、层实例化并经过 transformer 转换之后。源码注释明确说明这样做是为了“让运行时执行使用与实际 pydantic-ai 输入相同的转换后 prompt”避免校验的是原始配置、执行的是转换后内容的偏差字符串片段按strip()判定和 都不算有效输入非字符串片段富媒体/消息部件直接视为有效内容因为富内容没有统一的空白表示校验失败时runner.py 抛出AgentRunValidationError(run.user_prompts must not be empty)。注意存在一个豁免条件如果本次 run 携带的是延迟工具结果deferred tool results则跳过该校验——因为工具结果回传场景下用户 prompt 本来就可以为空。Prompt 如何进入模型run 级 instructions 与记忆隔离理解了 prompt 的“入口”还要知道它的“出口”。运行器在调用agent.run时做了明确的分工见 runner.py用户输入normalize_user_input(user_prompts)作为 run 的输入传入系统提示词instructionsrun.prompts or None即聚合后的 prefix/suffix 系统片段以pydantic-ai 的 run 级 instructions形式传入而不是被硬编码进模型层的系统提示。agent_factory的模块 docstring 也点明了这一设计“The runner passes Dify system prompts as run-level instructions”。这种“系统提示按 run 注入”的方式带来一个重要的行为边界当前 run 的系统提示词是瞬态transient的不会写入会话记忆。这与手册 Notes 中最后一条对应当 history layer 存在时当前系统 prompt 以 run 级 instructions 传入不会被保存到 memory。history.py 的 docstring 明确写道“Current system instructions belong to each run and are never (persisted)”其持久化实现replace(message, instructionsNone)在落盘前会把消息上的瞬态 instructions 清除。因此你想在每轮对话中稳定生效的规则写进prefix/suffix即可不用担心污染历史但反过来说历史轮次中曾用过的系统指令也不会自动出现在当前 run 的上下文中——每轮的 prefix/suffix 只来自当前请求的层配置。实践建议与注意事项用户输入一律走 prompt layer。不要假设存在user_prompt顶层字段只填了prefix没填user的请求且无延迟工具结果会以run.user_prompts must not be empty失败。层名用prompttype 用plain.prompt。名字不保留但建议遵守约定type id 是反查工厂的依据必须精确。多来源系统指令时注意 suffix 倒序聚合多个层同时提供 suffix 时先声明的层其 suffix 排在最后可按此设计指令的优先级。配合 history layer 使用时系统指令按 run 生效、不落盘跨轮上下文只通过history层持久化的消息历史传递。配置字段是封闭的extraforbid意味着拼写错误如sys_prompt会直接触发校验失败而不是被静默忽略。参考实现与测试内容路径用户手册本文主体dify-agent/docs/dify-agent/user-manual/prompt-layer/index.mdPromptLayerConfig/PromptLayer实现dify-agent/src/agenton_collections/layers/plain/basic.py空 prompt 校验dify-agent/src/dify_agent/runtime/user_prompt_validation.pyrun 执行与校验触发点dify-agent/src/dify_agent/runtime/runner.py系统/用户 prompt 聚合dify-agent/src/agenton/compositor/run.py记忆持久化清除瞬态指令dify-agent/src/dify_agent/runtime/history.py层 type id 单测dify-agent/tests/local/agenton_collections/layers/plain/test_basic.py协议层 schema 测试dify-agent/tests/local/dify_agent/protocol/test_protocol_schemas.py调度器中 prompt layer 用例dify-agent/tests/local/dify_agent/runtime/test_run_scheduler.py客户端示例dify-agent/examples/dify_agent/dify_agent_examples/run_server_sync_client.py综上Prompt Layer 是 Dify Agent 中“提示词即配置”的核心载体prefix/suffix系统片段按 compositor 的顺序规则聚合为 run 级 instructionsuser片段构成经过空值校验的 run 输入且系统指令与记忆持久化严格隔离。掌握这三条链路就能在任何包含 Dify Agent 模型层、history layer 等组件的组合中正确编排提示词。【免费下载链接】difyBuild Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.项目地址: https://gitcode.com/GitHub_Trending/di/dify创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考