加入 Hanzo 測試,任何付費方案享 50% 折扣

代理型語言模型的時代,無頭式商務要先賣得成

買家正在變成代理人。要讓大型語言模型在沒有人插手時讀得懂、簽得了名、付得了款,需要哪些條件,以及 Hanzo 今天為此準備了什麼。

本頁內容

無頭式商務把賣場門面從交易引擎分開,任何前端都能靠同一支 API 成交。從前的前端一定是人眼在看的東西:一個網站、一套應用程式,或是一台自助機台。

下一個前端不看,它讀。買家正變成代理人:一支有目標、有預算、有工具迴圈的程式,被派去找方案、找 GPU,或找付款 API。它向自己看得懂、而且不必找人幫忙就能付款的那一方下單。如果你的生意還得靠人讀頁面、關掉 cookie 橫幅、打開確認信,或是鍵入卡號,代理人就會改拿下一筆結果。

這就是論點。一家企業必須讓大型語言模型在沒有人插手時也能讀懂,並且獨自把交易完成。 讀得懂,是指代理人知道你賣什麼、價錢多少、要怎麼開始。辦得成交易,是指它能透過 API 自己開始、付款,並且拿到那樣東西。

以下逐項說明這需要什麼,以及 Hanzo 今天為此準備了什麼。下面每個網址都不需帳號就能回應,你可以自己核對每一句。

每個頁面都提供 Markdown

代理人為讀到的每一個 token 付費。在 hanzo.ai,於頁面網址後面加上 .md,就會得到 Markdown 版的頁面:hanzo.ai/pricing.md、hanzo.ai/about.md。每個頁面都在標頭用 <link rel="alternate" type="text/markdown"> 指明自己的對應頁,代理人不用猜。

10 月 26 日,我用兩種方式抓了我們的代理人頁面:HTML 是 528,810 位元組,Markdown 是 17,465 位元組。接著我從網站地圖每十二個 URL 取一個,829 個裡取了 70 個,再去要它的對應頁。70 個全都以 200 回來,類型是 text/markdown。

公布一份代理人可以當作起點的索引

從沒聽過你的代理人,需要一個能通往各處的網址。我們公布了三份。

  • hanzo.ai/llms.txt 是網站的純文字地圖。它先說明 Hanzo 是什麼,再在「For agents」一節給出取得金鑰的確切步驟,然後逐行列出頁面,一頁一行。docs.hanzo.ai/llms.txt 對文件做同樣的事。

  • api.hanzo.ai/v1 列出 API 提供的每一項能力,不必帶金鑰;api.hanzo.ai/v1/openapi.json 則有每一個操作和它的結構描述。就銷售來說,索引裡有一項 commerce 能力:結帳、訂閱、發票、付款 webhook,以及店面目錄。

  • hanzo.ai/.well-known/api-catalog 是用戶端最先查看的標準位置(RFC 9727)。它指向 OpenAPI 文件、說明文件和狀態頁。

故意迎接爬蟲

robots.txt 是任何爬蟲都會先要的檔案。我們的 逐一寫出十二個 AI 爬蟲的名字,其中有 GPTBot、ClaudeBot、Claude-User、PerplexityBot 和 Google-Extended,並允許它們。它們得到的例外與其他人相同:登入、帳號、付款,以及 API 路徑。

擋住 AI 爬蟲是正當的選擇。因為預設這麼寫就擋住,那根本不算選擇。

把價格做成一筆資料

代理人會比較。寫在圖片裡的價格,或藏在「聯絡我們」按鈕後面的價格,沒辦法比較。api.hanzo.ai/v1/billing/plans 不需要金鑰,回傳 JSON:Free 是 0,Pro 是每月 2000,Team 是每席 2500,每種方案的上限寫在旁邊。金額以美分計。

讓錢包自己註冊

代理人沒有收件匣,沒有電話,也沒有卡。它有一對金鑰。於是 hanzo.id 用錢包登入:為錢包位址要一組一次性 nonce,對它描述的訊息簽名,送出簽名,再把回來的代碼換成權杖。

Hanzo 沒見過的錢包會得到自己的帳號和自己的組織,錢包擔任管理員,方案是 Free。權杖有效七天。沒有人去開信,也沒有人去核准裝置。

呼叫一次就取得金鑰,並留一小段額度試用

憑這組權杖,POST /v1/account/keys 會回傳一把比權杖更長命的 sk-live- 金鑰。請留好;文件寫明它只顯示一次。

Free 方案在 zen-free 上每天 50 次請求,不必綁卡,每次回應都在 x-ratelimit-remaining 寫明剩餘次數。我的第一次呼叫回了 200,還剩 49 次。

沒有人也能收款:透過 API 收穩定幣

POST /v1/billing/crypto/deposit 接收一條鏈、一種代幣和一筆金額,並回傳一個有效 24 小時的入金位址。GET /v1/billing/crypto/options 列出它接受的內容:鏈是 Base、Ethereum 和 Solana,代幣是 USDC 和 USDT。

我停在位址,沒有匯錢。鏈上確認後餘額入帳,這是我們文件裡的說法,不是我跑過的結果。方案和訂閱仍是瀏覽器裡的刷卡結帳。代理人需要我們給的是餘額,而餘額有 API。

整段流程,寫在一個檔案裡

這就是 hanzo.ai/agents#headless,有刪節。每一行都和那個頁面印出的一樣;我略過了第二段檔頭註解、選項呼叫,以及印出金鑰前綴的那一行。需要 Node 22.18 或更新的版本,以及 npm i viem,然後執行 node headless.mts。我用一個新錢包在正式環境跑了這一段:得到權杖、金鑰、一次免費呼叫,以及一個 USDC 入金位址。

// No human required: sign in with a wallet, get a key, call the API, top up in USDC.
// npm i viem   ·   node headless.mts   (Node 22.18+; set HANZO_WALLET_KEY to use your own wallet)
import { createHash, randomBytes } from 'node:crypto'
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'

const ID = 'https://hanzo.id'
const API = 'https://api.hanzo.ai'
const CLIENT = 'hanzo-ai'
const REDIRECT = 'http://localhost:3000/callback'

const account = privateKeyToAccount((process.env.HANZO_WALLET_KEY as `0x${string}`) ?? generatePrivateKey())

const json = async (r: Response) => {
  const body = await r.json()
  if (!r.ok || body?.status === 'error') throw new Error(`${r.url} ${r.status} ${JSON.stringify(body)}`)
  return body
}

// 1. A one-time challenge for this wallet.
const { data: c } = await json(await fetch(`${ID}/v1/iam/web3/nonce?chain=evm&address=${account.address}`))

// 2. The CAIP-122 message the challenge describes, signed with EIP-191 personal_sign.
const message = [
  `${c.domain} wants you to sign in with your Ethereum account:`,
  account.address,
  '',
  ...(c.statement ? [c.statement, ''] : []),
  `URI: ${c.uri}`,
  `Version: ${c.version}`,
  `Nonce: ${c.nonce}`,
  `Issued At: ${c.issuedAt}`,
  ...(c.expirationTime ? [`Expiration Time: ${c.expirationTime}`] : []),
].join('\n')
const signature = await account.signMessage({ message })

// 3. Verify: a first-seen wallet gets an account and an organization of its own.
const verifier = randomBytes(32).toString('base64url')
const challenge = createHash('sha256').update(verifier).digest('base64url')
const { data: code } = await json(
  await fetch(`${ID}/v1/iam/web3/verify`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      clientId: CLIENT, chain: 'evm', scheme: 'secp256k1-eip191', address: account.address, message, signature,
      type: 'code', redirectUri: REDIRECT, scope: 'openid profile email', codeChallenge: challenge, codeChallengeMethod: 'S256',
    }),
  }),
)

// 4. The authorization code for a token.
const token = await json(
  await fetch(`${ID}/v1/iam/oauth/token`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({ grant_type: 'authorization_code', client_id: CLIENT, code, code_verifier: verifier, redirect_uri: REDIRECT }),
  }),
)
const bearer = { Authorization: `Bearer ${token.access_token}`, 'Content-Type': 'application/json' }

// 5. A key that outlives the token. Shown once: keep it in your secret store.
const minted = await json(await fetch(`${API}/v1/account/keys`, { method: 'POST', headers: bearer, body: JSON.stringify({ name: 'agent', type: 'secret' }) }))
const key = { Authorization: `Bearer ${minted.key}`, 'Content-Type': 'application/json' }

// 6. A first call, free.
const chat = await fetch(`${API}/v1/chat/completions`, {
  method: 'POST', headers: key,
  body: JSON.stringify({ model: 'zen-free', messages: [{ role: 'user', content: 'Reply with the single word: ready' }] }),
})
console.log('chat', chat.status, chat.headers.get('x-hanzo-served'), 'free left today:', chat.headers.get('x-ratelimit-remaining'))
console.log((await chat.json()).choices?.[0]?.message?.content)

// 7. Top up in USDC: ask for a deposit address, then send to exactly that address.
console.log(await json(await fetch(`${API}/v1/billing/crypto/deposit`, { method: 'POST', headers: key, body: JSON.stringify({ chain: 'base', token: 'usdc', amountCents: 500 }) })))

x402 會來,可是還沒到

儲值之外,適合代理人的形態是按請求付費。伺服器帶著價格回答 402 Payment Required,用戶端付款後再試一次。那就是 x402。它還沒有在我們的 API 上線:還沒有任何 Hanzo 端點用這種方式報價,所以我不會說已經支援。在那之前,透過 API 儲值的餘額,就是代理人付給我們的方式。

為什麼爬蟲零錯誤要緊

這些失敗都不會大聲響。代理人順著網站地圖的連結走進 404,不會去開單。它直接拿走下一筆結果。對待爬蟲錯誤,應當像店家對待壞掉的結帳。

我用 ClaudeBot 的 user-agent 字串抓了同樣的 70 個抽樣頁面,再用 Googlebot 的抓一次。每一次都回 200。這是抽樣,不是保證;user-agent 字串也不是爬蟲自己的位址,所以我沒辦法讓你看到真實爬蟲看見的內容。在你自己的網站上做同樣的事:用你邀請的代理人去抓網站地圖,數一數哪些回應不是 200。

我們以前來過這裡

我在 2014 年創辦這家公司,當時叫 Crowdstart;2016 年我們把它改名為 Hanzo。第一個客戶 SKULLY 在 Indiegogo 上大約 45 小時募集了 $1 million,TechCrunch 稱之為Indiegogo 上最快募滿的活動。在我看來,Hanzo 從一開始就是以 AI 為本的商務:先是我們自己的分析,然後是從平台上那些公司的資料裡學習的模型。2017 年我們加入 Techstars(那年六月的文章),當時我們說自己在做的是智慧商務。

2020 年,Damon Motorcycles 在 CES 發表,活動由 Hanzo 營運。30 天裡,平台以 $15,532 的廣告花費賣出了 $8.4M 的摩托車,回報是 541:1。受眾每 12 小時依我們的客戶資料重建一次,AI 撰寫的廣告組在 36 小時內於 Facebook 上被評為 Above Average。其餘見個案。

那是銷售一側的機器,找到會買的受眾,並寫出廣告。購買一側是下一步。同一條循環即將從另一頭跑起來,你的生意要麼被機器讀懂並付款,要麼被機器跳過。

把你的代理人指向 hanzo.ai/agents。

留言

使用 Hanzo ID 登入後即可留言。

正在載入留言…

繼續閱讀