OpenProgram Docs

Agentic 自递归保护

当前行为: agentic 函数在用户轮次中接收情境引导,同时保留按函数计数的递归深度上限作为确定性保护。
事实来源: openprogram/agentic_programming/call_state.py 和 openprogram/agentic_programming/runtime.py.
测试: tests/unit/programs/runtime/test_self_recursion_guard.py.

1. 问题

agentic 函数运行内部 Agent 循环。工具列表可能包含该函数自身,匹配的 docstring 会导致内部模型再次调用它。如果不加限制,重复直接调用可能造成无限同名递归。

2. 情境引导

openprogram/agentic_programming/runtime.py::_situational_prefix 生成英文用户轮次前缀,说明当前函数名,解释调用它会重新进入当前执行,并引导模型使用较低层工具。

  • 常规执行路径将前缀注入用户内容块的开头。
  • 独立执行的 fallback 从递归上下文取得最深层函数名,并应用相同前缀。
  • system prompt 保持独立。当前函数不会通过 self-deny 项隐藏;引导有明确主体,由模型决定不调用自身。

3. 深度上限

  • openprogram/agentic_programming/call_state.py::_MAX_AGENTIC_RECURSION_DEPTH 为 5。
  • _recursion_depth 是以函数名为键的上下文本地映射。
  • 同步与异步包装器增加当前函数的深度,超过限制时抛出 RecursionError ,并在以下代码块中重置上下文值: finally.
  • 深度上限对每个函数名独立计数。它防止直接 A → A 递归;A → B → A 等跨函数循环是已记录的剩余限制。

4. 源码符号

机制当前源码符号
深度上限openprogram/agentic_programming/call_state.py::_MAX_AGENTIC_RECURSION_DEPTH
深度上下文openprogram/agentic_programming/call_state.py::_recursion_depth
同步与异步包装器openprogram/agentic_programming/call_state.py
情境前缀openprogram/agentic_programming/runtime.py::_situational_prefix
常规注入openprogram/agentic_programming/runtime.py frame 前缀构造与用户内容组装
独立执行 fallbackopenprogram/agentic_programming/runtime.py 递归上下文 fallback
工具策略openprogram/agentic_programming/runtime.py 保留 source/allow/toolset 及无关 deny 处理

5. 行为合同

合同证据
引导说明当前函数名、禁止调用自身并解释递归。test_situational_prefix_warns_against_self_call
空 docstring 不添加无关的函数任务后缀。test_situational_prefix_handles_empty_doc
调用期间不把当前函数名加入 self-deny。test_self_name_NOT_denied_during_call
调用期间深度递增,返回或异常后重置。test_depth_increments_during_call, test_depth_restored_after_return, test_depth_restored_after_exception
直接同名递归在配置上限处抛出异常;不同子调用不会被连带拒绝。test_depth_backstop_raises_past_limit, test_distinct_subcalls_not_collateral_damage

6. 边界与剩余工作

  • 引导不保证能力较弱的模型一定会在到达上限前停止。
  • 本机制未实现跨函数循环检测。
  • 保护不改变工具授权、session DAG 语义或统一 system-prefix 合同。
  • 本页使用源码符号与仓库路径,而不是固定行号或历史 commit 标识,避免源码移动后证据悄然过期。
Last updated · 2026-10-10