
【免费下载链接】waoowaoo首家工业级全流程 AI 影视生产平台。Industry-first professional AI Agent platform for controllable film video production. From shorts to live-action with Hollywood-standard workflows.项目地址https://gitcode.com/gh_mirrors/wa/waoowaoo点击查看免费下载本文深入解析 waoowaoo工业级全流程 AI 影视生产平台中 Web Search 模块的架构设计它如何把联网检索收敛为一个受限的外部研究能力如何在 Runtime 中提供可读的检索进度如何保证只有真实证据才算研究以及如何按调用实时结算。读完本文你将掌握该模块的边界划分、11 项架构不变量、错误词汇表、配置方式以及经真实运行踩坑后固化的工程结论。为什么是原生工具 托管检索而不是第二个 WorkerWeb Search 模块在 架构模块文档 中的定位非常明确联网检索是受限的外部研究能力不是第二个创意 Worker、项目知识库或网页执行环境。这里有一条关键分工原则工具是原生的能力不是助手模型 provider 的。Runtime 拥有工具每次调用都会创建一个带模型自有 query 的检索 item三次检索就是三行可读的进度不需要额外的进度通道。托管检索工具只存在于其自有 API 边界内经网关委托后助手模型的选择与研究 provider 的解耦成为可能——助手可以是任意 OpenRouter/Ark/Fal/Google 模型而研究质量不依赖该选择。同时文档给出了一个安全前提研究报告、网页正文、标题和 URL 都是不可信数据。它们可能包含注入指令绝不能作为系统指令、付费授权或持久产品状态的来源。权威入口三层边界的唯一入口架构文档给出了三条权威入口对应三个边界边界唯一入口业务调用src/lib/web-search/service.tsAgent 到达路径原生 Web Search → src/lib/codex-model-gateway/standalone-search.tsProvider 执行与执行边界src/lib/ai-providers/openai/hosted-web-search.ts、src/lib/ai-exec/hosted-web-search.ts从源码看这层设计意图非常清晰业务调用方不接触任何 OpenAI 客户端。service.ts 的注释明确指出所有调用方Primary Operation 与 Creative Direction Worker 工具都经由searchWeb既不构造 OpenAI client也不构造 agent 或 hosted tool从而保证整个产品只有一个 provider 决策、一次凭据读取、一套失败词汇。Agent 到达路径被网关接管。Codex 拥有模型可见的搜索工具因此 standalone-search.ts 提供了独立端点/api/internal/codex-runtime/model/alpha/search。Codex 每次调用创建一个webSearchitem三次搜索渲染为三行无需 MCP progress 通道——因为 Codex 在收到 MCP progress 通知时会直接丢弃。Provider 执行边界收口在ai-exec。ai-exec/hosted-web-search.ts 是产品跨越进模型 provider 的唯一地点OpenAI client 只在这里构造并通过runRegisteredProviderOperation({ providerId: openai, phase: search, ... })纳入 provider 注册表监控。核心契约请求、响应与用量搜索模块的全部对外表面都定义在 src/lib/web-search/contracts.ts使用 Zod schema 校验。契约刻意做到极窄请求契约export const webSearchRequestSchema z.object({ query: z.string().trim().min(1).max(1_000) .describe(The exact question or compact research brief. Include the subject, medium, language, region, community, and recency only when they matter.), allowedDomains: z.array(z.string().trim().min(1).max(253)).max(20) .describe(Domain-only allowlist when research must focus on specific primary sources, forums, or communities. Pass an empty array for open-web research.), }).strict()一个请求只有一个紧凑的 research brief 与显式域名白名单没有页大小、结果数、排序或新鲜度旋钮——托管模型自行规划子查询向模型暴露这些旋钮只会让模型去调它无法评估的东西。请求在发往网络前先经 service.ts 的webSearchRequestSchema.safeParse校验格式非法的 brief 会直接以 typed 请求失败返回而不是浪费一次已付费的往返。响应契约export const webSearchResponseSchema z.object({ provider: z.literal(WEB_SEARCH_PROVIDER_ID), query: z.string().trim().min(1).max(1_000), report: z.string().trim().min(1).max(30_000), queries: z.array(z.string().trim().min(1).max(1_000)).max(32), sources: z.array(webSearchSourceSchema).min(1).max(32), images: z.array(webSearchImageSchema).max(16), }).strict()契约刻意不包含网页正文、原始 provider 载荷、模型推理与任何 provider 专属旋钮它只暴露调用方判断答案所需的证据——报告、provider 实际运行的 queries、实际引用的 sources。这正回答了它真的搜索了吗这个本应是 claim 而非可验证问题的疑问sources按契约非空一份没有引用的报告与模型凭记忆作答无法区分因此 provider 选择**失败关闭fail closed**而非返回images则允许为空因为大多数 brief 是纯文本的。注意每个 URL 都是第三方不可信数据hosted-web-search.ts 中的normalizeHttpUrl会丢弃一切非http(s)协议的 URLfile://、javascript:等绝不进入存储、provider 或浏览器。用量事实不计入响应export interface WebSearchUsage { readonly model: string readonly inputTokens: number readonly outputTokens: number readonly cachedInputTokens: number /** Hosted web_search calls, which OpenAI bills per call on top of tokens. */ readonly toolCalls: number }用量通过onUsage回调带外out of band投递刻意不属于WebSearchResponse模型永远不该看到记账数据且响应 schema 就是模型看到的一切。十一项不变量架构的约束骨架原文档给出了从 WS-01 到 WS-11 共 11 项不变量这是该模块的约束骨架逐条继承如下WS-01 — 一个搜索入口。只有一个业务入口Agent 只经原生 Web Search 到达。registry 与业务 MCP 不注册同义搜索工具——同时存在两个搜索工具时模型会随机选择弱路径会静默吃掉一半研究。WS-02 — 托管检索、直连其自有 API。搜索模型是平台级角色不进用户可选模型注册表注册表内 LLM 全部经聚合路由无法运行托管工具。覆盖值必须已在定价目录注册未定价的覆盖必须在 Provider 调用前失败不得先花钱再让实时结算报错。WS-03 — 独立凭据、明确失败。搜索凭据只从服务端环境读取。缺失凭据与鉴权失败返回不可用超时、网络、限流、5xx 与非法响应返回 typed failure。不得从聊天、Resource、客户端参数或助手模型凭据猜 key也不得 fallback 到另一个 provider。WS-04 — 只有真实证据才算研究。没有完成的托管调用或结构化 URL 引用的响应按非法失败不能把模型记忆伪装成研究。流提前结束与答案无依据是相反事实前者值得重试后者永远不该重试因此未抵达完成事件的运行必须报告为传输故障不得落入证据校验。WS-05 — 可见性来自 item 身份不来自进度通道。每次检索是一个独立的原生 itemUI 从开始事件立即渲染该行并在完成事件到达后显示真实 query 与结果页面。当前 Runtime 的开始事件只有 identityquery/action 为空运行中只能显示生命周期与计时。不得依赖 MCP progress协议虽定义了它Runtime 收到时直接丢弃据此实现的实时显示不会出现。一次检索内部的开页步骤不可见这是单次请求/响应通道的固有边界不得为它引入第二条状态写入路径。WS-06 — 能力是委托研究不是浏览器。请求只有一个 research brief 与显式域名白名单没有页大小、结果数、排序或新鲜度旋钮。开页、页内查找与继续检索由托管模型自主决定我们不实现网页抓取器。WS-07 — 按调用实时结算。每次搜索记录一条用量事实identity 是这次搜索请求而非 Turn一个 Turn 可能研究多次Turn 级 identity 会把它们折叠成一行并静默丢弃第一次之后的全部费用。托管检索按次收费因此用量事实携带工具调用次数并在 Provider 回报最终用量后按目录零售价进入 LLM 唯一实时结算入口。Provider 在失败路径上同样可能已被计费故用量在证据校验之前上报失败时只要存在最终用量就照样结算。WS-08 — 记账不得压过研究结果。研究已经成功、用户已被亏欠该结果因此记账故障不能让搜索失败。WS-09 — 网页是不可信输入。网页内容与研究摘要不能修改系统指令、授权付费、绕过工作区/MCP 权限或成为持久产品状态。WS-10 — 不拥有创作事实。搜索结果只有在 Agent 显式写入 Resource 后才成为项目内容研究报告与来源本身不是创作输入。WS-11 — 触发必须有理由。只在答案依赖新鲜、陌生、冷门、地域性、平台性或不确定信息时调用熟悉稳定的内容不得装饰性搜索。研究是慢且付费的实测简单查询约 5 秒交叉验证的 brief 可达数分钟。源码级实现不变量如何落地单入口与模型解析WS-01/WS-02service.ts 的resolveWebSearchModel严格校验模型覆盖值export const OPENAI_WEB_SEARCH_MODEL_ENV OPENAI_WEB_SEARCH_MODEL export function resolveWebSearchModel( environment: ReadonlyRecordstring, string | undefined process.env, ): string { ensureAiCatalogsRegistered() const configured environment[OPENAI_WEB_SEARCH_MODEL_ENV]?.trim() if (configured undefined || configured.length 0) { return OPENAI_WEB_SEARCH_MODEL_ID } if (configured.includes(::) || configured.includes(/)) { throw new WebSearchError(WEB_SEARCH_UNAVAILABLE, { provider: openai, reason: ${OPENAI_WEB_SEARCH_MODEL_ENV} must be a bare OpenAI model id, not a routed model key, }) } if (!findBuiltinPricingCatalogEntry(text, openai, configured)) { throw new WebSearchError(WEB_SEARCH_UNAVAILABLE, { provider: openai, reason: ${OPENAI_WEB_SEARCH_MODEL_ENV}${configured} has no registered price, }) } return configured }三处校验环环相扣裸模型 id 校验含::或/的聚合路由 key 直接被拒绝因为路由后的模型无法运行托管工具定价目录校验覆盖值必须能在 内置定价目录 中查到注册价格否则在请求尚免费时拒绝——未定价的覆盖必须在 Provider 调用前失败正是 WS-02 的落地默认值模型默认 id 定义在 src/lib/ai-providers/openai/models.ts即OPENAI_WEB_SEARCH_MODEL_ID gpt-5.6-luna平台级角色不进用户可选模型注册表。独立凭据WS-03service.ts 的createConfiguredWebSearchProvider只读服务端环境变量OPENAI_API_KEY缺失即抛 typed 错误——一个未配置的部署必须显而易见而不是在研究上悄悄变得更差绝不降级为无 key 调用或借用 Primary/analysis provider 的凭据。证据校验与失败关闭WS-04Provider 执行边界 hosted-web-search.ts 中证据门控逻辑如下报告为空、completedSearchCalls 0没有完成的托管调用或sources.length 0没有结构化 URL 引用三者任一命中即抛WEB_SEARCH_RESPONSE_INVALID——失败关闭缺失 images 不是失败大量 brief 是纯文本的强索图片会让这些调用误失败用量先于证据门控上报Provider 无论是否返回引用都已为该运行付费静默丢弃被拒绝答案的成本正是未计费用量的来源。关于流式传输hosted-web-search.ts 有一个决定性的细节中断的流会静默停止产出留下与模型未带证据作答不可区分的空输出。这两个是相反事实——前者是传输故障值得重试后者是已完成的非法响应永远不该重试——所以未抵达response.completed的运行一律按传输故障WEB_SEARCH_REQUEST_FAILED报告绝不落入证据校验。这正是 WS-04 的固化。此外OpenAI Responses 流式 API 下顶层output_text字段恒为空正文只存在于尾部messageitem 中hosted-web-search.ts 的注释与代码明示因此真正的正文来源是逐 item 遍历拼接output_text部件。真实证据的投影与上限hosted-web-search.ts 的projectHostedEvidence把原始输出投影为结构化证据并且为单次调用设置硬性上限防止恶意或退化响应淹没模型上下文与 Task 载荷上限项值说明MAX_REPORT_CHARS30 000报告正文最大字符数超出即截断并告警MAX_QUERIES32实际运行的 queries 最大条数MAX_SOURCES32引用来源最大条数按 URL 去重MAX_IMAGES16图像证据最大条数按 URL 去重OPENAI_WEB_SEARCH_IMAGE_RESULTS8请求侧图像结果数量OPENAI_WEB_SEARCH_TIMEOUT_MS300 000整个研究调用超时5 分钟其中超时值的设定来自一次实测真实研究是 agentic 的简单查询秒回而一次 12 次搜索的交叉验证 brief 实测达 136 秒——旧版 120 秒预算会在流中间掐断这类研究因此放宽到 300 秒。生命周期与实时进度WS-05关键事实在 standalone-search.ts 的注释中说得直白Codex owns the search tool the model sees... Codex creates onewebSearchitem per call, with the models own query on it, so a run of three searches renders as three rows without any progress channel. MCP progress cannot do that today, because Codex drops those notifications on receipt (openai/codex#28003).当前 Runtime 的开始事件只有 identityquery/action 为空UI 从开始事件立即渲染该行只显示生命周期与计时完成事件到达后才显示真实 query 与结果页面。查询失败后无论对错都不得用 query 反推状态query 只在协议实际提供后显示。按调用实时结算WS-07/WS-08standalone-search.ts 的recordSearchUsage展示了结算的精确性用量事实的 identity 是buildLlmUsageFactId(web-search, [turnId, requestId])——本次搜索请求而非 Turn一个 Turn 多次研究不会折叠费用用量经editionBilling.settleRealtimeLlmUsage进入 LLM 唯一实时结算入口按priceCatalogLlmUsage(fact)目录零售价结算action: assistant.web_searchtoolCalls由完成的搜索 item 计数而来hosted-web-search.ts因为 OpenAI 正是按调用计费item 流才是实际运行次数的权威记账故障绝不让搜索失败结算异常只记录audit: true的告警日志alert.billing.web_search_usage_unrecorded研究结果照常返回——WS-08 的落地。失败路径的端到端处理standalone-search.ts 的失败路径完整覆盖三种情况用户取消signal.aborted取消 provider attempt仍记录已有用量然后重抛中止凭据缺失/被拒WEB_SEARCH_UNAVAILABLE映射为PROVIDER_CONFIG_UNAVAILABLEHTTP 503这是操作员必须看见的配置故障其余 provider 故障经projectProviderCredentialOwnershipresolveAiProviderAdapter(openai).failure.normalize({ error, phase: search })归一化为 source failure映射为PROVIDER_SEARCH_RESPONSE_INVALIDHTTP 502原样浮出不授权重放。错误词汇定义在 src/lib/web-search/errors.tsWEB_SEARCH_UNAVAILABLE — 能力未配置或凭据被拒重试无济于事 WEB_SEARCH_REQUEST_FAILED — 传输级故障限流、网络、5xx、超时、流提前结束 WEB_SEARCH_RESPONSE_INVALID — provider 已作答但无可用证据 WEB_SEARCH_ABORTED — 用户主动取消绝非 provider 故障Provider 侧的 mapProviderError 在判定时有意区分两件事调用方取消报告为 abort与研究超时报告为传输故障先查 timeout signal 再查 abort慢搜索不会被误标为取消。配置一览该模块的全部配置通过服务端环境变量完成均从process.env读取详见 service.ts环境变量作用说明OPENAI_API_KEY搜索凭据缺失即抛WEB_SEARCH_UNAVAILABLE不降级、不借用其他 provider 凭据WS-03OPENAI_WEB_SEARCH_MODEL搜索模型覆盖可选缺省用平台默认gpt-5.6-luna禁止:://路由 key必须已在定价目录注册价格WS-02任何覆盖模型没有注册价格时会在请求尚免费时以WEB_SEARCH_UNAVAILABLE拒绝杜绝先花钱再让实时结算报错。踩过的坑能力级回归的六次教训原文档记录了该模块演进中六个真实踩坑它们是上述不变量得以固化的来源完整继承如下托管搜索能力曾被连带删除。一次让 app-server 成为唯一 Agent Runtime的提交在同一条正文里同时移除了 Creative Worker、托管搜索与旧交互协议——删除决策以 runtime 归一为唯一判据从未单独评估搜索能力矩阵三件事合并成一句话使回退不可见。实测代价是能力级的同一 brief 直连产生 12 步混合动作与 13 个来源经聚合路由则永远被压平成 1 步且动作细节全被抹掉。结论任何搜索链路变更必须先给出能力矩阵与通道可见性对比不得只论入口是否唯一。能力开关不等于能力。首版只设置能力开关而处于开发中的特性默认关闭、完全不向模型暴露工具第二版又把自定义 provider 的显示名伪装成上游名称smoke 只检查协议 schema 是否包含该类型——schema 与助手正文都不能自证能力必须有真实完成的检索。按名字与文档选型不足以定型。恢复时靠真实运行而非读代码抓到三个缺陷名字正确的模型被 API 拒绝流式下顶层输出字段恒为空、正文只在尾部 item 里短查询侥幸通过而重研究整个丢正文流被超时掐断后静默停止空输出撞上证据校验被误报成答案无依据。前两个说明选型需实测验证第三个固化为 WS-04。发送侧自证不算证据。恢复托管研究的第一版把搜索做成 MCP Operation并为正在读取新建一条 MCP progress 通道改动穿过两个共享契约。真实运行后界面始终只有一行静止的进行中日志证明发出了 12 条递增进度而线程里对应的 part 为 0——Runtime 收到即丢弃。两条教训发送侧自证不算证据四次修复全部作用在已经正确的一段不该为一个未验证的通道改共享契约WS-05。工具拓扑变化必须进入共享 Runtime revision。把搜索从 MCP 切回原生工具后工具代码已替换但持久 Codex Thread 仍执行旧的 MCP-only 指令界面继续投影旧工具行数据库也没有原生 item——而 smoke 只验证配置与 schema没有观察真实模型请求。结论revision 必须由实际契约派生协议 smoke 必须抓取 app-server 发出的工具与指令契约对应 CRR-06A/WS-01/WS-05。UI 不能假定协议外的事实。原生切换后的 UI 仍按已删除的 MCPsources结果读取页面并假定开始事件已有 query真实 Runtime 恰好在开始时发送空 query、完成时才发送 query/action/results导致运行中与完成后都只有工具标题。结论读取原生 results完成后保留 query开始事件没有的事实不得从模型代码或最近请求猜测WS-05。随后又发生过把不得用 query 反推状态过度扩大成不得显示 query导致检索期间界面完全沉默——生命周期只由统一 resolver 判定query 只在协议实际提供后显示当前 Runtime 是完成事件后与结果页面一起保留。小结waoowaoo 的 Web Search 模块是一套刻意收窄的系统一个业务入口WS-01、一个平台级托管模型WS-02、一套独立凭据WS-03、一个证据门控WS-04、一套 item 身份驱动的可见性WS-05、按次实时结算WS-07。它把联网检索严格限定为受限的外部研究能力——不是浏览器、不是创作 Worker、更不是凭记忆作答的伪装。对开发者而言最值得借鉴的是两点一是用契约与错误词汇把传输故障与无证据作答这两类相反事实彻底分离二是用真实运行而非 schema 检查作为能力是否可用的唯一判据。赞分享【免费下载链接】waoowaoo首家工业级全流程 AI 影视生产平台。Industry-first professional AI Agent platform for controllable film video production. From shorts to live-action with Hollywood-standard workflows.项目地址https://gitcode.com/gh_mirrors/wa/waoowaoo点击查看免费下载相关推荐使用 Agno 构建 Parallel 驱动的 Web 研究 Agent从单 Agent 搜索到可部署的 AgentOS 研究应用使用 Agno 构建 Parallel 驱动的 Web 研究 Agent从单 Agent 搜索到可部署的 AgentOS 研究应用 本文基于 cookbook人工智能大模型AI AgentAgent 框架多智能体工具调用RAGAgent 工作流Agent 记忆Backstage Search 架构深度解析可插拔搜索引擎与统一索引流水线Backstage Search 架构深度解析可插拔搜索引擎与统一索引流水线 导读本文基于 Backstage 官方文档《Search Architectu开发者门户后端前端用 Win11Debloat 免费完成 Windows 系统优化一次批量移除 150 预装应用用 Win11Debloat 免费完成 Windows 系统优化一次批量移除 150 预装应用 新装的 Windows 11 用不了多久就会暴露问题C 盘前端UI组件3D渲染跨平台游戏开发上一篇如何在嵌入式设备上使用RKNN Model Zoo实现语音识别下一篇基于仓库源码的 Bitwarden Android 代码评审指南MVVM、Compose 与依赖注入的审查清单与流程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考