The KB agent architecture provides a system of fully customizable, modular agents that can perform various tasks, including making assertions, creating terms, responding to user input, and triggering forward inference. Each agent is an instance of #$KBSpecifiedAgent, a set of instructions that abstractly specify how instantiations of that agent should behave. In brief, agents can be used to run queries, perform TOE operations, bind indexicals, trigger constrained forward inference, process query graphs, and control when and how other agents are run. This module will explain how to create an agent based application, how to instuct agents so that they perform specified actions, and will explain how to run an agent.
Make an Uber Agent
An uber agent is the agent that directs and controls all of the other agents in an application. Any agent-based application will require an uber agent (and will typically have exactly one). All uber agents are instances of #$UberAgent.
Once you have an uber agent, you may begin adding director or worker agents. These are the agents that form the functional structure of the application. Each agent must be a sub-agent of the uber agent or some other director agent. Add sub-agents to the uber agent using the predicate #$kbAgentSubAgents.
Make Worker Agents
Worker agents are the agents that do the actual work of the application. Such agents should be instances of #$KBSpecifiedAgent. Worker agents can be used to do the following:
- Run a query (or multiple queries) and TOE results
- Perform constrained forward inference
- Run a query (or multiple queries) and bind indexicals values to results from those queries
- Execute arbitrary SubL (see #$kbAgentApplicationDefn)
- Process a query graph
Any worker agent can perform any or all of these tasks.
Query Indexicals
When a KB agent runs a KBQ, it first substitutes out any indexicals in the query sentence or microtheory for which it has bindings. Generally, when a KB agent establishes a binding for an indexical, the value is stored on the uber agent, and is visible/available to all sub-agents of that uber agent until a new value is recorded. An exception to this rule is when a KB agent shadows an indexical, using #$agentShadowsIndexicalWithInitialValueTemplate, in which case values for that indexical recorded by that agent or any of its sub-agents are visible/available only to its sub-agents.
Query + TOE
To have an agent run a query and TOE the results, create a reified version of the query and connect it to the agent using #$kbAgentQuery.
If you want the results of the query to be asserted, create an instance of #$TOEAssertSpecification and associate with the query. If you wish to edit, use a #$TOEEditSpecification. You can also perform kill operations using #$TOEKillSpecification and create new constants by adding #$CreateConstantsInResponseToOpenVariablesParameter #$True to the specification. You can associate multiple TOE specifications with a single query.
Multiple query + TOE operations can be run by a single agent. If you need your queries to run in a specific order, you can assign them an order using #$kbAgentQueryDependsOnQuery.
You can also set an agent to run multiple queries in parallel such that the success of one query will cause the system to ignore the results of another. To do this, relate the queries using #$kbAgentQueryTrumpsQuery. For example, given (kbAgentQueryTrumpsQuery AGENT KBQ1 KBQ2)
, if AGENT runs both KBQ1 and KBQ2, and they both succeed (i.e. the inferences get one or more answers), the results of KBQ2 will be ignored. If KBQ1 succeeds before KBQ2 is finished, the inference for KBQ2 will be aborted.
Constrained Forward Inference
Agents can be used to trigger suites of forward rules off of specific trigger GAF assertions. To set an agent to trigger a rule, use #$kbAgentRule to associate the rule with the agent.
Use #$kbAgentRepropagateGAFPredsAndMTTypes to assert of the agent that any asserted GAF with a particular predicate as the operator found in a particular type of microtheory should be repropagated when the agent is run. For example, this assertion
(#$kbAgentRepropagateGAFPredsAndMTTypes #$KBNLUAgent-LexNodeInterpretationCreator-Maker #$viableProposedMeaning #$SemanticInterpretationMicrotheory)
means that for the agent #$KBNLUAgent-LexNodeInterpretationCreator-Maker, any asserted GAF with #$viableProposedMeaning as the operator found in an instance of #$SemanticInterpretationMicrotheory should be repropagated when the agent is run.
Use #$kbAgentRepropagateGAFTempsAndMTTypes to assert of the agent that any GAF matching a particular template in a particular type of microtheory should be repropagated when the agent is run.
An agent can run both queries and forward inference, but bear in mind that queries are run first, and forward inference occurs second.
Query + Indexical Binding
Agents can also be set to run a query whose results (or modifications of those results) are assigned as the value of the indexical. For example, suppose you want to set the result of a previous agent as the value of an indexical which will be used in later queries. To do this, you would reify a query that, when run by the agent, would return the result you are looking for as the binding for ?VARIABLE, and then make an assertion like the following:
(#$agentBindsIndexicalToActionSpecVariableTemplate AGENT QUERY (Quote ?VARIABLE) INDEXICAL)
More specialized versions of this can be done using #$agentAddsValueOfActionSpecVariableTemplateToIndexicalBindingSet, #$agentAddsValueOfActionSpecVariableTemplateToIndexicalBindingSet or #$agentBindsTabularResultsToIndexical.
The same query can be used for both a TOE operation and indexical binding.
Executing SubL
Agents can be used to invoke SubL via #$kbAgentApplicationDefn:
(#$kbAgentApplicationDefn AGENT (SubLQuoteFn SUBL-FUNCTION-NAME))
For example, we specify that the #$KBNLUAgent-SyntacticLinkPromoter executes the SubL function KBNLU-PROMOTE-SYNTACTIC-LINKS with this assertion:
(#$kbAgentApplicationDefn #$KBNLUAgent-SyntacticLinkPromoter (#$SubLQuoteFn KBNLU-PROMOTE-SYNTACTIC-LINKS))
If an agent has an application defn, any associated #$kbAgentActionQueries will still be executed, but no other related queries or GAF repropagation (as specified in the KB) will be performed. (Of course such agents could perform query+TOE operations or GAF repropagation if such actions were specified in SubL — along with a host of other possible actions.)
Make Director Agents
You may have a number of worker agents that are all working together to accomplish some task. You can group them together under a single director agent, which assists in determining when worker agents are applied.
Director agents are agents that have sub-agents. Technically, the uber agent is a director agent. You will often have multiple director agents as sub-agents of the uber agent. The sub-agents of a director agent can be either director agents or worker agents, and you can have arbitrary nesting of director agents, although in practice this rarely exceeds 5 or 6 levels.
Director agents are related to their sub-agents via #$kbAgentSubAgents.
Determining When to Apply Agents
Rigidly Ordered Agents
In some cases, you may be able to specify a rigid ordering of your agents or sub-agents, explicitly indicating that one agent should be run after another. To do this, use #$kbAgentSubAgentList. The order of the specified list is the order in which the agents will be run.
If you have an uber agent or director agent whose sub-agents are ordered via a list, you must indicate how the sub-agents are to be run. If they should be run once in order, make the following assertion on your agent:
(#$kbAgentSubAgentDirective AGENT #$KBAgentWithSingleRunSubAgents)
If you want the sub-agents to run in a cycle until some condition is satisfied, make the following assertion on your director agent:
(#$kbAgentSubAgentDirective AGENT #$KBAgentWithRepeatedSubAgents)
Then, associate the director agent with a reified query that identifies the condition that should cause the cycle to stop using #$kbAgentHaltQueryOccurrenceDirective.
Action Queries
If the application of your agents is dependent on some changing state (code, KB, database), you can use action queries to help determine when agents run. Agents are associated with their action queries via #$kbAgentActionQuery, which relates the agent, a query, an occurrence-directive identifying when the query should be run, an action directive identifying what should be done if the query is successful, and an optional second action directive identifying what should be done if the query is not successful.
For example,
(#$kbAgentActionQuery #$DialogSeqAgent-SummaryOfStatsForQuestionsOnTopic #$DialogAgentQuery-WeShouldBreakOutOfDialogSequence
(#$KBAgentActionQueryRunAfterAgentFn #$DialogAgent-TopicIdentifier)
(#$KBAgentActionFn-EndAgent #$DialogSeqAgent-SummaryOfStatsForQuestionsOnTopic))
means the agent #$DialogSeqAgent-SummaryOfStatsForQuestionsOnTopic should run the query #$DialogAgentQuery-WeShouldBreakOutOfDialogSequence after its sub-agent #$DialogAgent-TopicIdentifierends, and if the query succeeds, it should end itself.
The possible occurrence directives are #$KBAgentActionQueryRunAtStart, which tells the code to run that agent at the start of the director agent, and (#$KBAgentActionQueryRunAfterAgentFn AGENT) which tells the director to run that query after a certain agent ends.
The possible action directives are (#$KBAgentActionFn-StartAgent AGENT), which tells the code to start an agent; (#$KBAgentActionFn-StartDeepCoverAgent AGENT), which tells the code to start a deep cover agent (a special kind of agent that runs in a background thread with no way to communicate back to the agent that launched it); (#$KBAgentActionFn-PauseAgent AGENT), which tells the code to pause an agent; and (#$KBAgentActionFn-EndAgent AGENT), which tells the code to end an agent.
Fallback Agent
If the indexical (#$TheNamedFn #$KBSpecifiedAgent (“next agent when other directives don’t say what to do”) is bound to an agent, the agent code will run this agent next in cases where it doesn’t otherwise know what to do next.
Running an Uber Agent
The following code can be used to call an uber agent that does not require initial indexical bindings:
(start-uber-agent [YOUR-UBER-AGENT])
The following code can be used to call an uber agent with a specified binding set for required N indexicals:
(clet ((indexical-bindings '((INDEXICAL-1 . INDEXICAL-1-VALUE)
(INDEXICAL-2 . INDEXICAL-2-VALUE)
…
(INDEXICAL-N . INDEXICAL-N-VALUE))
(uber-agent (nth-value 1 (new-uber-agent UBER-AGENT indexical-bindings))))
(start-uber-agent uber-agent))
The Uber Agent Runner tool in the Cyc Browser will let you select an uber agent, specifying starting indexical values, and start it running, displaying log output as it goes.