To check your current agent cycle time and number of agents use the Tinderbox Inspector, Agents & Rules tab.
Controlling Agent Priority
The $AgentPriority attribute, allows the user to set the periodicity with which agents are run. This attribute can be set via;
- Get Info, agent tab.
- Get Info, attributes tab, General group.
- Key Attributes, if $AgentPriority is added.
- Properties Inspector, Quickstamp tab.
- Action Inspector, Query tab.
- Action code.
This attribute allows agents with queries tracking low rate of change to be run less often, reducing the overall agent cycle time.
When set to 'Off' (-1), Tinderbox 'freezes' the contents of an agent and it does not run again; this reduces the overall cycle time. It means that when turned off, the agent retains whatever children it had at the last update cycle before it was turned off. Agents switched 'off' do not get updated via the file menu's 'Update now' command. It is thus not possible to have an agent that is only 'manually' updated.
This means that agents can be used to harvest sets of aliases and then turned off to 'fix' the content. Alternatively, such agents' priority can be turned on/up to update content before an export and then turned off/down. aTbRef uses this method for agents used to do tasks such as representing the main attribute list in alternate forms such as by data type or TBX system attribute group.
To avoid having to change each agent by hand, they are located by an 'utility' agent '@attributes_agents_frequency' with this query:
inside(Attribute Data Types) | inside(Attribute Groups)
An action sets priority for the matches found (which here will be agents):
Note the $AgentPriority must be set using a numerical value. Using 'Low' instead of '10' results in—due to type coercion—a value of 'Highest' and not quite what's wanted. In turn, this utility agent is turned off when not in use. When enabled, it allows 18 agents to be controlled via one setting.
Although the Agents & Rules Inspector tab will tell you how many agents you have, you may be sure where they are in your TBX. An agent can help using this query:
Notes, adornments, etc., will not have an $AgentPriority value. More precisely, adornments may have an $AgentPriority but only if they are 'smart' adornments.
Now you have all the agents you can use use the Show Original command to locate the agent. To aid more granular control of separate groups of agents, consider their location in the TBX. For example, in aTbRef the exported content, with the exception of the RSS feeds is all in one note hierarchy 9outline branch). A separate root-level note 'UTILS' contains, sets of prototypes and utility agents. Meanwhile both the Attribute and Export Code section use agents to present their lists in different splits; because the agents are within a containing (note) the #inside() query syntax can be used to easily locate them.
If your agents are more scattered in the TBX consider using a user set/attribute to flag agents so an agent may easily find them. however location based queries (as above) are more efficient, for reason discussed further below.
Altering Content of Disabled Agents
When switched off, an agent retains the aliases it had at that point. You can also do several things you cannot do when the agent is active:
- Re-order the aliases, e.g. alter the outline order or map location
- Delete aliases without them being recreated (N.B. you cannot add new notes aliases)
Note that re-enabling the agent may undo some of the above order/location changes and may add back deleted aliases.
If you need to alter the layout of an active agent, make sure to set $CleanupAction to any non-default value.
Making Agents More Efficient
In small TBXs you will not notice your agent settings affecting update time but as a TBX grows in size and complexity, ideally your agents should match as few notes as possible, or at least where that is possible to do so, in order to keep performance snappy. In this context, think about using inside() and descendedFrom() as part of your queries. The former allows you specify only the immediate children of a given note whilst the latter matches any descendant of a given note. For example, if searching for text in children of a note called 'The Library', it is much faster to run:
inside("The Library)" & $Text.contains("When.+April")
$Text.contains("When.+April") & inside("The Library")
…because the inside() part of the query cuts the number of notes searched. The second example does a regular expression search against all notes in the TBX before the results are then filtered to only children of 'The Library).
It is much faster, in performance terms, to factor out very complex queries into separate agents, and then use inside() to leverage those agents, than it is to repeat the queries. Complex regular expressions are also comparatively heavy users of TB thinking time so consider if there is not an easier way to find the same match. For example, if using such an expression to find misspellings, you might delete the agent when done or at least turn it off between major editing sessions.
As a general point, regex (regular expression) based queries like .contains(0 and .icontains() are far more CPU-intensive than many other actions.
Check That Results Make Sense
Finally, beware of broken agents. Sometimes, a syntax error can create an agent that finds nothing (or the wrong things), but takes an age to do so.
Disabling Automatic Updates
Trying to do text editing and getting disturbed by the hourglass? In a big TBX with many agents this can happen. In such circumstances it can help to disable the "Update Agents Automatically" option (via the File menu), just do not forget to enable it again if your document relies on ongoing use of live agents.
Flushing All Agents
File menu -> Update Agents Now runs all 'on' agents once. It also forces the process in front of other task, like running rules. This can be useful if a document has many agents and rules and you wish to update agents more quickly, e.g. to reflect a change you know youhave made. But…
If you either do not use (or have temporarily turned off) automatic updates, you can use the same (File) menu to force a one-off update via "Update now" (cmd+ctrl+=). However, if you use a lot of agents and have different priorities set it can be a wise idea to use this update call several times in succession to ensure all agents are fired, as those agents with lower priority settings are omitted from some firing cycles (i.e. update); the lower the priority setting, the more often an agent is omitted from the cycle. For instance, for the aTbRef TBX it can take 3 or 4 successive "Update now" calls to ensure all the low priority agents are run. Failure to do so means that sections like the listings of attributes by data type do not get populated, given that the HTML output expects each alias to be exported as a separate HTML file. If the TBX is not properly updated after being opened, some sections (agent containers) my be empty until enough update cycles has completed to populate even the lowest priority ones.
However, Tinderbox is aware of the latter issue and when doing an HTML export, Tinderbox should update all agents regardless of priority before export (including agents set to 'Off') but it is still worth checking output to ensure that output depending on several agent's actions has actually been generated. Once happy the process is working as expected, you can ease back on such checks.
Put another way, when you get creative with agents and start to create more complex TBXs, do not just check for the obvious output but look for unintended consequences: either of your query/action/rule coding or simply the inheritances and agent activities youhave put in place.