iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
Modern Web

網站終於會說話:30 天實作並驗證 Agent-ready 的 WebMCP 活動網站系列 第 15

Day 15|讓人類與 Agent 共用同一套活動搜尋規則

  • 分享至 

  • xImage
  •  

安安~我是ChiYu~

昨天把網站範圍鎖定在五支 Tool 與三條活動流程,也留下可以重播的正式搜尋基線。今天不再
增加功能,而是正式驗收第一段能力:搜尋活動。

重點不是替 Agent 開一條專用捷徑,而是讓人類表單與 search_events 共用同一套搜尋規則。
人類選擇台北、免費、入門,Agent 用自然語言提出相同條件,兩邊最後都應該得到同一個結果。

如果 UI 與 Tool 各寫一套篩選邏輯,網站很快就會出現兩個版本的答案:畫面找得到,Agent
找不到;或者 Agent 為了湊結果,偷偷把使用者指定的條件放寬。

所以今天先拆開共用搜尋路徑,再用三種問法檢查模型是否忠實保留條件。第一次結果並不完美,
失敗與後續重測都會留在原本的位置。

沿用正式搜尋基線,不另外切新版本

如果昨天已經停在 v3-day-14,今天不用再切一次;單篇閱讀時,先準備這個版本:

git switch --detach v3-day-14
npm ci
npm run dev

這個里程碑已包含正式搜尋頁、人類表單與 search_events 的共用路徑。今天沒有新的 source
delta,工作重點是拿同一版程式依序做 UI 搜尋、deterministic tests 與 Inspector 題目。版本
先固定,後面一題通過、一題失敗、另一題需要重測時,才知道自己究竟在考哪份程式。

正式搜尋表單與目前活動結果

圖 1:UI 使用台北、免費、入門三個條件,回傳 2027 年 1 月 23 日的 WebMCP 入門工作坊。

Human UI 與 Agent 共用同一個 search action

搜尋頁保留原本可見表單,再加入 WebMCP metadata:

<form
  id="event-search"
  toolname="search_events"
  tooldescription="依關鍵字、地點、費用與程度搜尋目前公開活動。"
  toolautosubmit>
  <!-- query、location、price、level -->
</form>

toolname 提供穩定能力名稱,tooldescription 說明適用任務;欄位的 name、label、enum 與
constraint 共同形成 input schema。它們描述的是搜尋任務,不是「點藍色按鈕」。

人類 submit 與 Agent submission 都會進入同一個 eventActions.search()

async search(query, context) {
  const result = await dependencies.search(query);
  recordActivity("search_events", context.mode, "SUCCESS");
  return {
    count: result.events.length,
    events: result.events
  };
}

共用 action 再呼叫 GET /api/events。因此 enum validation、公開活動篩選與結果格式只有一份
來源;UI 與 Tool 不會因改版各自漂移。

成功 result 也不是整頁 HTML 或資料表全部欄位:

{
  "count": 1,
  "events": [
    {
      "id": "evt-webmcp-intro",
      "url": "/events/evt-webmcp-intro",
      "title": "WebMCP 入門工作坊",
      "startsAt": "2027-01-23T10:00:00+08:00",
      "location": "taipei",
      "price": "free",
      "level": "beginner"
    }
  ]
}

id 是後續詳情查詢的 opaque key,url 讓 Agent 沿用網站提供的 route。其餘只保留這次
搜尋需要的公開摘要。

三種問法,檢查 Tool 選擇與條件保留

今天對應三個案例:

Case 問法/變化 要檢查什麼 實際結果
SEL-01 找台北、免費、入門活動 是否選 search_events 並保留三個條件 Agent trace 通過
ARG-01 找高雄、付費、進階,關鍵字 Agent 零筆結果後是否擅自放寬條件 初次失敗;revision 0000008 Attempt 2 通過
ARG-02 只搜尋 WebMCP,不限制地點與費用 是否只傳使用者說過的條件 歷史證據不足;revision 0000008 Attempt 2 通過

三題的 Inspector trace 檢查 Agent 是否選對 Tool、是否保留參數,屬於 E4 行為證據;共用
search action、server 篩選與 UI parity 仍由 E2 測試負責。不同 Attempt 來自不同固定版本,
不能把後來兩次通過倒填成第一次就 3/3

Agent 自行選擇 search_events 的完整紀錄

圖 2:SEL-01 保留 Prompt、Tool input、Tool result 與 AI result。

SEL-01 證明 Agent 在固定公開版本中選對 Tool,並送出 taipeifreebeginner。另外
兩題則先留下失敗與證據不足,之後才在新的固定 revision 各重測一次。

ARG-01:第一次參數正確,零筆後卻自行放寬

ARG-01 中 Agent 在空結果後自行放寬搜尋條件

圖 3:黑色 trace 區才是本題證據;上方輸入框是尚未送出的另一段文字,不屬於這次執行。

第一次呼叫完整保留 Agentkaohsiungpaidadvanced,但收到空陣列後,Agent 又
連續呼叫三次,依序移除程度、地點與其他限制:

四個條件 → 移除程度 → 只留關鍵字 → 只留地點

這次歷史執行判定為 failedsearch_events 對每次輸入都正確回傳空結果,問題出在 Agent
未經使用者同意便改變搜尋條件。較安全的行為應是先回報沒有完全符合的活動,再詢問是否允許
放寬條件。

ARG-02:沒有發明條件,但版本對不上

ARG-02 的 Tool result 與目前公開版 API 不一致

圖 4:input 只帶 query: "WebMCP",空字串代表不限制地點與費用;截圖沒有網址與版本座標,因此只能作為輔助證據。

這次 Agent 沒有發明非空條件,但 Inspector 回傳 count: 0;重新查詢目前公開版 API,則能
找到 WebMCP 入門工作坊。在還沒確認頁面、Tool registry 與 API 是否屬於同一個 release 前,
不能把它算成通過,也不能直接歸咎於模型。

因此這份歷史證據標記為 rerun_required。重跑時必須把網址、/health 版本座標與完整 Copy
trace 一起保存。

修正契約後,用相同題目重測

前兩題的初次結果都留在原位。後來我把「零筆結果不得自行放寬」寫進 result guidance,也把
網站、/health 與 Inspector trace 綁到 revision 0000008,再各執行一次。

ARG-01 Attempt 2:保留四個條件,零結果後停下來問

Attempt 2 使用完全相同的四個條件,只呼叫一次 search_events。Tool 回傳零筆後,Agent
沒有自行移除條件,而是把決定權交還給使用者:

ARG-01 重測保留全部搜尋條件,零結果後沒有自行放寬

圖 5:querylocationpricelevel 四個參數完整保留,且 trace 沒有第二次放寬搜尋。

這次改變不是再補一句 Prompt,而是讓零筆結果把決策邊界說清楚。Tool result 除了回傳
appliedFilters,也標示 constraintsRelaxed: falserequiresUserDecision: true,並在
nextAction 要求先詢問使用者。下一步因此是停下來問,而不是自行改寫搜尋條件。

ARG-02 Attempt 2:只保留使用者真的說過的條件

revision 0000008 的 Attempt 2 補齊版本座標。Agent 只傳 query: "WebMCP"location
price 維持空字串,也沒有發明 level;Tool 找到一筆 evt-webmcp-intro,全程沒有呼叫
詳情或寫入 Tool。

ARG-02 重測只保留 WebMCP 關鍵字,沒有發明其他限制

圖 6:單次呼叫的 input、Tool result 與最終回答一致,ARG-02 在這個固定 revision 判定通過。

兩份文字紀錄是依截圖逐行轉錄的 reconstructed trace,不冒充 Inspector 原始匯出檔:

不替 Agent 另外維護一套搜尋規則

若 human submit 自己過濾資料,Tool execute 又維護另一份條件轉換,按鈕與 Agent 很快會得到
不同結果。更糟的是,兩邊都可能各自「測試通過」。

共用 use case 的結構應該是:

UI adapter ┐
           ├→ search action → API → server validation
Tool adapter┘

差別只在 context.mode 用來記錄操作來源,不應改變搜尋規則。

第一份成績不好看,卻把兩件事講得很清楚:UI 與 Tool 必須共用規則,模型是否守住條件則要
另外驗。搜尋 result 現在已帶回 opaque event ID,明天就進詳情頁問一句更像人話的:「我現在
看的活動是哪一場?」接著再切走頁面,看看舊 Tool 會不會識相地下班。


上一篇
Day 14|五支 Tool 不再往外長:把產品範圍寫成會亮紅燈的契約
下一篇
Day 16|Agent 怎麼知道「我現在看的活動」是哪一場?
系列文
網站終於會說話:30 天實作並驗證 Agent-ready 的 WebMCP 活動網站23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言