NotesAgent:用程式呼叫另一支 Agent(Run vs RunOnServer)

NotesAgent:用程式呼叫另一支 Agent(Run vs RunOnServer)

2026.06.12 約 1,153 字

你有一支很重的批次處理 agent — 跑一次要好幾分鐘。現在需求變了:使用者按下表單上的按鈕時,要能「立刻把這支 agent 叫起來跑」;或是另一支 agent 處理到一半,需要把工作轉交給它。重點是 — 你不想用排程等它自己跑,你想用程式直接觸發

這正是 NotesAgent 的用途。官方對它的定義是「Represents an agent」 — 它代表資料庫裡的一支 agent 設計元件,讓你查它的設定、也讓你用程式把它跑起來。而「跑起來」有兩個方法:RunRunOnServer — 選錯會讓你的程式在錯的機器上跑、或根本沒效果。這篇把這個決定講清楚。


重點摘要

  • db.GetAgent("agent名稱") 拿到一支 NotesAgent,或用 db.Agents 取得全部
  • Run:在當前(client)環境跑 agent;RunOnServer:在資料庫所在的伺服器上跑
  • 兩者都回傳 Integer 狀態碼,0 代表成功,簽章都帶一個選用的 noteID$
  • noteID$ 會被傳進被呼叫 agent 的 ParameterDocID 屬性 — 這是把「要處理哪份文件」傳過去的標準做法
  • 屬性可查 agent 設定:IsEnabled(讀寫)、TriggerTargetLastRunServerNameIsWebAgent / IsNotesAgentOwner
  • 四個限制:不能遞迴呼叫自己、不能 debug 被呼叫的 agent、使用者不能直接互動、輸出只進 Domino log

拿到一支 Agent

agent 屬於資料庫,所以從 NotesDatabase 取得:

Dim session As New NotesSession
Dim db As NotesDatabase
Set db = session.CurrentDatabase
Dim agent As NotesAgent
Set agent = db.GetAgent("DailyCleanup")
If agent Is Nothing Then
' 這個名稱在這個 db 裡找不到
Exit Sub
End If

要列出資料庫裡所有 agent,則用 db.Agents(回傳陣列)。注意官方對 Name 的提醒:「Within a database, the name of an agent may not be unique」 — 同名 agent 在一個 db 裡可能不只一支,GetAgent 拿到的是其中之一。

Run vs RunOnServer:最重要的決定

RunRunOnServer 兩個方法都「把 agent 跑起來」,但跑在哪台機器上完全不同:

RunRunOnServer
執行位置當前 client 環境資料庫所在的伺服器
簽章status = agent.Run([noteID$])status = agent.RunOnServer([noteID$])
回傳Integer0 = 成功同左
典型情境互動式、client 端觸發把重活丟到 server 跑、不佔用 client

為什麼這個選擇重要?想像那支「跑好幾分鐘」的批次 agent:用 Run,它在使用者的 Notes Client 上跑,使用者整個卡住等它跑完;用 RunOnServer,工作交給伺服器、client 馬上拿回控制權。重活就該 RunOnServer

有一個例外要記住,官方原文:「On a local database, the RunOnServer method works like the Run method, that is, runs the agent on the local computer.」 — 如果資料庫是本機的,RunOnServer 其實就退化成 Run、在本機跑。沒有伺服器,自然沒地方「丟過去」。

兩個方法都「runs any agent regardless of source language(simple action、formula、LotusScript、Java)」 — 被呼叫的 agent 是什麼語言寫的都行。

把一份文件傳給被呼叫的 agent

Run / RunOnServer 的選用參數 noteID$,官方說明:「The note ID of a document. This value is passed to the ParameterDocID property of the called agent.」

換句話說,這是「呼叫端」跟「被呼叫端」之間傳遞「要處理哪份文件」的標準管道:

' 呼叫端:把某份文件的 NoteID 傳過去
Call agent.RunOnServer(doc.NoteID)
' 被呼叫的 agent 裡:從自己的 ParameterDocID 取回那份文件
Dim session As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Set db = session.CurrentDatabase
Set doc = db.GetDocumentByID(session.CurrentAgent.ParameterDocID)

被呼叫的 agent 從自己的 ParameterDocID(官方:「the note ID of a document passed to the agent by Run or RunOnServer」,唯讀,Release 5.02 起)拿到那個 NoteID,再用 GetDocumentByID 取回文件來處理。這比用一個全域暫存欄位乾淨得多。

認識這支 agent:常用屬性

不只能跑它,也能查它的設定(多數唯讀):

屬性內容
IsEnabled讀寫,「whether an agent is able to run or not」— 可程式化啟用/停用
Trigger這支 agent 何時觸發(排程/事件…)
Target它作用在哪些文件上
LastRun上次執行的日期
ServerName讀寫,設定它排程跑在哪台 server(是設計元件的屬性,不是這次執行的)
IsNotesAgent / IsWebAgent能在 Notes client/Web 瀏覽器環境跑嗎
IsPublic共用還是私人
Owner最後修改並儲存它的人

IsEnabled 可寫這點很實用 — 維護期間用程式把某支排程 agent 停掉、完事再開回來,配合 Save() 寫回設計元件即可。

幾個限制

呼叫 agent 不是萬能,官方列了幾條硬限制:

  • 不能遞迴:「You cannot run an agent recursively (cannot call it from itself).」 agent 不能呼叫自己。
  • 不能 debug:「You cannot debug a called agent.」 被 Run / RunOnServer 叫起來的 agent 進不了 debugger。
  • 使用者不能互動:「The user cannot interact directly with a called agent.」 被呼叫的 agent 裡別放對話框 — 沒人能按。
  • 輸出只進 log:「User output goes to the Domino log.」 Print 之類的輸出會跑到 Domino log,不會出現在使用者眼前。要記錄被呼叫 agent 的執行過程,搭配站上先前寫的 NotesLog 是更可控的做法。

同類別在其他語言

NotesAgent 三種語言都有,名字一致:

語言對應類別取得方式
Java(lotus.domino.*Agentdb.getAgent(name)
SSJS / XPagesAgentdatabase.getAgent(name)

run / runOnServerParameterDocID 的觀念三邊一致。XPages 端用 SSJS 從按鈕觸發後端 agent 是很常見的模式,走的也是這個 runOnServer — 把重活丟回 server,跟這篇的邏輯完全相同。

參考來源

← 回到文章列表