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