39daa815 by Ean Schuessler

Implement Reliable Agent Architecture using CommunicationEvent thread logic

- Update AgentServices.xml: Single-turn state machine (process one turn, re-queue if tool called)
- Add Agent.secas.xml: Trigger Agent Turn on new CommunicationEvent to Agent Party
- Update AgentEntities.xml: Add rootCommEventId to SystemMessage for thread tracking
- Update AgentData.xml: Define Agent Party, Role, and default VLLM config
1 parent 85eedd26
...@@ -2,20 +2,18 @@ ...@@ -2,20 +2,18 @@
2 <entity-facade-xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 <entity-facade-xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/entity-facade-3.xsd" type="seed"> 3 xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/entity-facade-3.xsd" type="seed">
4 4
5 <!-- ========================================================= --> 5 <moqui.security.UserGroup userGroupId="AgentUsers" description="AI Agent Users"/>
6 <!-- Agent User Account (for authentication) -->
7 <!-- ========================================================= -->
8 6
9 <moqui.security.UserAccount 7 <!-- Agent Party -->
10 userId="AGENT_CLAUDE" 8 <mantle.party.Party partyId="AGENT_CLAUDE_PARTY" partyTypeEnumId="PtyPerson"/>
11 username="agent-claude" 9 <mantle.party.Person partyId="AGENT_CLAUDE_PARTY" firstName="Claude" lastName="Agent"/>
12 currentPassword="16ac58bbfa332c1c55bd98b53e60720bfa90d394" 10 <mantle.party.PartyRole partyId="AGENT_CLAUDE_PARTY" roleTypeId="Agent"/>
13 passwordHashType="SHA"/>
14 11
15 <moqui.security.UserGroup userGroupId="AgentUsers" description="AI Agent Users"/> 12 <moqui.security.UserAccount userId="AGENT_CLAUDE" username="agent-claude" partyId="AGENT_CLAUDE_PARTY"
13 currentPassword="16ac58bbfa332c1c55bd98b53e60720bfa90d394" passwordHashType="SHA"/>
16 <moqui.security.UserGroupMember userGroupId="AgentUsers" userId="AGENT_CLAUDE" fromDate="2026-02-04 00:00:00.000"/> 14 <moqui.security.UserGroupMember userGroupId="AgentUsers" userId="AGENT_CLAUDE" fromDate="2026-02-04 00:00:00.000"/>
17 15
18 <!-- Agent users have permission to execute the delegation service --> 16 <!-- Agent users have permission to execute delegation service -->
19 <moqui.security.ArtifactGroup artifactGroupId="AgentDelegationServices" description="Agent Tool Delegation Services"/> 17 <moqui.security.ArtifactGroup artifactGroupId="AgentDelegationServices" description="Agent Tool Delegation Services"/>
20 <moqui.security.ArtifactGroupMember artifactGroupId="AgentDelegationServices" artifactName="AgentServices.call#McpToolWithDelegation" artifactTypeEnumId="AT_SERVICE"/> 18 <moqui.security.ArtifactGroupMember artifactGroupId="AgentDelegationServices" artifactName="AgentServices.call#McpToolWithDelegation" artifactTypeEnumId="AT_SERVICE"/>
21 <moqui.security.ArtifactAuthz userGroupId="AgentUsers" artifactGroupId="AgentDelegationServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 19 <moqui.security.ArtifactAuthz userGroupId="AgentUsers" artifactGroupId="AgentDelegationServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
...@@ -27,7 +25,13 @@ ...@@ -27,7 +25,13 @@
27 <!-- Agent Task Message Type --> 25 <!-- Agent Task Message Type -->
28 <moqui.service.message.SystemMessageType systemMessageTypeId="SmtyAgentTask" description="Agent Task" 26 <moqui.service.message.SystemMessageType systemMessageTypeId="SmtyAgentTask" description="Agent Task"
29 contentType="application/json" 27 contentType="application/json"
30 consumeServiceName="AgentServices.poll#AgentQueue" 28 consumeServiceName="AgentServices.poll#AgentQueue"/>
31 receiveServiceName=""/> 29
30 <!-- Default AI Config (Brainfood VLLM) -->
31 <moqui.mcp.agent.ProductStoreAiConfig
32 productStoreId="POPC_DEFAULT" aiConfigId="DEFAULT"
33 serviceTypeEnumId="AistVllm" description="Brainfood VLLM"
34 endpointUrl="http://crunchy.private.brainfood.com:11434/v1" apiKey="brainfood"
35 modelName="bf-ai" temperature="0.7" maxTokens="4096"/>
32 36
33 </entity-facade-xml> 37 </entity-facade-xml>
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
19 <field name="aiConfigId" type="id"> 19 <field name="aiConfigId" type="id">
20 <description>Specific AI configuration used for this task.</description> 20 <description>Specific AI configuration used for this task.</description>
21 </field> 21 </field>
22 <field name="rootCommEventId" type="id">
23 <description>The root CommunicationEvent ID for the conversation thread.</description>
24 </field>
22 25
23 <relationship type="one" title="RequestedBy" related="mantle.party.Party"> 26 <relationship type="one" title="RequestedBy" related="mantle.party.Party">
24 <key-map field-name="requestedByPartyId" related="partyId"/> 27 <key-map field-name="requestedByPartyId" related="partyId"/>
......
1 <?xml version="1.0" encoding="UTF-8"?>
2 <secas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/service-eca-3.xsd">
3 <seca id="AgentTriggerOnCommunication" service="create#mantle.party.communication.CommunicationEvent" when="post-service">
4 <condition>
5 <expression>toPartyId == 'AGENT_CLAUDE_PARTY'</expression>
6 </condition>
7 <actions>
8 <!-- Ensure rootCommEventId is set (thread tracking) -->
9 <script><![CDATA[
10 def rootId = rootCommEventId ?: communicationEventId
11 if (!rootCommEventId) {
12 ec.service.sync().name("update#mantle.party.communication.CommunicationEvent")
13 .parameters([communicationEventId: communicationEventId, rootCommEventId: rootId])
14 .call()
15 }
16
17 // Trigger Agent Turn
18 ec.service.sync().name("create#moqui.service.message.SystemMessage").parameters([
19 systemMessageTypeId: 'SmtyAgentTask',
20 statusId: 'SmsgReceived',
21 requestedByPartyId: fromPartyId,
22 effectiveUserId: ec.user.userId, // Use the actual human user ID for RBAC
23 productStoreId: 'POPC_DEFAULT',
24 aiConfigId: 'DEFAULT',
25 rootCommEventId: rootId,
26 isOutgoing: 'N'
27 ]).call()
28 ]]></script>
29 </actions>
30 </seca>
31 </secas>