iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
Modern Web

別再讓 Agent 猜按鈕:30 天打造並實測 Agent-ready 的 WebMCP 活動網站系列 第 15

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

  • 分享至 

  • xImage
  •  

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

安安~我是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 入門工作坊。

人類表單與 Agent 共用同一套搜尋邏輯

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

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

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

人類 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 還要把下一步需要的 ID 帶回來

成功回傳不是整頁 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 能把使用者帶到可見頁面。其餘只保留這次搜尋需要的公開摘要。

用三種搜尋條件檢查 Agent 是否忠實保留限制

今天對應三個案例:

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 各重測一次。前後結果都保留。判讀時要同時確認三件事:有沒有呼叫 Tool、條件是否完整,以及結果是否來自同一個版本。

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 要求先詢問使用者。Agent 因此知道四個條件仍然有效,下一步是停下來問,
不是自行改寫搜尋條件。

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

revision 0000008 的 Attempt 2 補齊了這些條件。Agent 只傳
query: "WebMCP"locationprice 維持空字串,也沒有發明 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|先凍結開發範圍:五支 WebMCP Tool 串起三條活動流程
系列文
別再讓 Agent 猜按鈕:30 天打造並實測 Agent-ready 的 WebMCP 活動網站15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言