我做了一个原生的 iOS BYOK 智能体 App。
它最初叫 iClaw,后来改名为 Palvia。
它有多智能体、记忆、技能、设备上的 JavaScript 沙箱、浏览器工具,还有一小部分与 Apple 健康相关的能力。用户自己带 API Key。这个 App 不卖模型点数,也从来没有试图把自己伪装成任何模型提供商的官方客户端。
一开始,我以为做这类 App 最大的风险会是:
JavaScript 运行时因为会执行代码而被拒; 大模型幻觉导致没法可靠完成任务; 找不到可行的方式把 RAG 做进去。
结果我发现,我脑子里想象的这个世界,太工程化了。
真正的挑战不是把 App 做出来,而是把它变成 Apple 审核员在一台未知设备、一条未知网络、一个未知时间、一种未知心情下能够看懂的东西。
七次提交,六次没通过,从头到尾花了三个多月。
这三个月里,整个过程最稳定的一环不是审核状态,而是那封每周都会来的邮件,里面的内容是“感谢你的耐心”。
对公司来说,三个月可能只是某个季度的一个 OKR。对一个小型 AI App 来说,三个月可能意味着:
一个模型从领先变成普通; 一个有希望的潮流从“新机会”变成“已经做烂了”; 竞争对手从 demo 走到融资,再走到上架 App Store; 用户从“哇,这是新的”变成“哦,我已经装了三款类似的 App”; 一个本来合理的商业模式,慢慢被某个操作系统入口、某个模型厂商、某个超级 App,或者某个跑得更快的克隆吞掉。
所以,这篇文章严格来说不是一份 App Review 攻略,它更像一本航海日志:一个小 App 在 App Store 审核系统里漂流三个月之后,留下的记录。
时间线:一个 App 如何被拆成七个不同人格
第一次提交:Apple 说它崩了,但这个宇宙里没有任何它崩过的证据
2.1.0 | 性能:App 完整性
审核员的消息大致是:
你的 App 在我们启动它的时候意外关闭了。
换句话说:你的 App 一打开就消失。
我不能说这次拒绝完全没道理。
有一小部分 TestFlight 用户报告过启动崩溃,大概 1% 左右,所以也不能排除审核员只是恰好落在了现实的另一个分支上。
问题在于,App Review 会提供测试平台的信息,所以我立刻去查了 TestFlight。
结果很精彩:
对应审核平台没有任何崩溃记录; 同一平台上的模拟器运行一切正常; 冷启动、首次安装、普通流程都正常; 没有异常日志,没有堆栈,没有有用的后续; Apple 没有说 App 卡在了哪个界面; “它崩了”的唯一证据,就是审核员的一句话。
这感觉就像上班时收到一个 P0 工单:
生产环境挂了。没有主机名,没有时间戳,没有 trace,没有日志,没有复现步骤。请尽快修复。
严格来说,我没法证明 App Review 是错的。也许是首次安装的状态,也许是审核网络,也许是某个藏在 Keychain、本地数据库、权限初始化、时间同步或者迁移路径里的隐藏分支。
但开发者能拿到的信息,本质就是这样一句话:它崩了,你自己想办法。
于是我把所有首次启动的路径又加固了一遍:首次安装、冷启动、无网络、弱网络、空数据、权限被拒、Keychain、本地数据库、从旧版本升级、缺少 API Key。不是因为我知道 bug 在哪,而是因为 Apple 说那里有一个。
这大概是 App Review 给上的第一课:
审核反馈不是 bug 报告,它更像一句预言。你没法验证它,但你最好能活下来。
第二次提交:语言里的禁忌比你想象的多
第二次审核一口气给了三个问题。从那时起我开始意识到,Apple 审核的不是一个 App,而是你整个人类表达体系的全部。
你的标题、副标题、完整描述、发布说明、关键词、截图里的文字、截图里的模型名、App 内的说明、支持页面,以及所有你以为没人会仔细看的地方,任何一个都可能在未来的某个下午,变成一条拒绝理由。
1. 副标题里不能写 iPhone
5.2.5 | 法律:知识产权
我在副标题里写了“iPhone”,Apple 说不行。
这个逻辑我能理解:iPhone 是 Apple 的商标,不是可以随手丢进产品文案里的普通名词。但作为一个 iOS 开发者,那种情绪体验差不多是:
我做了个跑在 iPhone 上的 App,我说它和 iPhone 有关,Apple 说:请不要用“iPhone”。
所以我把它删了。这件事没什么好争的,但它教会我一件事:在 Apple 的世界里,iPhone 不属于语言,它是一个必须被放对位置、被正确引用、最好尽量少碰的法律对象。现在我看到任何 Apple 产品名,第一反应都是:这几个字母,值不值得我再动一次包?
2. 中国区上架不能提 OpenAI 或 Anthropic,所以我给同一个 App 建了另一个模型宇宙
5 | 法律
第二个问题是,中国区的商店元数据、文案和截图里,不能提到 OpenAI、Anthropic 或它们的产品。
这不只是删几个字的事。在 App Store 里,“文字”不只存在于描述里。审核员可能会看副标题、长描述、发布说明、截图文字、截图里可见的模型列表、关键词、支持页面,以及那些你以为只是产品展示的部分。
所以到最后,我没有只是把品牌名打码,也没有把一切都写成“支持某些模型服务”“支持兼容 API”这种企业采购腔。我直接把中国区商店的整套模型叙事重写了一遍:OpenAI 和 Anthropic 的提及,变成了 GLM、DeepSeek 和 Qwen。
同一个 App,在不同地区就有了不同的 AI 宇宙。中国以外的用户看到一份模型列表,中国的用户看到另一份。底层还是同一个 App、同一个智能体、同一个设置页,用户依然得自己带 Key。变的只是 App Store 截图里展示的那些模型,也就是那些据说在服务人类的模型。
从产品本地化的角度看,这并非不合理。GLM、DeepSeek、Qwen 确实是中国用户可能去配置的服务。但作为开发者的体验,这真的很像互联网形态的多重宇宙:
你以为你在上传截图,实际上你在为不同地区生产不同版本的现实。你以为你在做本地化,实际上你在维护多个各自都能通过审核的世界观。
3. 你得解释 HealthKit / CareKit 是干什么用的
2.5.1 | 性能:软件要求
第三个问题是,HealthKit / CareKit 的用途讲得不够清楚。这条表面上看很合理,所以我加了一段说明:只有在用户主动授权后才会读取数据;可能包含步数、睡眠等健康数据;帮助智能体给出更贴合用户日常状态的建议;用户随时可以拒绝授权或关闭;不会用于广告或其他无关用途。
我以为那就是标准答案。
后来第五次审核告诉我,在文档里解释不算数。你得把它做成审核员在 App 里点两下就能撞见的东西。
这就像申请装修一间公寓。你递交了建筑图纸,物业经理说:图纸不算数,你先把它建出来,我再看看你是不是真的在装修。
第三次提交:Apple 告诉我它加速了审核,然后把我留在“审核中”里思考关于加速的哲学
第三次提交之后,App 很快进入了“审核中”。
这个状态会制造一种很特别的幻觉。看到“审核中”,你自然会想象一个审核员打开了 App,点过主屏,检查过权限,读过审核备注,复制过 API Key,或者至少把这个构建放进了当天要处理的一堆事项里。
后来我才明白,“审核中”更接近一种哲学状态。它只意味着你的 App 不再排在队列外面。到底有没有真人在审、审到哪一步、审核员还记不记得这个 App,这些开发者都观察不到。它就那么安静地待在那里,处于“审核中”。
一开始我给 Apple 发邮件问状态。第一封回复里,Apple 甚至给了我好消息:
这个 App 已经被准予加急审核。
我并没有申请加急。Apple 主动告诉我,它注意到了我的情况,并加急了审核。有那么一瞬间,我感受到了现代化平台服务的温暖。“加急审核”听起来像是一个具体的承诺:我们知道你已经等了很久,我们会把它排到前面,事情应该会快起来了。
然后它继续待在“审核中”。
整整一个月。
加急。审核中。一个月。把这三个词放在一起,你会得到一种抽象的 Apple 之美。
我最终逐渐理解了,“加急”可能并不意味着“更快完成”。它可能意味着平台开始在精神上更关心你了。
之后我每周发一封邮件,尽量让每个问题都具体:有没有实质进展;有没有缺测试信息;审核用的 API Key 需不需要更新;审核员有没有成功进入需要 Key 的路径;还有没有别的我能提供、修复或澄清的东西。
Apple 的回复出奇地稳定。官方措辞总是很客气,但核心永远一样:审核还在进行中,请耐心等待,完成后会通知你。连着读了几周之后,这段精神内核听起来越来越像:永远不放弃你。
我问:卡在哪了?
Apple:不要放弃。
我问:API Key 有没有被成功用到?
Apple:不要放弃。
我问:加急审核还要多久?
Apple:不要放弃。
我们建立了一段非常稳定的客户关系:我持续地提供焦虑,Apple 持续地提供鼓励。它唯一没有持续提供的,是审核的进度。
那段时间我专门去 Apple Developer Forums 找类似经历。起初我只想回答一个问题:是我的 App 本身有哪里特别不对劲,还是 App Review 偶尔真的会把某些人忘在某个状态里?
然后我找到了一个非常熟悉的世界。有些开发者卡在“等待审核”里卡了半个月。有些进入了“审核中”,然后一个月没有任何变化。有些说自己的审核账号、测试服务器、测试订阅都快过期了。有些怀疑根本没人打开过 App。有些一封接一封地发邮件,或者预约 App Review 咨询,结果状态纹丝不动。
那些帖子通常有两类回复。第一类是 Apple 的模板:“感谢你的反馈。我们正在调查,会在 App Store Connect 里联系你提供进一步协助。如果你在审核期间继续遇到问题,请联系我们。”第二类是其他开发者的跟进。起初语气还算克制,比如“我也是,还在等”“已经十天了”“最近有人通过吗”“我收到了同样的回复”。但越往下翻,语气会慢慢变:
第三周了。还在审核中。
我的测试账号快过期了。
我取消了,又重新提交了。
重新提交之后,我又回到了“等待审核”。
我什么反馈都没收到。
我放弃了。
Apple Developer Forums 上最持久、也最能形成共识的东西,不是某个 API 的最佳实践,而是这个:所有人都在等,没人知道自己到底在等什么,所有人都收到了同样的回复。然后某一天,有人被轻轻拒了,有人取消又重提,还有人从此再也没回来更新后续。
这就像一群人站在机场航站楼里,盯着同一块航班信息屏。状态一直是“延误”。没有新登机口,没有预计起飞时间,没有任何解释。每隔一会儿,广播响一次:感谢你的耐心。
你去论坛找解决方案,结果找到的是一群陪你一起被安慰的人。
最后,这个故事迎来了一个特别适合 AI App 时代的结局:App 还在“审核中”,但为审核准备的 API Key 先过期了。所以我只能自己撤回这次提交。
整条链是这样:提交 → 进入“审核中” → Apple 发邮件说审核已加急 → 还在“审核中” → 每周跟进一次 → 每周收到一次“请耐心等待” → API Key 过期 → 撤回 → 回到起点。
从某种意义上说,Apple 从没撒谎。它没有放弃审核我的 App。它只是很久很久,都没有再明显地为它做点什么。
一个可能为 Apple 开脱的理由:也许 AI 生成的 App 真的淹没了审核队列
站在 Apple 的角度,找到一个解释并不是不可能。
做 AI App 的门槛已经低到荒谬。以前,谁想把一个 App 做出来,至少得熟悉 Xcode、Swift、UI、后端服务、鉴权、支付、崩溃处理。然后花上好几个月,把“我有一个想法”变成“这东西至少能装进手机”。
现在的路径更像这样:想一个 AI 点子 → 打开 Cursor、Claude Code 或 Codex → 生成一个 SwiftUI 界面 → 接几个模型 API → 加一个订阅页 → 三天后以《AI Life Copilot Pro》之类名字提交到 App Store。
在供给端,Apple 的审核队列可能真的在面临一场 AI 时代的洪流。每天它可能要收到无数个披着不同图标的聊天壳子:心理治疗师、健身教练、关系顾问、PDF 摘要器,全都是靠一段提示词区分开的;每个都再挂一个订阅页,一起涌向 App Review。
审核员可能上午检查一个“AI 睡眠伴侣”,中午检查一个“AI 情绪安全屋”,下午检查一个“AI 商务助手”,晚上又遇到一个带多智能体、记忆、工具调用、用户自带 API Key、还能访问健康数据的 App。单靠一眼,可能真的很难判断:这是精心设计的产品,还是另一个带订阅页的提示词壳子?
所以审核慢,也许并不是因为 Apple 故意怠慢,而是因为整个系统被生产成本极低的 AI 时代供给给淹没了。
但这个解释并不会让小团队好受多少。大公司面对拥堵的队列,可以多雇审核员、重新设计流程、加自动化、让状态更透明,或者给开发者更明确的 SLA。至少,它还能告诉人们流程卡在哪。而小开发者面对拥堵的队列,通常只能每周发一封邮件,收到一句“感谢你的耐心”,去论坛看看别人是不是也在等,然后盯着看谁先过期:你的 API Key、你的测试账号,还是你那个想法的市场窗口。
这是一出非常 AI 时代的结构性喜剧:
AI 让做 App 变快,于是提交的人变多,于是审核变慢,于是小团队花更多时间等待。到头来,稀缺的不是生成代码的能力,而是进入 App Store 的时间。
Apple 可能并不是故意拖延你。它只是恰好站在闸门前,拦着那波 AI App 的洪水。而闸门后面,是一眼望不到头的 AI Copilot Pro 队伍,不幸的是,其中也包括你。
第四次提交:iClaw 不行,因为它长得像 OpenClaw 的亲戚
1.1.6 | 安全:不当内容
第四次提交终于得到了一条清晰的回复。核心意思是:我的元数据可能误导用户,让他们以为这个 App 和 OpenClaw 有关联。
名字原本叫 iClaw。我当初觉得它有点早期 Apple 的味道,适合做一个移动端智能体。Apple 把它理解成了 OpenClaw 的 iOS 客户端。
App Review 最强大的一点是:Apple 不需要证明你确实在冒充谁,它只需要相信用户可能会误解。而用户会不会误解,最终也是由 Apple 替用户来回答的。
所以 iClaw 死掉了。我没有继续争辩说我们没有任何官方关系、它不是客户端、我没用过那个项目的 logo、“claw”只是个普通单词、我也不是故意蹭流量。因为在审核的语境里,这些解释几乎没有实际价值。一旦“看起来像”成立,你就已经踩在整改的道路上了。
所以我很干脆地改了名:
iClaw → Palvia
随之而来的,是整个 App 身份的彻底重建:App 名称、图标、App 内文案、网站、支持页面、截图、宣传物料、元数据,还有,是的,中国工信部的备案。
没错,重新备案了一次。一个产品名和另一个产品名形成了语义上的关联,结果我得再走一遍行政流程。互联网的某个角落扇动了一下翅膀,一个开发者又要重新填一次表。
顺带说一句,重新备案其实比再过一次 Apple 审核容易多了。
App 备案流程经常被人吐槽。大家以为它意味着填表、交材料、等待、补材料、电话确认、再等待,最后在某个由无名氏维护的网站的最后一步报一个错。
但实际体验基本上就是:提交,等待,通过,一天之内。没人让我解释什么是智能体,没人问我为什么叫 Palvia,没人找我要 API Key,没人问我跟 OpenClaw 有没有什么精神上的亲缘关系,没人告诉我 App 意外关闭了但不给日志,也没人要求我每周发邮件证明自己还活着。它甚至比 Apple 把一个构建从“等待审核”挪到“审核中”还快。
这给了我一个有点失礼但又非常真实的印象:一个常被看作额外行政负担的流程,在整个发布链条里,反而是最像现代服务交付的那一环。至少它有一个输入、一个处理、一个输出。
而在这第四次拒绝之前,这个 App 已经在“等待审核”里待了半个月。这一次它甚至没走到“审核中”这个哲学状态。如果第三次尝试像一份躺在审核员桌上、没人翻页的文档,那这一次就像一份还排在接待台队列里的文档,工作人员一直告诉你,系统正在处理。
之后的几次尝试,终于回到了更“正常”的节奏:大约每周出一次结果。只是结果通常又是一条拒绝理由,而不是通过。
第五次提交:HealthKit 文档不算数,我明明提供的 API Key 也不算数
第五次提交是整个流程里最有 App Review 味道的一次:一半非常合理,一半感觉像是系统在让我解一道谜。
HealthKit 用例在 App 内部不够显眼
Apple 说,虽然我在文档里解释了 HealthKit 的用途,但它在 App 内部不够显眼。
于是我立刻加了一段落地流程:Apple 健康能力的介绍、授权用途的说明、健康功能的入口、设置里的 Apple 健康分区、权限状态,以及一条更清晰的产品路径。总之,我把 HealthKit 从“作为功能存在”变成了“审核员一进 App 就能遇到的东西”。
回头看,我觉得这是对的。审核员不会替你把逻辑推理出来,用户也不会。你不能指望别人从“App 请求了一个权限”加上“文档里提过一次”,就推断出完整的健康用例。你得把门建起来,在招牌上写清 Apple 健康,把功能放在门后,再在门口贴一张便条:我们真的会用这个权限。
Apple 说:你没有提供 API Key
然后 Apple 说,它无法体验完整功能,因为我没有提供 API Key。
问题是,我确实提供了。它就在审核备注里。我反复检查过:Key 有效、有可用额度、没过期、正常使用没问题、填对了位置、还带了使用说明。我甚至拿了一台干净的 iPad,从头到尾自己走了一遍审核路径。
但审核那边说,没有提供 Key。
那一刻,开发者最自然的反应是:你能不能再看一眼?但你真的没法这么写。你不是在跟一个会在 Slack 上回复你的同事协作。你是在向一个握有最终决定权、却几乎不透露任何过程信息的系统提交补充材料。
于是我把审核备注重写得更详细,详细到接近给幼儿园小朋友写说明书的地步:打开 App → 点这里 → 点那里 → 在这里输入 API Key → 复制下面这段文字 → 选择这个服务 → 选择这个模型 → 输入这条测试提示词 → 如果不行,先检查前面那八步。
更微妙的是,从 API Key 的使用记录来看,我甚至怀疑,当这个 App 最终通过审核时,审核员可能根本没走到需要 Key 的那一步。换句话说:我先是因为“没有提供 API Key”被拒,我重写了说明,然后 App 通过了,而审核员可能压根没用到那个 Key。
这倒不是说审核员有恶意。只是从那时起我开始明白:
审核反馈不是审核过程的日志。你收到的是一个结论。中间发生了什么,属于一个你看不见的世界。
第六次提交:改名之后,关键词里的旧世界也得一起消失
1.1 | 安全:不当内容
第六次审核说,元数据里仍然包含引用不当内容或服务的词或图。
我把所有地方又过了一遍,最可能的元凶,是留在关键词里的一条和 OpenClaw 有关的旧引用。
这很有意思。我已经因为 iClaw 和 OpenClaw 的关联把 App 改名了。但显然改名还不够:把那个名字留在关键词里,照样可能触发一次拒绝。
于是我把元数据当成一次墓地清理:移除 OpenClaw;移除所有可能暗示第三方关联的词;移除所有看起来像导流、蹭流量、生态搭车的词;把每一个字段都搜一遍,包括名称、副标题、关键词、描述、截图、发布说明、网站和 App 内文案。
从那以后,我对关键词的理解变了:
你以为那是 ASO,Apple 把关键词当成一份人格档案。你放进去的每一个词,都有可能在某一天引来一个问题:你为什么会和这个东西有关联?
第七次提交:终于上架 App Store,Apple 审核宇宙暂时允许这个 App 存在
第七次提交终于过了。
看到通过通知的时候,没有那种史诗般的胜利感,更像是:行吧,这个特定构建,恰好通过了这个特定时空里的审核状态机。
回头看,App Review 并不是完全不讲理。很多单个问题都说得通:启动崩溃要修;HealthKit 的用途要解释;用户不应该对第三方关系产生误解;审核员应该能体验核心功能;Apple 商标不能乱用;地区内容要符合地区要求。
问题不在于 Apple 有规则。问题在于,小团队得在一个极度不对称的时间系统里遵守这些规则。
在开发者这一侧,产品窗口按天算,潮流按周算,竞争对手按月算,现金流按季度算,人力按人天算。
在审核这一侧,可能是一周、半个月、一个月。App 可能已经在“审核中”,可能已经“加急”了。你可能拿到一份没有日志的崩溃报告。你可能被要求提供一个可能根本不会被用到的 API Key。某个词可能出现在元数据某个你遗忘的角落里。你可能会每周收到一封邮件,但每封邮件都只是让你继续等。
对平台来说,这些只是审核过程里的普通波动。对一家小公司来说,那些波动可能就是一个商业模式的寿命。
这对 AI 产品尤其如此。一个用户今天觉得新鲜的能力,三个月后可能已经被某个操作系统入口、某个模型厂商、某个超级 App、某个开源项目、某个竞品克隆,或者一次新模型发布给吞掉了。有时候不是你的产品不够好,而是你还在等审核的时候,别人已经把这个需求做成了默认功能。
所以到最后,我觉得 App Store 审核对小团队最残忍的地方,不是它拒绝你。而是它可以表面上什么都没做错,却依然让你在最关键的那个窗口期里,慢慢失去速度。
大公司可以把审核当成一个流程。小公司有时候只能把它当成一项风险资产。
结尾:审核不是测试,是给一个看不见的观众的戏剧
如果我再做一个依赖外部模型、权限和审核环境的 App,我会默认:
审核可能遇到一个我无法复现的崩溃; 审核可能看不到审核备注; 审核可能看到了审核备注,但没按说明走; 审核可能要求一个 API Key,但未必真的用它; 审核可能整整一个月一动不动; 审核可能说它加急了,但“加急”用的可能不是人类的时间单位; 审核可能在我忘了它存在的某个元数据字段里,发现一个词; 审核可能让我解释一件我已经解释过的事; 审核可能不在乎我花了多少时间,它只在乎当前这个构建,是否恰好落在它接受的那个表达边界之内。
所以产品应该朝着这个方向去设计:让首次启动尽量不依赖其他东西;让核心路径尽量显眼;让权限用途一目了然;让审核环境尽量活得久;给外部 API 留好优雅的降级路径;把审核备注写得像是给陌生人看的说明书;让元数据不背任何历史包袱;选一个不像任何热门项目移动端亲戚的名字。
这并不是在说 Apple 不应该审核 App,也不是说每一条拒绝都不合理。站在小开发者的角度,审核最吓人的不是严格,而是:
严格 + 不透明 + 不确定 + 慢。
前者可以用工程去解决,后者可以直接消耗一个想法最值钱的东西:时间。
如果互联网产品的竞争是一场速度赛,那审核队列本身有时也是这场比赛的一部分,而且是那部分小公司最承担不起、最绕不过去、也最难向投资人或者用户解释的部分。
对所有正在做自己想法的人,我祝你们:
少一次无法复现的崩溃; 少一个元数据地雷; 少一次“你没有提供 API Key”; 少一次改名; 少一次重新备案; 少一个月等待; 还有,少一点那种你坐在审核队列里,眼睁睁看着自己的想法从“值得做”,变成“已经有人做完了”的感觉。
最后是 App Store 和 GitHub 的链接,欢迎反馈:
App Store GitHub
作者:ShadowMov's Blog
原文标题:From iClaw to Palvia: Seven Submissions, Six Rejections, and an App That Nearly Died in Apple's Time Dilation
发布平台:ShadowMov's Blog
原文链接:https://shadowmov.com/en/posts/palvia-now-available-on-app-store/
许可协议:CC BY-SA 4.0
相关链接:
App Store GitHub https://www.youtube.com/watch?v=dQw4w9WgXcQ
相关阅读:
生产级 AI Agent 评估指南:工具调用、推理质量与输出准确性

夜雨聆风