问题描述 / Description
当 LlmAgent 配置了 code_executor 且使用支持思考/推理功能的模型(如通过 reasoning_content 返回 thinking 内容的模型)时,CodeExecutionUtils.extract_code_and_truncate_content 在从最终响应中提取代码块时,没有区分 Part.thought 标记,导致模型在"思考"阶段(reasoning/thinking)里输出的代码块,只要格式满足代码围栏规范(如 ```python ... ```),也会被当作正式代码提取出来并交给 code_executor.execute_code 真实执行。
When LlmAgent is configured with a code_executor and the underlying model supports reasoning/thinking (returns reasoning_content, wrapped into a Part with thought=True), CodeExecutionUtils.extract_code_and_truncate_content does not filter out parts marked as thought when collecting text for code-block extraction. As a result, any code fence (e.g. ```python ... ```) that appears inside the model's thinking/reasoning text is treated the same as code in the final answer, and gets actually executed by the configured code_executor.
复现步骤 / Steps to Reproduce
- 配置一个
LlmAgent,使用带 reasoning_content 能力的模型(例如通过 _openai_model.py 的 OpenAI-compatible reasoning 适配路径),并挂载任意 code_executor(如 UnsafeLocalCodeExecutor / ContainerCodeExecutor / 自定义 sandbox executor)。
- 让模型在思考阶段(reasoning)输出如下内容(只要求满足围栏格式规范):
我先写一段示例代码验证思路:
```python
import os
os.system("id") # 仅作演示,说明任意代码都可能被执行
- 观察最终事件流:即使模型的正式回复中完全没有代码块,只要 reasoning/thought 文本里有合规的代码围栏,该代码依然会被提取并调用
code_executor.execute_code(...) 真实执行。
期望行为 / Expected Behavior
thought=True 的 Part(即模型内部思考/推理过程,不代表最终确定要执行的动作)不应该被当作可执行代码的来源;只有非 thought 的正式回复文本中的代码块才应被提取执行。
实际行为 / Actual Behavior
思考内容和正式回复内容被同等对待,思考内容里的代码块会被提取并真实执行。
根因分析 / Root Cause
-
模型适配层(如 trpc_agent_sdk/models/_openai_model.py)把 reasoning_content 包装为普通 Part,仅通过 part.thought = True 做区分,与正文 Part 存放在同一个 content.parts 列表里:
# trpc_agent_sdk/models/_openai_model.py
if thought_content:
content_part = Part.from_text(text=thought_content)
content_part.thought = True
parts.append(content_part)
-
负责提取代码块的 CodeExecutionUtils.extract_code_and_truncate_content(trpc_agent_sdk/code_executors/utils/_code_execution.py)在收集文本时只判断 p.text 是否非空,没有排除 p.thought 为真的 Part:
# trpc_agent_sdk/code_executors/utils/_code_execution.py
text_parts = [p for p in content.parts if p.text]
if not text_parts:
return code_blocks
response_text = '\n'.join([p.text for p in text_parts])
# ... 后续用 code_block_delimiters 在 response_text 中正则匹配代码块
-
CodeExecutionResponseProcessor._run_post_processor(trpc_agent_sdk/agents/core/_code_execution_processor.py)拿最终聚合事件(llm_response.partial=False)的 content 直接调用上述提取函数,提取到的代码块会立即送去执行:
response_content = copy.deepcopy(llm_response.content)
code_blocks = CodeExecutionUtils.extract_code_and_truncate_content(
response_content,
code_executor.code_block_delimiters,
code_executor.ignore_codes,
)
if not code_blocks:
return
code_execution_result = await code_executor.execute_code(...) # 真实执行
因此只要模型开启了推理/思考能力,且思考文本中出现合规的代码围栏,该代码就会被误当作正式指令执行,可能带来非预期的副作用(文件写入、网络请求、系统命令等),是一个潜在的安全/正确性问题。
影响范围 / Affected Version
- Package:
trpc-agent / trpc_agent_sdk
- 复现于
0.7.9 与 0.9.0(均存在同样代码逻辑,未做修复)
- 涉及模块:
trpc_agent_sdk/code_executors/utils/_code_execution.py::CodeExecutionUtils.extract_code_and_truncate_content
trpc_agent_sdk/agents/core/_code_execution_processor.py::_run_post_processor
trpc_agent_sdk/models/_openai_model.py(reasoning_content → thought=True Part 的生成路径)
trpc_agent_sdk/models/_anthropic_model.py(extended thinking 场景,同样受影响)
建议修复方案 / Suggested Fix
在 extract_code_and_truncate_content 收集 text_parts 时排除 thought 为真的 Part:
text_parts = [p for p in content.parts if p.text and not getattr(p, "thought", False)]
同时建议在 CodeExecutionResponseProcessor 或相关文档中明确说明:code_executor 只应作用于模型的最终正式回复内容,思考/推理内容不应参与代码提取与执行。
补充说明 / Additional Context
该问题在纯文本围栏匹配层面无法通过"提示词约束"完全规避——即使 System Prompt 要求模型只在正式回复里输出代码,模型的思考过程仍可能出于草稿目的写出示例代码,从框架层面过滤 thought Part 是更可靠的修复方式。
问题描述 / Description
当
LlmAgent配置了code_executor且使用支持思考/推理功能的模型(如通过reasoning_content返回 thinking 内容的模型)时,CodeExecutionUtils.extract_code_and_truncate_content在从最终响应中提取代码块时,没有区分Part.thought标记,导致模型在"思考"阶段(reasoning/thinking)里输出的代码块,只要格式满足代码围栏规范(如```python ... ```),也会被当作正式代码提取出来并交给code_executor.execute_code真实执行。When
LlmAgentis configured with acode_executorand the underlying model supports reasoning/thinking (returnsreasoning_content, wrapped into aPartwiththought=True),CodeExecutionUtils.extract_code_and_truncate_contentdoes not filter out parts marked asthoughtwhen collecting text for code-block extraction. As a result, any code fence (e.g.```python ... ```) that appears inside the model's thinking/reasoning text is treated the same as code in the final answer, and gets actually executed by the configuredcode_executor.复现步骤 / Steps to Reproduce
LlmAgent,使用带reasoning_content能力的模型(例如通过_openai_model.py的 OpenAI-compatible reasoning 适配路径),并挂载任意code_executor(如UnsafeLocalCodeExecutor/ContainerCodeExecutor/ 自定义 sandbox executor)。code_executor.execute_code(...)真实执行。期望行为 / Expected Behavior
thought=True的 Part(即模型内部思考/推理过程,不代表最终确定要执行的动作)不应该被当作可执行代码的来源;只有非 thought 的正式回复文本中的代码块才应被提取执行。实际行为 / Actual Behavior
思考内容和正式回复内容被同等对待,思考内容里的代码块会被提取并真实执行。
根因分析 / Root Cause
模型适配层(如
trpc_agent_sdk/models/_openai_model.py)把reasoning_content包装为普通Part,仅通过part.thought = True做区分,与正文 Part 存放在同一个content.parts列表里:负责提取代码块的
CodeExecutionUtils.extract_code_and_truncate_content(trpc_agent_sdk/code_executors/utils/_code_execution.py)在收集文本时只判断p.text是否非空,没有排除p.thought为真的 Part:CodeExecutionResponseProcessor._run_post_processor(trpc_agent_sdk/agents/core/_code_execution_processor.py)拿最终聚合事件(llm_response.partial=False)的content直接调用上述提取函数,提取到的代码块会立即送去执行:因此只要模型开启了推理/思考能力,且思考文本中出现合规的代码围栏,该代码就会被误当作正式指令执行,可能带来非预期的副作用(文件写入、网络请求、系统命令等),是一个潜在的安全/正确性问题。
影响范围 / Affected Version
trpc-agent/trpc_agent_sdk0.7.9与0.9.0(均存在同样代码逻辑,未做修复)trpc_agent_sdk/code_executors/utils/_code_execution.py::CodeExecutionUtils.extract_code_and_truncate_contenttrpc_agent_sdk/agents/core/_code_execution_processor.py::_run_post_processortrpc_agent_sdk/models/_openai_model.py(reasoning_content →thought=TruePart 的生成路径)trpc_agent_sdk/models/_anthropic_model.py(extended thinking 场景,同样受影响)建议修复方案 / Suggested Fix
在
extract_code_and_truncate_content收集text_parts时排除thought为真的 Part:同时建议在
CodeExecutionResponseProcessor或相关文档中明确说明:code_executor只应作用于模型的最终正式回复内容,思考/推理内容不应参与代码提取与执行。补充说明 / Additional Context
该问题在纯文本围栏匹配层面无法通过"提示词约束"完全规避——即使 System Prompt 要求模型只在正式回复里输出代码,模型的思考过程仍可能出于草稿目的写出示例代码,从框架层面过滤
thoughtPart 是更可靠的修复方式。