有些 Agent 报错看起来像 provider 不稳定:
API call failed
Non-retryable error
trying fallback
Aborting
但真正的问题可能很底层:协议适配器拿到的是一个对象,却把它当成可迭代的 streaming 数据来处理。
NousResearch/hermes-agent issue #16271 记录的就是这种典型适配层错误。用户使用 copilot-acp provider,模型是 claude-opus-4.7,endpoint 是:
acp://copilot
结果请求失败:
TypeError: 'types.SimpleNamespace' object is not iterable
这不是模型不会回答,也不是 API Key 错,更不是简单重试能解决的问题。
这是 ACP Copilot CLI 的 streamable HTTP response 没有被正确解析。
错误日志透露了什么?
issue 里的日志很短,但信息密度很高:
⚠️ API call failed (attempt 1/3): TypeError
🔌 Provider: copilot-acp Model: claude-opus-4.7
🌐 Endpoint: acp://copilot
📝 Error: 'types.SimpleNamespace' object is not iterable
⚠️ Non-retryable error (HTTP None) — trying fallback...
❌ Non-retryable error (HTTP None): 'types.SimpleNamespace' object is not iterable
❌ Non-retryable client error (HTTP None). Aborting.
🔌 Provider: copilot-acp Model: claude-opus-4.7
🌐 Endpoint: acp://copilot
💡 This type of error won't be fixed by retrying.
Error: 'types.SimpleNamespace' object is not iterable
几个关键点:
- provider 是
copilot-acp; - endpoint 是
acp://copilot; - HTTP status 是
None; - 错误类型是 Python
TypeError; - 系统判断为 non-retryable;
- fallback 也救不了。
这说明请求并不是远端返回了一个标准 4xx / 5xx。
它更像是在本地解析/适配 response 的过程中,代码对返回结构做了错误假设。
为什么 SimpleNamespace 不能被当成 iterable?
types.SimpleNamespace 是 Python 里一种很轻量的对象容器。
它适合这样访问:
obj.foo
obj.bar
但它不是 list,不是 generator,也不是 async iterator。
如果某段代码期待:
for chunk in response:
...
但实际拿到的是:
SimpleNamespace(...)
就会出现:
'types.SimpleNamespace' object is not iterable
这类错误的重点不是 SimpleNamespace 本身,而是上游返回结构和下游消费方式不匹配。
ACP 场景为什么更容易出现这种错?
ACP,也就是 Agent Communication Protocol,本质上是在 Agent 与外部工具/模型/CLI 之间建立一层协议适配。
它不是传统的:
HTTP JSON request → HTTP JSON response
很多 ACP provider 会涉及:
- streamable response;
- event message;
- JSON-RPC 风格结构;
- CLI bridge;
- stdout/stderr;
- object wrapper;
- async stream;
- partial result;
- final result。
如果适配层没有清楚区分“事件流”和“最终对象”,就容易把对象当 chunk 流处理。
这正是 #16271 的核心。
评论里的线索:它不是孤立问题
维护者评论指出:
Likely duplicate of #14437 — same copilot-acp SimpleNamespace iteration crash.
Fix PRs: #15365 (api_mode detection), #14442 (NotImplementedError guard), #14438 (full streaming), #12274.
这说明问题不是单次用户环境异常,而是 Copilot ACP streaming 支持链路中的一类已知缺陷。
几个修复方向也很有信息量:
api_mode detection:先判断当前 API 返回模式;NotImplementedError guard:未实现路径不要伪装成可运行;full streaming:真正支持 streaming,而不是半截兼容;- 其他适配修复:补齐 ACP response 的消费逻辑。
换句话说,这不是给 TypeError 外面包个 try/except 就结束。
真正要修的是协议层对返回模式的识别。
“重试三次”为什么没用?
很多 API 错误可以重试,例如:
- timeout;
- 502;
- rate limit;
- connection reset;
- incomplete chunked read。
但这个错误不属于那类。
SimpleNamespace object is not iterable 是本地代码路径错误。
只要输入结构不变,重试 100 次也会得到同样的 TypeError。
所以日志里说:
This type of error won't be fixed by retrying.
这个判断是对的。
问题在于:用户需要知道这不是 provider 临时抽风,而是 Hermes / ACP adapter 的版本或实现能力问题。
正确的修复思路:先识别 response 形态,再决定消费方式
一个健壮的 ACP adapter 至少要区分这些情况。
1. 普通一次性对象
例如:
SimpleNamespace(content="...", status="completed")
这种不能直接 for-loop。
应该读取字段,转换成 Hermes 内部统一 message/result 格式。
2. 同步 iterable stream
例如:
for event in response:
handle(event)
这种才适合普通迭代。
3. 异步 stream
例如:
async for event in response:
handle(event)
这种要走 async iterator。
4. 未实现 streaming
如果某个 mode 还没实现,应该明确抛出 NotImplementedError,并给出可读错误,而不是让用户看到 SimpleNamespace TypeError。
5. 混合结构
有些 provider 会先返回 wrapper,再从 wrapper 里取 stream。
这种要明确解包字段,而不是假设顶层 response 就是可迭代对象。
用户怎么快速判断是不是这个问题?
如果你看到下面组合,就基本可以定位到 ACP adapter 层:
Provider: copilot-acp
Endpoint: acp://copilot
Error: 'types.SimpleNamespace' object is not iterable
HTTP None
Non-retryable client error
这时不建议优先折腾:
- API Key;
- DeepAI base_url;
- 模型上下文窗口;
- 网络代理;
- provider fallback;
- 重试次数。
更应该检查:
- Hermes 版本是否包含 Copilot ACP streaming 修复;
- 是否命中了
#14437/#16271同类问题; copilot-acp是否支持当前模型和当前 api mode;- 是否有 full streaming 相关 PR 已合并;
- 是否可以临时切到非 ACP Copilot provider 或标准 OpenAI-compatible provider。
为什么这类错误对 Agent 特别致命?
普通脚本遇到 TypeError,最多这次请求失败。
Agent 场景里会更麻烦:
- fallback 可能切到另一个 provider,导致输出风格/能力变化;
- session 状态可能记录一次失败工具调用;
- 用户以为是模型不可用;
- 长任务可能被迫中断;
- 如果错误发生在 streaming 中途,可能没有完整 final answer。
协议适配层越靠近底部,错误越容易被上层包装成模糊的 “API call failed”。
所以文章标题里的“对象不是流”,其实是这类问题的核心:数据形态不能靠猜。
和 DeepAI API 中转站的边界
DeepAI API 中转站提供标准 OpenAI-compatible API 入口:
Base URL: https://api.deepai.wang/v1
API Key: 你的 DeepAI Key
Model: 以 DeepAI 控制台为准
但 copilot-acp 是 GitHub Copilot + ACP adapter 的专用路径,endpoint 是:
acp://copilot
这和标准 OpenAI-compatible HTTP API 不是一回事。
所以如果你遇到 SimpleNamespace object is not iterable,不要把它归因到 DeepAI API 中转站。这类错误发生在 Hermes 的 Copilot ACP 适配层,而不是 DeepAI 的模型转发层。
更实际的建议是:
- 需要标准模型 API:用 DeepAI / OpenAI-compatible provider;
- 需要 GitHub Copilot ACP:升级 Hermes,确认 Copilot ACP streaming 修复是否包含在当前版本;
- 不要把
acp://copilot当成普通https://.../v1/chat/completions。
FAQ
SimpleNamespace object is not iterable 是模型错误吗?
不是。它是本地 Python 代码把对象当成 iterable 使用时产生的 TypeError。
重试能解决吗?
通常不能。只要 response 结构不变,重试仍会走同一条错误代码路径。
为什么 HTTP status 是 None?
因为错误可能发生在本地适配/解析阶段,而不是远端返回了标准 HTTP 错误码。
该查 API Key 吗?
如果日志已经明确是 SimpleNamespace object is not iterable,优先查 Hermes Copilot ACP adapter 版本和相关修复,而不是 API Key。
DeepAI API 中转站会导致这个错误吗?
不会。这个错误属于 copilot-acp / acp://copilot 路径,和标准 OpenAI-compatible DeepAI API 不是同一层。
总结
#16271 的教训非常工程化:
不要在协议适配层猜 response 是流。
ACP Copilot CLI 返回的 streamable data 可能是对象、wrapper、同步流、异步流或尚未实现的模式。Hermes 只有先识别 response 形态,再选择消费方式,才能避免 SimpleNamespace object is not iterable 这类本地崩溃。
对用户来说,看到这个错误时也别急着怀疑模型或中转 API。真正该查的是 Copilot ACP adapter 的 streaming 支持和版本修复。