AI 扫描小票记账:Claude 与 Codex 工作流
用 Claude 或 Codex 识别小票并写入 Expense Budget Tracker:提取总额、预览具体写入、明确批准,再读回核对账本记录。
咖啡馆小票上的总额是 $27.82,银行卡通知还停在“待处理”,纸边已经在笔记本电脑旁卷了起来。再放一周,商户名、小费和分类只会更难想起来。
趁小票还在手边,Claude 或 Codex 就能把照片变成一份待审核的记账草稿。智能体读取照片中能看清的内容,对照账本里的账户、分类和近期记录,再逐字展示准备执行的写入内容。只有你明确批准这一次写入后,账本才会发生变化。
这里要先讲清楚产品边界。**Expense Budget Tracker 没有内置摄像头或小票扫描器,也不存储小票图片。**你所使用的 Claude、Codex 或模型提供商负责识别你提供的图片,Expense Budget Tracker 只保存经过批准的结构化账本数据。
能不能识别图片,取决于你使用的 AI 客户端和模型配置。Anthropic 文档说明 Claude 可以处理和分析视觉输入,而 OpenAI Responses API 接受文本、图片或文件输入。这并不表示每个 Claude 或 Codex 客户端都能自动打开本地照片:客户端还必须支持附件或能够访问相应的文件路径,并获得你的许可。图片识别很有用,但金额仍需要人工审核。
![]()
这套工作流里的“扫描器”具体做什么
这是一套由 AI 辅助的小票记账工作流,不是应用内置的摄像头功能。
可以把它理解为一次分工:模型处理你提供的小票图片,Expense Budget Tracker 接收经过批准的账本数据。
| 阶段 | 发生什么 |
|---|---|
| 拍摄 | 你给小票拍照,或把扫描文件保存在 Claude 或 Codex 可以访问的位置。 |
| 解读 | 模型读取商户、日期、小计、折扣、税费、小费、总额、币种和付款线索等可见字段,并标出任何不确定之处。 |
| 检查账本 | 智能体读取选定的 Expense Budget Tracker 工作区、实时 schema、账户、分类和疑似重复的记录。 |
| 预览 | 智能体展示提取出的事实、不确定项、分类选择和准备执行的具体写入内容。 |
| 批准 | 你明确批准这一次写入,或纠正内容并要求生成新的预览。 |
| 写入并核对 | 智能体写入一笔结构化交易,再从账本中读回核对。 |
| 对账 | 银行卡或银行交易正式入账后,你把它与已经记录的小票条目匹配,而不是再导入一份副本。 |
最后的对账步骤,才会让这套 AI 扫描小票记账流程留下可审计的账本。正确读出 $27.82 只是开始。这笔记录还必须使用正确的工作区、账户、正负号、币种和分类,也不能误判重复记录。
如果你需要的是一款内置拍照入口、还能保存小票附件的应用,这款产品并不适合。Expense Budget Tracker 负责接收和保存结构化财务数据;需要长期保留的小票图片,仍应放在你平时使用的文件系统、文档归档工具或其他服务中。
直连 Agent API 与远程 MCP 连接器,二选一
Expense Budget Tracker 支持两种连接路径。它们访问的是同一类财务数据,但认证凭据和客户端的工作方式不同。
供 Claude Code、Codex 和支持 HTTP 的智能体使用的直连 Agent API
直连 API 的入口是:
https://api.expense-budget-tracker.com/v1/
智能体先调用 GET /v1/,按照发现响应中的说明继续,通过电子邮件验证码完成接入,并将返回的长期有效 ApiKey 存放在聊天记忆之外。随后,它调用 /v1/me,列出并选择工作区,检查 /v1/schema,通过 /v1/sql/query 读取数据,再通过 /v1/sql/execute 提交一次经过批准的变更。
如果 Claude Code 或 Codex 已经能够打开你电脑上的小票文件并发起 HTTP 请求,这条路径很合适。AI 智能体设置指南介绍了接入顺序,API 参考文档则说明当前的读写约定。更完整的 Claude Code 终端工作流可参阅如何用 Claude Code 追踪支出并管理预算。
使用浏览器 OAuth 的远程 MCP
支持 MCP 的客户端也可以连接到:
https://mcp.expense-budget-tracker.com/mcp
这条路径通过浏览器 OAuth 授权,使用 MCP 访问令牌和刷新令牌,而不是 Agent API 的 ApiKey。读取时使用 list_workspaces、get_schema 和 sql_query 等工具;写入则需要单独的 expenses:write 权限,并通过 sql_execute 执行。
远程连接器不会因此获得你电脑上照片的访问权限。客户端或模型仍需通过自身支持的附件或文件机制获取小票。MCP 连接器指南介绍了 OAuth 流程和权限范围。
无论选择哪条路径,顺序都一样:先识别小票,再检查账本,然后展示预览,最后对这一次写入单独授权。
一张小票,从照片到入账的完整流程
假设你拍了一张清晰的餐厅小票,内容如下:
| 小票字段 | 可见值 |
|---|---|
| 商户 | North Street Cafe, New York |
| 日期和时间 | 2026 年 8 月 31 日 12:17 |
| 餐食小计 | $24.00 |
| 折扣 | -$2.00 |
| 税费 | $1.82 |
| 小费 | $4.00 |
| 最终总额 | $27.82 |
| 付款线索 | 尾号为 4242 的 Visa 卡 |
金额能对上:$24.00 - $2.00 + $1.82 + $4.00 = $27.82。这项检查很有用,但只能证明数字彼此吻合,不能证明目标账户或分类正确。智能体仍然需要查看账本。
1. 先确认目标,再解读照片
要求智能体识别并展示:
- 当前登录身份对应的账户信息
- 准确的工作区名称和 ID
- 目标账本账户及其币种
- 小票日期和时区
- 小票币种
在这个例子中,假设用户确认工作区是 Personal,ID 为 workspace-personal-example;账户是 a-visa_4242-usd,币种为 USD;小票时间按纽约当地时间解释。这些都是假设值,并非产品内置的工作区、账户或分类名称。银行卡末四位只能提供线索,不能成为智能体自行选择账户的依据。如果两张已保存的银行卡都以 4242 结尾,智能体应该停下来询问究竟使用了哪一张。
2. 读取实时 schema
智能体应该调用:
GET https://api.expense-budget-tracker.com/v1/schema
/v1/schema 返回的内容,才是当前可用数据库关系、字段、约束和写入规则的准确信息。文章中的示例可能过时;生成 SQL 之前,智能体应以实时 schema 为准。按照当前账本 schema,执行 INSERT 时必须明确包含已经确认的 workspace_id。为 API 密钥选择并保存工作区,只会设置请求上下文,写入行时仍不能省略这一列。
3. 分别提取事实、线索和不确定项
一份可靠的提取报告应该像这样:
| 字段 | 提取值 | 可信度或待确认问题 |
|---|---|---|
| 商户 | North Street Cafe | 清楚 |
| 交易时间 | 2026-08-31 12:17 当地时间 |
清楚;用户已确认纽约时区 |
| 币种 | USD | 根据 $ 和已确认地点判断;用户已确认账户币种 |
| 小计 | 24.00 |
清楚 |
| 折扣 | -2.00 |
清楚 |
| 税费 | 1.82 |
清楚 |
| 小费 | 4.00 |
清楚 |
| 实付总额 | 27.82 |
清楚,且金额计算一致 |
| 付款方式 | 尾号为 4242 的 Visa 卡 |
线索与用户确认的账户匹配 |
不要把看不清的文字硬塞进一个确定字段。如果总额的最后一位可能是 2,也可能是 7,正确的输出应该是“总额不清楚;需要另一张图片或人工确认”,而不是猜一个看起来合理的数字。
4. 决定记录一笔交易,还是拆分分类
这张小票上的消费全是餐饮,因此,如果 Dining Out 已经是工作区中的现有分类,记录一行账本数据就很合理。税费、折扣和小费共同解释了最终金额;在普通个人预算中,不需要为它们分别创建记录。
如果一张超市小票同时包含食品、药品和厨房电器,就可能需要拆分分类。在当前账本模型中,这意味着创建多行记录:它们通常属于同一个账户,并共享同一个 event_id。每一行都有自己的分类和带正负号的金额,这些金额之和必须准确等于原始付款金额:对于一笔 $27.82 的支出,应合计为 -27.82。
预览应该说明如何分摊整张小票共同承担的税费、折扣、服务费和舍入差额。有些小票适合按比例分摊,有些则适合把明确对应某件商品的折扣分给该商品。没有一条规则适合所有小票。如果只能靠猜,就保留一行并使用范围更广的现有分类,或者询问用户。
智能体应该先查询账本中的现有分类,不要为了看起来整齐而临时发明一套新分类:
SELECT category, COUNT(*) AS use_count
FROM ledger_entries
WHERE kind = 'spend'
AND category IS NOT NULL
GROUP BY category
ORDER BY use_count DESC
LIMIT 100
5. 查询可能重叠的记录,只返回候选项
拟定插入语句前,先查询已确认账户在小票日期附近的记录。对于示例小票,可以使用这条范围较窄的查重查询:
SELECT entry_id, event_id, ts, account_id, amount, currency, category, counterparty, note, external_id
FROM ledger_entries
WHERE event_id = 'receipt-2026-08-31-north-street-cafe-2782'
OR (
account_id = 'a-visa_4242-usd'
AND currency = 'USD'
AND ts >= '2026-08-29 00:00:00-04'
AND ts < '2026-09-03 00:00:00-04'
AND amount = -27.82
)
ORDER BY ts
LIMIT 100
智能体将这条语句发送到 POST /v1/sql/query。这里的 event_id 是智能体为该事件创建的字符串值;如果拆分分类,所有相关记录都会共享这个值。它可以用来组织多行记录,也方便精确查询,但数据库不会把它当作唯一的去重键。完全相同的 event_id 是值得调查的强信号,不代表可以删除或覆盖任何内容。
日期相近、金额相同、商户类似的记录也只能算重复候选项。两笔真实发生的咖啡馆消费完全可能金额相同;银行卡扣款从待处理变为正式入账时,也可能出现不同的商户名称或时间戳。
如果账本里很可能已经有匹配记录,预览应该把候选项和小票提取结果并列展示。用户解决冲突之前,不应再提出插入操作。
6. 展示完整账本记录和将要执行的 SQL
假设重复查询没有返回候选项,而且 Dining Out 是已有分类。此时,只读预览就可以给出具体内容:
| 账本字段 | 准备写入的值 |
|---|---|
| 工作区 | Personal (workspace-personal-example) |
| 账户 | a-visa_4242-usd |
| 时间戳 | 2026-08-31 12:17:00-04 |
| 金额 | -27.82 |
| 币种 | USD |
| 类型 | spend |
| 分类 | Dining Out |
| 交易对方 | North Street Cafe |
| 备注 | Receipt subtotal 24.00; discount -2.00; tax 1.82; tip 4.00 |
| 重复候选项 | 所查时间范围内没有候选项 |
预览还应该逐字展示准备发送的 SQL:
INSERT INTO ledger_entries (
event_id,
ts,
account_id,
amount,
currency,
kind,
category,
counterparty,
note,
workspace_id
)
VALUES (
'receipt-2026-08-31-north-street-cafe-2782',
'2026-08-31 12:17:00-04',
'a-visa_4242-usd',
-27.82,
'USD',
'spend',
'Dining Out',
'North Street Cafe',
'Receipt subtotal 24.00; discount -2.00; tax 1.82; tip 4.00',
'workspace-personal-example'
)
这仍然只是预览。智能体应该说明预期效果——在已确认的工作区中新增一行账本记录——然后等待“批准这一次写入”之类的明确授权。只要任何值发生变化,包括工作区、账户、金额、分类或备注,旧预览就会失效,必须重新生成。
7. 只执行批准过的语句,再读回核对
获得批准后,直连 Agent API 会把准确语句发送到:
POST https://api.expense-budget-tracker.com/v1/sql/execute
随后,智能体通过 /v1/sql/query 进行核对:
SELECT entry_id, event_id, ts, account_id, amount, currency, kind, category, counterparty, note, workspace_id
FROM ledger_entries
WHERE event_id = 'receipt-2026-08-31-north-street-cafe-2782'
LIMIT 100
读回结果必须恰好包含一行,并且与批准过的预览一致。只收到 HTTP 成功响应,却没有逐项比较,核对工作就还没完成。
8. 银行卡扣款正式入账后再对账
小票记录的是柜台当场发生的交易,正式入账的银行卡交易则确认最终计入账户的金额。日后这笔交易出现在银行卡导出文件中时,查询同一账户、金额、日期范围、商户线索和任何稳定的来源 ID。如果证据表明它对应先前根据小票写入的那一行,导入时就应排除对账单中的这一行,而不是再创建一笔账本记录。
如果正式入账的金额不同,不要创建余额调整记录。先调查是否读错了小票总额、小费后来发生变化、预授权金额变成了最终结算金额,或银行卡对外币交易进行了换算。把修正内容明确展示出来,再单独请求批准。
处理较大批次时,银行对账单导入指南介绍了重叠期间和转账的处理方式。预算与银行余额对账指南则说明如何把已经入账的账户活动与确认无误的余额进行比较。
小票识别最容易出问题的地方
小票照片本来就不规整。谨慎的 Claude 或 Codex 小票识别流程应该主动暴露下面这些问题,而不是悄悄补齐信息,只求结果看起来顺滑。
| 棘手情况 | 安全处理方式 |
|---|---|
| 照片模糊、过暗、折叠或裁切不全 | 标出无法读取的字段,要求提供新图片或人工填写数值;只要总额、日期或币种仍不确定,就不要写入。 |
| 小计与总额 | 重新计算照片中看得见的各项金额,并使用实际支付的最终金额。检查税费是已经包含在内还是另行加入,也要确认总额中是否已经包含服务费。 |
| 小费 | 区分印刷的建议小费、手写小费、银行卡预授权金额和最终总额。之后再与正式入账的银行卡金额比较。 |
| 折扣和优惠券 | 保留最终实付总额。如果拆分分类,应展示折扣如何分摊,而不是默默分配。 |
| 退货和退款 | 把退货小票视为一笔待处理或已完成退款的凭证,不要当作普通收入。只有当退款状态和金额明确时,才在收款账户中将它记录为单独的结构化条目,并在正式入账后进行对账。 |
| 分类拆分小票 | 为相关记录使用同一个 event_id;展示每个分类的带正负号金额、分摊规则、舍入决定和合计值。各行之和必须等于最终实付总额。 |
| 现金还是银行卡 | 使用实际付款账户。照片中的商户标志,甚至画面里出现的钱包,都不能证明付款方式;小票没有付款方式一栏时应询问用户。 |
| 外币 | 明确保留小票币种。如果银行卡账户使用另一种币种,不要虚构汇率或结算金额;等待扣款正式入账,或取得准确且经过确认的金额。 |
| 重复候选项 | 比较日期、带正负号金额、账户、币种、商户和任何稳定的来源标识符。把候选项交给用户决定,不要擅自跳过或插入。 |
税务分类同样不能想当然。小票可以作为记账凭证,但模型不应只凭商户名称就认定一笔消费属于可抵扣的业务支出,也不能据此给出法律或税务结论。税务或报销所需的文件应保存在你自己的文档系统中;涉及个人具体情况的问题,请咨询具备资质的专业人士。
可直接复用的 Claude 或 Codex 提示词
智能体连接好以后,粘贴下面这段提示词,再替换方括号中的值。刚上手时,最好每次只处理一张小票。
处理 [准确文件路径或附件] 中的小票图片,并使用 Expense Budget Tracker。
如果使用直连 API,请从 https://api.expense-budget-tracker.com/v1/ 开始,
按照发现响应中的说明继续。使用保存在聊天记忆之外的 ApiKey。如果当前连接使用 MCP,
则调用 MCP 的工作区/schema/查询工具,并遵守下方相同的批准边界。
先不要写入任何数据。使用直连 API 时,展示我的 /me 账户信息。列出可用工作区,
让我确认准确的工作区。检查 /v1/schema(或调用 get_schema)。查询可用账户,
让我确认准确的账户及其币种。不要仅凭银行卡末四位推断账户。
读取图片,提取商户、小票日期和时间、币种、小计、税费、小费、服务费、折扣、
退货、最终总额和付款线索。标出任何看不清、裁切不全、有歧义或金额计算不一致的内容。
绝不要编造缺失值。告诉我适合使用一行账本记录还是拆分分类;提出分类名称前,
先查询我已有的分类。如果拆分,请让相关记录共用一个 event_id,并证明各行带正负号的
金额之和等于最终总额。
使用只读查询,检查已确认账户和日期范围内重叠的账本记录。展示重复候选项及其证据;
不要因为日期和金额相同,就认定它一定是同一笔消费,也不要认定它一定是一笔新消费。
然后展示只读预览,其中包括已确认的工作区、准确账户、带正负号的金额、准确币种、
时间戳、类型、现有分类、交易对方、备注、适用时的每个拆分金额,以及重复候选项。
逐字展示准备执行的 SQL,在每条 INSERT 中包含已确认的 workspace_id,并说明预计受影响
的行数。不要创建余额调整记录、猜测出的换算金额或额外记录。
停下来,等待我对这一次具体写入给予单独且明确的批准。获得批准后,只通过
/v1/sql/execute(或 sql_execute)发送获批语句。通过 /v1/sql/query(或 sql_query)
读回该记录,并把每个已存储字段与获批预览逐项比较。如果存在差异,只报告问题,
不要再修改数据。之后,帮我把这条小票记录与正式入账的银行或银行卡交易匹配,
不要创建重复记录。
这段提示词故意把边界设得很严格。“用 AI 扫描小票”听起来只是提取信息,但真正代价高的错误通常发生在提取之后:选错账户、选错币种、擅自新建分类、重复插入,或未经审核就执行写入。
用最直白的话讲清数据边界
不连接银行账户,并不代表数据不会离开你的电脑。这套工作流中的每个环节都有自己的边界。
| 边界 | 涉及的数据 |
|---|---|
| 你的设备或客户端 | 小票最初是一张照片或一个文件。客户端只能获得你授予的文件访问权限。 |
| Claude、Codex 和所选模型提供商 | 小票内容和你的指令会按照该提供商与客户端的条款和设置处理。请根据自己的配置核对这些条款;Expense Budget Tracker 无法代替 Anthropic 或 OpenAI 提供额外的隐私保证。 |
| 直连 Agent API 或 MCP 连接器 | 智能体会发送任务所需的具体工作区/schema 读取、账本查询和经过批准的结构化写入。Expense Budget Tracker 的这两种连接方式都不需要接收小票图片。 |
| Expense Budget Tracker 存储 | 在这套工作流中,Expense Budget Tracker 只保存金额、币种、账户、分类、交易对方和备注等经过批准的结构化财务数据,不保存小票图片。 |
| 你的小票归档 | 如果退货、保修、报销或留档需要原始图片,应由你另选位置保存。 |
如果你想使用一款无需关联银行账户的预算应用,这套方案可能很合适:小票工作流不需要长期连接银行数据,每一项准备写入账本的变更也都会先展示给你。你仍然需要选择 AI 提供商、授予文件访问权限,并通过 Expense Budget Tracker 的连接方式发送必要的财务读取和写入。
这种小票扫描方式适合你吗?
如果你所说的“支持小票扫描的记账软件”是指内置手机拍照入口并保存附件,请选择专门为这项工作设计的产品。如果你希望用 AI 识别小票,同时在每次写入账本前都能看到完整内容,并把结构化记录与原始图片分开保存,这套工作流就更合适。
如果你需要下面这些能力,可以选择这套工作流:
- 不连接银行账户也能根据小票记账
- 由 Claude 或 Codex 负责图片解读和账本查询
- 以已有账户和分类为准进行记账
- 每次写入前都查看完整预览
- 把可能重复的记录列为候选项,不擅自替你判断
- 得到经过核对、日后还能对账的结构化账本记录
Expense Budget Tracker 也不打算取代支持搜索的小票归档工具。
先拿一张清晰的小票、一个已确认的账户和一个熟悉的分类试一遍。核对金额计算,批准一笔具体记录,写入后读回,再等扣款正式入账时完成匹配。这个简短闭环会留下一条日后依然看得懂的审计轨迹。