---
name: agentmarket-buyer
description: 搜索和获取 AgentMarket 知识对象。当用户要求浏览 AgentMarket、比较知识对象或获取对象时使用。覆盖目录搜索、对象详情、Route A 0 元获取和使用后评分；付费对象必须在首次 acquire 前获得用户明确授权并交给宿主官方支付宝 402 买家支付能力，Route B 对象走卖家自理集成。
---

# AgentMarket 买家 Skill

用 `agentmarket` CLI 连接 AgentMarket。买家无需注册账号，也不需要平台 API Key；
CLI 自动管理本地会话（`X-Client-Session`），购买历史凭据持久保存在
`~/.agentmarket/` 下，不需要手动设置 Header。

## 1. 前置条件

确认 `agentmarket` CLI 可用：

```bash
which agentmarket || echo "未安装"
```

如果未安装，在 Python 3.12+ 环境执行：

```bash
pip install git+https://github.com/CongQIANFN/agentmarket-sdk.git
```

这会安装 `agentmarket` CLI 和 SDK 客户端；不发布 PyPI，也不包含服务端代码。

首次使用需要配置服务器地址：

```bash
agentmarket config set base-url https://api.agentmarket.org.cn/api/v1
```

也可以通过环境变量 `AGENTMARKET_BASE_URL` 覆盖配置文件值。
当前公开入口为 HTTPS；仍不要提交生产数据、真实支付凭证或敏感内容。

`SESSION_HEADER` 可直接传给 `curl -H`；不要把它的值输出到终端、对话或日志。
当前公开入口为 HTTPS；仍不要提交生产数据、真实支付凭证或敏感内容。

## 2. 付费对象前置能力

- 只浏览目录，或获取 `price_cents=0` 的 Route A 对象时，不需要支付宝能力。
- 获取 `price_cents>0` 的 Route A 对象时，宿主必须具备官方支付宝 402 买家支付能力和
  `alipay-bot`；钱包开通、授权、额度和支付状态也由该官方能力处理。
- `@alipay/alipay-aipay` 是卖家/服务方收款集成，不是买家支付运行时；不要安装它来
  冒充买家能力。
- 仅当实际支付命令因找不到 `alipay-bot` 无法执行，且用户明确同意安装时，先校验包
  完整性，再安装固定版本：

```bash
npm view '@alipay/agent-payment@1.0.23' dist.integrity \
  --registry 'https://registry.npmjs.org'
# 期望 sha512-7OGSHhPnuKsyENpivpY60NgE77ktKtWTP8UBtmizeB1Et44KHFFIjDcSRIFpitEdKAC7uMBx3Mp1Zg/wbYmYCQ==

npx -y --registry=https://registry.npmjs.org \
  @alipay/agent-payment@1.0.23 install
```

第一次 `acquire` 前必须让用户明确确认要购买的对象和价格。收到 402 后立即交接给
官方支付能力，不再做第二次购买确认。

若官方支付命令明确转交钱包生命周期，按宿主 `alipay-authenticate-wallet` 能力处理；
没有该独立 Skill 时才使用 `alipay-bot` 的钱包子命令。`check-wallet` 只读查询；
用户要求开通时执行 `apply-wallet`，开通口令用 `apply-wallet -c`，当前开通过程产生的
OTP 用 `bind-wallet -c`。`applied_unbound` 表示等待用户在支付宝侧授权，本轮停止；
用户完成后再执行一次 `check-wallet`。不要在 AgentMarket 流程内自建钱包状态机。

## 3. 搜索目录

V1 是关键词匹配，不是语义搜索。关键词应出现在 `topic`、`preview` 或 `object_id` 中。

```bash
agentmarket buyer query "<关键词>"
```

已知对象可查详情：

```bash
agentmarket buyer get <object_id>
```

向用户展示候选时，至少核对并说明 `object_id`、`topic`、`route_type`、`price_cents`、
`preview` 和 `freshness`。裸 HTTP API 不返回 `is_valid`。

空结果不代表市场一定没有对象。可拆词、缩短关键词、换同义词或用已知 `object_id`
重查；不要机械重复同一个失败查询。

## 4. 自动获取 Route A 0 元对象

只有同时满足以下条件才自动继续：

- `route_type=platform_hosted`
- `price_cents=0`
- `freshness.valid_until` 不存在，或其值晚于当前 UTC 时间
- 用户明确要求获取该对象内容

0 元对象由路线所有者**直接 200 交付**（无 402、无账单、无凭证、无 confirm）：

```bash
agentmarket buyer acquire <object_id>
```

CLI 内部自动管理 `X-Client-Session`、`Payment-Proof` 和支付确认，不需要手动处理
Header 或 Proof 文件。不要输出或记录完整 Proof。`Payment-Proof` 五分钟内有效。
重复 acquire 会创建新购买；
测试体验请优先选择 0 元对象。

## 5. 付费对象与官方 402 支付交接

在第一次发起付费 acquire 前，执行一次 CLI 更新检查：

```bash
agentmarket update check
```

处理规则：

- `update_available=true`：向用户展示当前版本、远端 main commit 和升级命令，询问是否
  升级；不要自动升级，也不要在未确认前继续付费。
- `status=unknown`：说明网络、GitHub 限流或本地安装元数据无法判断版本。向用户说明
  后，只有用户显式确认继续，才进入付费流程。
- `status=up_to_date`：继续付费流程。
- 如果本机 CLI 不支持 `update check`，视为版本信息不可用，按 `status=unknown` 处理。

以下付费流程和评分命令仍需要 curl。如果本机还没有 `session.sh`，先下载一次：

```bash
SERVER_ROOT="${AGENTMARKET_BASE_URL:-https://api.agentmarket.org.cn/api/v1}"
SERVER_ROOT="${SERVER_ROOT%/}"
SERVER_ROOT="${SERVER_ROOT%/api/v1}"
HOME_DIR="${AGENTMARKET_HOME:-$HOME/.agentmarket}"
# 目录型 Skill 包可用 export AGENTMARKET_SESSION_SCRIPT="<skill目录>/scripts/session.sh" 覆盖
SESSION_SCRIPT="${AGENTMARKET_SESSION_SCRIPT:-$HOME_DIR/session.sh}"
if [ ! -s "$SESSION_SCRIPT" ]; then
  mkdir -p "$HOME_DIR" && chmod 700 "$HOME_DIR"
  # 不要用 `curl | sh` 直接执行远程脚本
  curl -fsS "$SERVER_ROOT/static/frontend/scripts/session.sh" -o "$SESSION_SCRIPT"
  chmod 700 "$SESSION_SCRIPT"
fi
SESSION_HEADER="$(sh "$SESSION_SCRIPT" header)"
BASE="${SERVER_ROOT}/api/v1"
```

`SESSION_HEADER` 不要输出到终端、对话或日志。

先获得用户对本次购买的对象、价格和业务目的的明确确认，再第一次调用 `acquire`。
收到 402 后按以下规则处理：

- 账单不在响应 body；body 仅作调试信息。
- 区分三类材料：`Payment-Needed` Header 原值是**当前支付输入**，`Payment-Proof`
  是**付款后恢复请求的凭证**，已解析 `bill` 仅是调试/适配器视图。
- 读取当前 402 响应的 `Payment-Needed` Header **原值**，保存到仅当前用户可访问的
  安全文件。
- 不解码、不改写、不自行拼接，也不用历史响应补全。实际账单字段嵌套在 `protocol`
  内，但本 Skill 不解析它；更不要把已解析账单或旧账单重新当成恢复输入。
- 不展示、不输出、不写入日志完整 `Payment-Needed`、`Payment-Proof` 或
  `X-Client-Session`。
- 同时保存原始请求上下文：资源 URL、HTTP method、POST body、`Content-Type` 和
  `X-Client-Session`。

首次付费请求先用同一个变量保存原始 body，并把响应头和响应体分别落盘；预期是
HTTP 402，不要用 `curl -i` 把 Header 和 body 混在一起：

```bash
OBJECT_ID='<object_id>'
REQUEST_BODY='{"object_id":"<object_id>"}'
OBJECT_TOKEN="$(printf '%s' "$OBJECT_ID" | tr -c 'A-Za-z0-9._-' '_')"
ATTEMPT_ID="$(date -u +%Y%m%dT%H%M%SZ)-$$-$(od -An -N4 -tx4 /dev/urandom | tr -d ' ')"
FILE_PREFIX="$HOME_DIR/acquire-paid-${OBJECT_TOKEN}-${ATTEMPT_ID}"
HEADER_FILE="$FILE_PREFIX.headers"
BODY_FILE="$FILE_PREFIX.body"

umask 077
if [ -e "$HEADER_FILE" ] || [ -e "$BODY_FILE" ]; then
  echo "acquire attempt files already exist: $FILE_PREFIX" >&2
  exit 1
fi
: > "$HEADER_FILE"
: > "$BODY_FILE"
curl -sS -D "$HEADER_FILE" -o "$BODY_FILE" \
  -X POST "$BASE/knowledge/acquire" \
  -H "$SESSION_HEADER" \
  -H 'Content-Type: application/json' \
  -d "$REQUEST_BODY"
```

如果用 `curl -D` 保存响应头，只允许存在一个 `Payment-Needed` Header；提取时去掉
Header 名、冒号、首尾空白和 CRLF，不要输出到终端：

```bash
PAYMENT_NEEDED_FILE="$FILE_PREFIX.payment-needed.bin"

awk 'tolower($0) ~ /^payment-needed:/ {
  if (seen++) exit 2
  sub(/^[^:]*:[ \t]*/, "")
  sub(/[ \t\r]+$/, "")
  printf "%s", $0
  seen = 1
}
END { if (!seen) exit 1 }' "$HEADER_FILE" > "$PAYMENT_NEEDED_FILE" \
  && chmod 600 "$PAYMENT_NEEDED_FILE" \
  && rm -f "$HEADER_FILE"
```

交给官方买家支付命令的形态如下；`RUNTIME_SESSION_ID` 必须是当前 Agent 运行时会话
标识，绝不能填 AgentMarket 的 `X-Client-Session`：

```bash
RUNTIME_SESSION_ID='<当前 Agent 运行时会话 ID>'
PAYMENT_NEEDED_FILE="$FILE_PREFIX.payment-needed.bin"

alipay-bot 402-buyer-pay \
  --session-id "$RUNTIME_SESSION_ID" \
  --file "$PAYMENT_NEEDED_FILE" \
  --resource-url "$BASE/knowledge/acquire" \
  --intent-summary '原始请求：<用户业务目的>' \
  --method 'POST' \
  --data "$REQUEST_BODY" \
  --header 'Content-Type: application/json' \
  --header "$SESSION_HEADER"
```

官方命令负责支付、恢复原始资源请求和发送履约回执。执行成功后，本 Skill 不得再手动
重发 `acquire`，也不要追加独立履约回执或重复查询。业务失败原样停止；只有命令超时或
网络失败可重试一次。

`--intent-summary` 必须以 `原始请求：` 开头，并概括用户本次要完成的业务目的；不要只
写 URL、HTTP 方法或支付材料。业务目的不明确时先询问用户。

若 `402-buyer-pay` 返回待确认，原样向用户展示支付入口后停止；同时保存当前命令输出
给出的订单号或交易号，以及原始资源请求上下文。用户后续表示已支付、已完成或要查询时，
只执行一条状态查询命令：有有效订单号时优先 `402-query-payment-status
--out-shake-no`，否则使用输出交易号传 `--trade-no`。查询成功由官方命令恢复资源并
发送回执；查询命令必须带上保存的 `--resource-url`、原 `--method`、原 `--data`
和业务 `--header`。原始请求上下文丢失时只能查询支付状态，不能恢复资源。不要手动
重发 `acquire`。业务失败停止；只有超时或网络失败可重试一次。

按保存的上下文二选一执行，不要连续执行两种查询：

```bash
# 有有效订单号
alipay-bot 402-query-payment-status \
  --out-shake-no '<订单号>' \
  --resource-url "$BASE/knowledge/acquire" \
  --method 'POST' \
  --data "$REQUEST_BODY" \
  --header 'Content-Type: application/json' \
  --header "$SESSION_HEADER"

# 否则有交易号
alipay-bot 402-query-payment-status \
  --trade-no '<交易号>' \
  --resource-url "$BASE/knowledge/acquire" \
  --method 'POST' \
  --data "$REQUEST_BODY" \
  --header 'Content-Type: application/json' \
  --header "$SESSION_HEADER"
```

唯一例外：同一次 `402-buyer-pay` 或状态查询已经取得资源，但官方输出明确说明履约
回执发送失败并给出交易号，且用户后续要求恢复时，才按官方指引执行一次
`402-buyer-fulfillment-ack --trade-no`。其他情况不要自行追加履约回执。

支付到达终态后删除临时 `Payment-Needed` 文件。若支付宝返回“买家和卖家不能相同”，
这是终止性业务失败；不能重试 `acquire`，也不能重新签账单。
测试买家 AI 钱包必须绑定与卖家不同的支付宝账户。

## 6. 必须停止的情况

- **Route B 对象（`route_type=seller_managed`）**：交付由卖家 provider 负责，可能需要
  白名单、参数和独立支付闭环。不要自行调用 `provider.acquire_url`。
- **对象不存在或已失效**：展示 API 错误，并询问用户是否换一个对象。
- **官方支付能力不可用或钱包授权未完成**：转交/提示用户处理官方支付宝买家支付能力；
  本 Skill 不自建钱包状态机，不用 mock 支付绕过。

## 7. 查询交易历史

```bash
agentmarket buyer transactions --page 1
```

只能看到当前会话的交易；丢失会话文件会丢失购买历史引用。
评分需要从返回记录中取得 `platform_transaction_id`。

## 8. 使用后评分

内容实际帮助完成任务后，向用户确认评分并提交。`rating` 是 1-5 整数，
`--used` 只能在内容确实被本次任务使用时提交。
CLI 内部调用 `POST /knowledge/{object_id}/rating` 提交评分。

```bash
agentmarket buyer rate <object_id> --platform-transaction-id <platform_transaction_id> --rating 5 --used --comment "内容准确，可直接使用"
```

本会话（`buyer_session`）名下 `status=delivered` 的交易可评分；**0 元（Route A）交易同样可评分**；
Route B 交易需开发者完成交易同步后才进入可评分状态（口径见 03-1 §3.6）。
同一对象同一会话只能评分一次。

## 9. 客户端限额配置

以下环境变量属于 SDK/CLI 客户端的本地建议性限额，当前 CLI 子命令暂不读取
（后续版本会接入）：

| 环境变量 | 含义 | 默认 |
|---|---|---|
| `AGENTMARKET_MAX_PRICE_CENTS` | 单次购买上限（分） | 无限制 |
| `AGENTMARKET_MAX_SPENDING_PER_DAY_CENTS` | 日消费上限（分） | 无限制 |
| `AGENTMARKET_AUTO_PAY` | 是否自动支付付费对象 | `0`（关闭） |
