Chapter 8-5

Agents






Introduction

Agent notes, like form and view notes, are design notes of class NOTE_CLASS_FILTER that reside in databases. Domino application developers design agents to automate operations on documents in a database.

Agent notes consist of a document selection formula, a trigger, and one or more actions. An action can be a Domino-supplied action, an @function formula, a LotusScript program or a Java program. The actions work on a preselected set of documents, triggered by a predetermined time or event. You can create personal (private) agents and shared agents. For complete information on types of agents and how they are used, refer to the Domino or Notes user documentation or help.

The agent interface provides a facility to create, test, execute, and view the results of agents for a particular database. This interface introduces several on-disk structures required to properly manage the note via the C API. The queryods.h and stdnames.h include files define the associated data types and constants that comprise the agent note. When you inspect these include files, note that the terms "assistant" and "agent" are synonymous. Domino and Notes also provide a set of C API functions that support the execution of agent notes (it is important to note that agents that run through the C API are unknown to the Agent Manager). The agents.h include file defines the function prototypes and supporting data types and constants.

Thread Support

Agents may run on more than one thread but should be given a run context per thread. Each run context can be used for multiple agents.

This chapter describes the kinds of agents, details the components that make up the corresponding design notes, and illustrates how to properly execute an agent and report any results.

Cross-Platform implementation

C API programs that run on non-Intel based platforms such as UNIX, must convert certain types of data between host-specific format and Domino canonical format when creating or accessing item data. Please refer to the "Domino Cannonical Format" chapter and to the sample source file agents.c for detailed explanations.

The AGENTS Sample Programs

The sample programs in dbdesign\agents illustrate how to use the C API to create, execute, and view the results for a subset of agent types and agent note variations.

The sample program agents.exe (agents in UNIX) creates four agent notes that reside in the sample database problems.nsf, including:

The sample uses general purpose subroutines to create the various agent note items. Subroutine arguments support the settings for a particular agent type. The sample routines AddManualAgent, AddBackgroundAgent, AddScheduledAgent, and AddJavaAgent drive the appropriate settings for the four sample agent types.

The sample program ragents.exe (ragents in UNIX) executes the background and scheduled agents created by agents and reads and displays the results. It calls the sample routine RunTriggeredAgents to call the general purpose routines for executing the agent notes and analyzing the results, based on the agent action type.

We recommend that you refer to the agents and ragents programs code (agents.c and ragents.c) as you read this chapter.


Components of Agent Notes

Agents are design notes that reside in a database. Use NSFNoteCreate to create them. Shared agent notes are of class NOTE_CLASS_FILTER; private agent notes are of class NOTE_CLASS_FILTER | NOTE_CLASS_PRIVATE.

The following items comprise an agent note and are required to manage and execute an agent note from the agent interface.

Field Name Description Sample Reference
$TITLE Agent name SetAgentTitle
$Comment Agent description SetAgentComment
$Flags Design flags SetAgentDesignFlags
$MachineName Server name where agent runs SetAgentMachineName
$UpdatedBy Agent owner via NSFNoteUpdate
$Signature Agent owner signature via NSFNoteSign
$AssistVersion Agent version stamp SetAgentVersion
$AssistType Action type SetAgentType
$AssistLastRun Last run time-date SetAgentLastInfo
$AssistDocCount Number of processed documents SetAgentLastInfo
$AssistFlags Agent flags SetAgentAssistFlags
$AssistTrigger Agent trigger type SetAgentTrigger
$AssistInfo Selection and execution information SetAgentInfo
$AssistQuery Document selection query formula SetAgentAction
$AssistAction Action formula or script SetAgentAction
$AssistAction_Ex Extended action script SetAgentAction
$AssistRunInfo Agent run data object SetAgentRunInfo, GetAgentRunInfo The following sections describe each field and how to configure each field for the type of agent being created.

$TITLE
The $TITLE item (FIELD_TITLE) is of type TYPE_TEXT and contains a string specifying the agent name.

$Comment
The $Comment item (FILTER_COMMENT_ITEM) is of type TYPE_TEXT and contains a string describing the agent.

$Flags
The $Flags item (DESIGN_FLAGS) is of type TYPE_TEXT and contains a character sequence of the constant values (defined in stdnames.h) that describe the agent design. You must use the related constants as follows, based on the desired agent type:

$MachineName
The $MachineName item (FILTER_MACHINE_ITEM) is of type TYPE_TEXT and contains the canonical name of the location where the agent runs. This item only applies to scheduled and mail triggered agents and does not need to exist in the design note for other agent types.

If a scheduled agent runs on the local machine, set the $MachineName value to the user name in canonical format (for example, "CN=John Doe/OU=CAM/O=Lotus"). If it runs on a server, set the $MachineName value to the server name in canonical format.

For mail triggered agents, set the $MachineName value to the "MailServer" setting from the workstation's notes.ini file. Use OSGetEnvironmentString to read the setting.

$UpdatedBy
The $UpdatedBy item contains the name of the agent owner, displayed by the Notes agent UI for private agents. This item is automatically appended to the agent note when you use NSFNoteUpdate to write it to the database.

$Signature
An agent design note requires the signature of its creator. Call NSFNoteSign before adding the note to the database to automatically add this item to the note.

$AssistVersion
The $AssistVersion item (ASSIST_VERSION_ITEM) is of type TYPE_TIME and contains a time/date stamp for the agent. Update this field with the current time/date every time the agent is modified.

$AssistType
The $AssistType item (ASSIST_TYPE_ITEM) is of type TYPE_NUMBER and contains a signature constant value appropriate to the type of agent action:

Agent Action $AssistType Value Include File
None ASSIST_SIG_ACTION_NONE agents.h
Formula SIG_ACTION_FORMULA ods.h
LotusScript SIG_ACTION_LOTUSSCRIPT ods.h
Java SIG_ACTION_JAVAAGENT ods.h $AssistLastRun
The $AssistLastRun item (ASSIST_LASTRUN_ITEM) is of TYPE_TIME and contains the time/date stamp of the last execution of the agent. When you create the agent, you should clear this item, setting the two Innards elements of the TIMEDATE variable to (DWORD) 0. Domino or Notes automatically updates this item for each agent execution.

$AssistDocCount
The $AssistDocCount item (ASSIST_DOCCOUNT_ITEM) is of type TYPE_NUMBER and contains the number of documents processed by the last execution of the agent. When you create the agent, initialize this item to zero. Domino or Notes automatically updates this item for each agent execution.

$AssistFlags
The $Assist Flags item (ASSIST_FLAGS_ITEM) is of type TYPE_TEXT and contains a character sequence of constant values (defined in stdnames.h) used to describe miscellaneous agent attributes that are used by the Notes agent UI. Use the related constants as follows:

$AssistTrigger
The $AssistTrigger item (ASSIST_TRIGGER_ITEM) is of type TYPE_TEXT and contains a constant value that describes the event that triggers the agent. The associated literals are defined in queryods.h and assigned to the item as follows:

Agent Trigger $AssistTrigger Value
Manual ASSISTTRIGGER_TYPE_MANUAL
If Document is pasted ASSISTTRIGGER_TYPE_PASTED
If Document is updated ASSISTTRIGGER_TYPE_DOCUPDATE
If New Mail has arrived ASSISTTRIGGER_TYPE_NEWMAIL
If Scheduled event ASSISTTRIGGER_TYPE_SCHEDULED
Not defined (empty) ASSISTTRIGGER_TYPE_NONE $AssistQuery
The $AssistQuery item (ASSIST_QUERY_ITEM) is of type TYPE_QUERY and consists of a CD record sequence that defines a front end search query, used to narrow the document selection against which the agent runs. Even if you do not want a search query, this item still requires an appended CDQUERYHEADER record (SIG_QUERY_HEADER signature). If you include a search query, append one of the following CD records and related packed data to the $AssistQuery item:

Query type CD Record CD Signature Packed Data
By field CDQUERYBYFIELD SIG_QUERY_BYFIELD Field name, field value
By folder CDQUERYBYFOLDER SIG_QUERY_BYFOLDER Folder name
By form CDQUERYBYFORM SIG_QUERY_BYFORM ODS_ASSISTSTRUCT records, form name
Formula CDQUERYFORMULA SIG_QUERY_FORMULA Compiled formula
Text search CDQUERYTEXTTERM SIG_QUERY_TEXTTERM Text strings
Uses form CDQUERYUSESFORM SIG_QUERY_USESFORM Form name LIST $AssistInfo
The $AssistInfo item (ASSIST_INFO_ITEM) is of TYPE_ASSISTANT_INFO and provides the control information Domino or Notes uses to determine when and against which documents the agent should run. This corresponds to the data entered in the Notes agent dialogs "When should this agent run?" and "Which document(s) should it act on?"

The ODS_ASSISTSTRUCT structure contains the information for the $AssistInfo item. It is defined in queryods.h and described as follows:

typedef struct
{
WORD wVersion; /* Structure version */

WORD wTriggerType; /* Type of trigger */
WORD wSearchType; /* Type of search */
WORD wIntervalType; /* Type of interval */
WORD wInterval; /* Interval */
DWORD dwTime1; /* depends on interval type */
DWORD dwTime2; /* depends on interval type */

TIMEDATE StartTime; /* Agent does not run before this time */
TIMEDATE EndTime; /* Agent does not run after this time */

DWORD dwFlags;
DWORD dwSpare[16];
} ODS_ASSISTSTRUCT;


Set the reserved wVersion and dwSpare fields to 0.

The wTriggerType field describes the event that triggers the agent. The ASSISTTRIGGER_TYPE_xxx constants define the valid values for this field. The value must be identical to the one assigned to the $AssistTrigger item.

The wSearchType field describes the method for determining which documents are applied to the agent action for a particular type of trigger. The ASSISTSEARCH_TYPE_xxx constants define the valid values for this field. The following table identifies the valid values, based on the trigger type specified in the wTriggerType field. If wTriggerType Use wSearchType To Run Agent Against
The wIntervalType and wInterval fields only apply to scheduled agents. Together, they define how often Domino runs the agent. The wIntervalType field describes the interval type (minutes, days, weeks, or months) and the wInterval field describes the interval amount between executions of the scheduled agent. The ASSISTINTERVAL_TYPE_xxx constants define the valid wIntervalType values. Both fields are ignored if wTriggerType does not equal ASSISTTRIGGER_TYPE_SCHEDULED.

For example, if wIntervalType = ASSISTINTERVAL_TYPE_DAYS and wInterval = 2, Domino executes the agent once every two days.

The dwTime1 and dwTime2 fields also apply only to scheduled agents. Together, they further refine the schedule for the wIntervalType value, as described in the following table. Both of these fields are ignored if wTriggerType does not equal ASSISTTRIGGER_TYPE_SCHEDULED. wIntervalType dwTime1 dwTime2
ASSISTINTERVAL_TYPE_
MINUTES Starting time Ending time
DAYS Time of day Ignored
WEEK Time of day Day of the week (Sunday == 1)
MONTH Time of day Day of the month

Note that the time units are in ticks since midnight GMT. Use the appropriate TICKS_IN_xxx constant values, declared in the misc.h include file, to determine this value. For example, if wIntervalType = ASSISTINTERVAL_TYPE_MONTH, wInterval = 1, dwTime1 = 5*TICKS_IN_HOUR, and dwTime2 = 1, Domino executes the agent on the first day of every month at 5 AM.

The StartTime and EndTime fields apply to all scheduled agents and background agents triggered by new or modified documents. They define the starting and ending time/dates on which Domino executes the agent. Use the relevant C API routines, declared in the misc.h and ostime.h include files, to set the values for these fields. If you do not want to set a starting and/or ending time, set the field's TIMEDATE structure to 0. Both of these fields are ignored if wTriggerType is not set to ASSISTTRIGGER_TYPE_SCHEDULED or ASSISTTRIGGER_TYPE_DOCUPDATE.

The dwFlags field contains miscellaneous information about the agent. The ASSISTODS_FLAG_xxx constants, declared in queryods.h, provide the valid values for this field. The following table describes each constant with respect to the types of agents that apply. This field must be set to 0 if none of the constants apply.

ASSISTODS_FLAG_ Description Applicable agent $AssistInfo values
HIDDEN Hidden agent (that is, ASSISTTRIGGER_TYPE_MANUAL NOWEEKENDS Do not run on weekends ASSISTTRIGGER_TYPE_DOCUPDATE; CHOOSEWHENENABLED Force server dialog when ASSISTTRIGGER_TYPE_DOCUPDATE; STOREHIGHLIGHTS Store search query highlights All agent notes
$AssistAction
The $AssistAction item (ASSIST_ACTION_ITEM) is of type TYPE_ACTION and consists of one or two CD records that define what the agent should do when it executes. The sequence consists of one CDACTIONHEADER header record followed by one CDACTIONFORMULA action record, one CDACTIONLOTUSSCRIPT action record, or no action record, depending on the type of action specified by the value for $AssistType item.

CDACTIONHEADER
The CDACTIONHEADER record is the first CD record in the agent action item. It has a CD record signature of SIG_ACTION_HEADER. If the value for the $AssistType item is ASSIST_SIG_ACTION_NONE, no other CD records are appended to the agent action item.

CDACTIONFORMULA
If the value for the $AssistType item is SIG_ACTION_FORMULA, the CDACTIONFORMULA record is the second CD record appended to the agent action item. This structure has a CD header record signature of SIG_ACTION_FORMULA and a header length equal to the structure size plus the length of the packed formula object that follows. The dwFlags field specifies additional formula options, if any, as defined by the ACTIONFORMULA_FLAG_xxx constant values in queryods.h. The wFormulaLen field is set to the even byte boundary length of the compiled formula object that follows this structure.

CDACTIONLOTUSSCRIPT
If the value for the $AssistType item is SIG_ACTION_LOTUSSCRIPT, the CDACTIONLOTUSSCRIPT record is the second CD record appended to the agent action item. This structure has a CD header record signature of SIG_ACTION_LOTUSSCRIPT and a header length equal to the structure size plus the length of the packed LotusScript subroutine that follows. Set the reserved dwFlags field to 0. The dwScriptLen field is set to the even byte boundary length of the LotusScript subroutine source that follows this structure.

NOTE: A background agent should not refer to the UI (front-end) classes, because it has no knowledge of the context. See the Running Agent section below for possible errors.

NOTE: To execute properly, the LotusScript source appended to the agent action item must be contained in the Initialize event subroutine. Once the agent is attached, you can view this source from the Notes agent UI by selecting the Initialize event. You can manually select the agent for test and execution from the Notes UI. Since the Notes LotusScript IDE expects the script source to be formatted with specific event comments, the error message box "Generic LSE Failure" will appear when you exit the Notes UI Agent view of the script source. Likewise, you cannot edit and save the agent action script through the agent UI. This limitation is due to the missing API support for importing generic LotusScript source into the IDE format. A future Notes release will support agent integration with the Notes Agent UI and the LotusScript IDE. CDACTIONJAVAAGENT
If the value for the $AssistType item is SIG_ACTION_JAVAAGENT, the CDACTIONJAVAAGENT record is the second CD record appended to the agent action item. This structure has a CD header record signature of SIG_ACTION_JAVAAGENT and a header length equal to the structure size plus the length of the java class name, java class code path, java class file list plus two null fields that follow. Set the reserved dwSpare[2] fields to 0.

$FILE
The $FILE item (ITEM_NAME_ATTACHMENT) required only for a Java Agent, is of type TYPE_OBJECT and contains information related to the Java Agent executable file. The value of this item is a structure of type FILE_OBJECT. Use NSFNoteAttachFile to add this item to the database.

$AssistAction_Ex
The $AssistAction_Ex item (ASSIST_EXACTION_ITEM) is of type TYPE_LSOBJECT and contains the compiled LotusScript object for a LotusScript agent action type. Domino and Notes uses the compiled object in lieu of run-time compilation of the script during agent execution. This item is required for all Agent types, although it only contains usable information in the case of LotusScript agent actions. In previous releases of Domino and Notes, you could not programmatically compile LotusScript source, and his item contained the address of the $AssistAction agent action item.

$AssistRunInfo
The $AssistRunInfo item (ASSIST_RUNINFO_ITEM) is of type TYPE_OBJECT and attaches a run information object used by Domino and Notes to store execution data. Call NSFDbAllocObject to allocate the attached object. If the agent is shared, the object is a public note and has a note class of NOTE_CLASS_DOCUMENT. If the agent is private, access to the object is restricted to the owner and it has a note class of NOTE_CLASS_FILTER | NOTES_CLASS_PRIVATE. The object contains the object descriptor item followed by the object run data.

The object descriptor item consists of the TYPE_OBJECT object type followed by an OBJECT_DESCRIPTOR structure, in which the RRV field is set to the allocated object ID and the ObjectType field is set to the OBJECT_ASSIST_RUNDATA constant (defined in nsfdata.h). Call NSFDbItemAppendObject to assign the object descriptor item to the $AssistRunInfoItem.

The object run data consists of a sequence of CD records that contain the run data information. When you create an agent note, you must provide an initial placeholder for the first two CD records of the object run data -- specifically, one ODS_ASSISTRUNOBJECTHEADER structure followed by one ODS_ASSISTRUNOBJECTENTRY structure. Domino or Notes adds and/or modifies the remaining CD records after subsequent agent executions. Call NSFDbWriteObject and NSFDbReadObject to write and read all of the object run data records.

ODS_ASSISTRUNOBJECTHEADER
The ODS_ASSISTRUNOBJECTHEADER structure contains the number of run data object entries, as specified by the wEntries field. When you create the agent note (that is, the agent has not executed), set the wEntries field to 1. After the agent note executes, Domino or Notes updates the wEntries field to the actual number of run data object entries. By default, Domino or Notes creates five run data object entries. Set the reserved dwFlags and wSpare elements to 0.

ODS_ASSISTRUNOBJECTENTRY
At least one ODS_ASSISTRUNOBJECTENTRY structure entry follows the run data object header record. It is defined as follows:

When creating the agent, there should be a single entry with a length of zero, as specified by the dwLength field. Domino or Notes creates and reserves at least five (the default number) run data object entries. The first run data entry contains the run information structure ODS_ASSISTRUNINFO and the third run data entry contains the agent log string that is displayed after executing the agent from the Notes UI. To determine that the agent has executed, you should verify that the length specified by the dwLength field for both the first and third entry is greater than 0. The remaining entries are reserved for luse by Domino or Notes.

Set the reserved dwFlags field to 0.

ODS_ASSISTRUNINFO
The ODS_ASSISTRUNINFO record is the first run data object to follow the run data object entry record sequence created by Domino or Notes. If available, this structure (defined in queryods.h) contains the following run information for the last execution of the agent:

typedef struct
{
TIMEDATE LastRun; /* Time of last agent run */
DWORD dwProcessed; /* Number of documents processed on last run */
TIMEDATE AssistMod; /* Time date of last assistant modification */
TIMEDATE DbID; /* DbID on which assistant was last run */
LONG dwExitCode; /* Exit code when assistant was last run */
DWORD dwSpare[4];
} ODS_ASSISTRUNINFO;


The LastRun field is the time/date of the last execution.

The dwProcessed field specifies the number of documents modified by the last run of the agent. This value is only valid for formula-based agent actions. Since LotusScript agent actions run once, Domino and Notes cannot determine the number of documents modified and the value is not reported to this field.

The AssistMod field contains the time/date for the last modification of the agent.

The DbID field contains the replica ID of the database against which the agent last ran.

The dwExitCode field holds the return code from the last agent execution.

The dwSpare field is reserved and should be set to 0.

Agent Log
The agent log is the third run data object created and/or modified by Domino or Notes. It contains the null-terminated character string displayed by the Notes Agent UI after the agent executes.


Running Agents

The agents.h include file declares and defines the functions, data types, and symbolic constants used to properly execute an agent note residing in the database. This section describes how to use the C API to execute agent notes. For additional information, see the ExecuteAgent and GetAgentRunInfo routines from the AGENTS sample program in ragents.c.

Follow these steps to use the C API to run an agent. For details, look for the subroutines in the AGENTS sample program, ragent.c, that are mentioned in parentheses below.

1. Open a run handle for the agent note. (OpenAgent)
Call AgentOpen to return a handle of type HAGENT that is associated with the specifed agent note and database. Domino and Notes uses the resources provided by the agent run handle when you use AgentRun to execute the agent. To locate the agent note ID to pass to AgentOpen in an open database, call NIFFindDesignNote for shared agent notes or NIFFindPrivateDesignNote for private agent notes.

The agent run handle returned by AgentOpen is thread-safe but can only be referenced by the thread that created it. You must call AgentClose to free the agent run handle before reusing it with a different agent note or exiting.

2. Create an agent run-time context handle. (SetRunContext)
Call AgentCreateRunContext to create an agent run-time context handle of type HAGENTCTX that can be used with all subsequent agent executions. The agent run-time context maintains execution information for the agent run handle it is paired with when you call AgentRun. Note that, although required by AgentRunContext, the run handle input parameter is ignored by and not relevent to AgentCreateRunContext.

The run-time context handle is also thread-safe and can only be used by the thread that created it. You must call AgentDestroyRunContext to free the runtime context handle before exiting.

3. Set up a "Parameter Document" for LotusScript agent actions. (SetRunContext)
If the agent to be run has a LotusScript action that uses subroutine input parameters, call AgentSetDocumentContext to assign the note handle to an open document with the current runtime context handle. A subsequent call to AgentRun will pass the note handle to LotusScript via a special property of the back-end NotesSession class, defined as follows:

NotesDocument = NotesSession.DocumentContext

The NotesDocument can be instantiated by the action script routine and its field values can be read in as parameters to the LotusScript subroutine.

Since the document context is assigned to the current run-time context handle, you should reset it before each call to AgentRun.

4. Set up PRINT statement output redirection for LotusScript agent actions. (SetRunContext)
If the agent to be run has a LotusScript action that uses PRINT statements, call AgentRedirectStdout to either disable standard output or redirect it to the log.nsf file or an in-memory buffer. The output of the PRINT statements is assigned to the current run-time context handle and is controlled by the redirType argument of AgentRedirectStdout. You can set this argument to one of the following constant values, defined in agents.h: redirType Value Redirected Standard Output
AGENT_REDIR_NONE Disabled
AGENT_REDIR_LOG LOG.NSF
AGENT_REDIR_MEMORY Memory buffer - reset with each call to AgentRun
AGENT_REDIR_MEMAPPEND Memory buffer - appended to with each call to AgentRun

When redirecting to memory, you must call AgentQueryStdoutBuffer after the agent execution to read the output buffer.

Since this redirection is associated with the run-time context handle, you can change the desired action before each call to AgentRun.

5. Execute the agent. (ExecuteAgent)
Call AgentRun to make Domino or Notes run the agent note defined by the specified run handle and run-time context handle arguments. Set the reserved hSelection parameter to 0. For the dwFlags parameter, if AGENT_REOPEN_DB is set, the AgentRun call will reopen the agent's database with the privileges of the signer of the agent. If the flag is not set, the agent's "context" database will be open with the privileges of the current user (either the current Notes id, or the current Domino
web user). The AgentRun routine pends until the desired agent execution has completed.

If a background agent erroneously refers to the UI (front-end) classes, you might get one of the following errors:
If the scripts were included in the Script Libraries, Notes returns
"Error loading USE or USELSX module: <modulename>" error message;
otherwise, the AgenRun API returns the "Unknown LotusScript Error" error message.

6. Get the agent execution results and output. (GetAgentRunInfo, GetScriptRunInfo)
After the agent has executed, retrieve the results and any redirected LotusScript agent output. The execution results are in the $AssistRunInfo item of the agent note. For details about this item and its use, refer to the previous section. If the agent action was LotusScript-based and the current run-time context handle was set to support standard output redirection to an in-memory buffer, you can call AgentQueryStdoutBuffer to retrieve this information. This routine returns a handle to the redirected output and its byte length that is assigned to the specified run-time context handle argument. You can then lock, read, and unlock the returned handle as desired. Note that this handle is owned by Domino or Notes and must not be freed by the C API program.

7. Close the agent run handle. (CloseAgent)
When you are through executing a particular agent note, call AgentClose to close the associated run handle. This call also frees any resources associated with the run handle; subsequent calls that use this handle fail unless you perform another call to AgentOpen.

8. Close the agent run-time context handle. (CloseAgent)
Call AgentDestroyRunContext to close the current agent run-time context handle. This call also frees the resources associated with the run-time context handle, including the LotusScript document context and redirected standard output handles. Subsequent calls that use this handle fail unless you perform another call to AgentCreateRunContext.

Note: On Unix platforms, if you have a C API program which expects to run LotusScript agents, you must either put the program in the Domino executable directory, or put the Domino resource directory on the Path. This must be done so that Unix can find Domino resource files at runtime.
----------------------------------------------------------------------------------------------------------