@@ -739,6 +739,124 @@ public JsonNode getAgentExecutionStatus(AgentExecution execution, AgentExecution
739739 return JsonUtil .MAPPER .createObjectNode ();
740740 }
741741
742+ @ Verb (
743+ name = "get_current_agent_status" , returnType = ObjectNode .class , description =
744+ "Queries and summarizes questions against the current agent's memory, history, and context. " +
745+ "Provides detailed information about agent state including messages, short-term memory, and execution context." ,
746+ requiresTokenManagement = true ,
747+ argName = "query" ,
748+ exampleJson = "{ \" query\" : \" What tasks has the agent completed?\" }"
749+ )
750+ public ObjectNode getCurrentAgentStatus (AgentExecution execution , AgentExecutionContextDTO context )
751+ throws ZtatException , JsonProcessingException {
752+ var status = agentExecutionService .getExecutionContextDTO (execution .getExecutionId ());
753+
754+ if (status == null ) {
755+ ObjectNode errorNode = JsonUtil .MAPPER .createObjectNode ();
756+ errorNode .put ("error" , "No execution context found for this agent" );
757+ return errorNode ;
758+ }
759+
760+ // Get the user's query if provided
761+ Optional <JsonNode > queryNode = context .getExecutionArgument ("query" );
762+ String userQuery = queryNode .map (JsonNode ::asText ).orElse ("Provide a summary of the agent's current status" );
763+
764+ // Build context information
765+ ObjectNode statusInfo = JsonUtil .MAPPER .createObjectNode ();
766+ statusInfo .put ("executionId" , execution .getExecutionId ());
767+ statusInfo .put ("messageCount" , status .getMessages ().size ());
768+ statusInfo .put ("shortTermMemorySize" , status .getAgentShortTermMemory ().size ());
769+ statusInfo .put ("persistentMemorySize" , status .getPersistentMemoryItems ().size ());
770+ statusInfo .put ("dataListSize" , status .getAgentDataList ().size ());
771+
772+ // Add agent context if available
773+ if (status .getAgentContext () != null ) {
774+ ObjectNode agentContextInfo = JsonUtil .MAPPER .createObjectNode ();
775+ agentContextInfo .put ("name" , status .getAgentContext ().getName ());
776+ if (status .getAgentContext ().getContextId () != null ) {
777+ agentContextInfo .put ("contextId" , status .getAgentContext ().getContextId ().toString ());
778+ }
779+ agentContextInfo .put ("description" , status .getAgentContext ().getDescription ());
780+ statusInfo .set ("agentContext" , agentContextInfo );
781+ }
782+
783+ // Add short-term memory keys
784+ ArrayNode memoryKeys = JsonUtil .MAPPER .createArrayNode ();
785+ status .getAgentShortTermMemory ().keySet ().forEach (memoryKeys ::add );
786+ statusInfo .set ("memoryKeys" , memoryKeys );
787+
788+ // Add persistent memory keys
789+ ArrayNode persistentMemoryKeys = JsonUtil .MAPPER .createArrayNode ();
790+ status .getPersistentMemoryItems ().keySet ().forEach (persistentMemoryKeys ::add );
791+ statusInfo .set ("persistentMemoryKeys" , persistentMemoryKeys );
792+
793+ // Prepare messages for LLM query
794+ List <Message > messages = new ArrayList <>();
795+
796+ messages .add (Message .builder ().role ("system" ).content (
797+ "You are analyzing the current state of an AI agent. " +
798+ "You have access to the agent's execution history, memory, and context. " +
799+ "Answer the user's query based on this information. " +
800+ "Provide a clear, concise response in JSON format with the following structure: " +
801+ "{ \" answer\" : \" your answer\" , \" details\" : \" additional details if relevant\" }"
802+ ).build ());
803+
804+ messages .add (Message .builder ().role ("system" ).content (
805+ "Agent Status Information: " + statusInfo .toString ()
806+ ).build ());
807+
808+ // Include recent message history (last 20 messages)
809+ List <Message > recentMessages = ListUtils .getLastNElements (status .getMessages (), 20 );
810+ if (!recentMessages .isEmpty ()) {
811+ messages .add (Message .builder ().role ("system" ).content (
812+ "Recent message history (last " + recentMessages .size () + " messages):"
813+ ).build ());
814+ messages .addAll (recentMessages );
815+ }
816+
817+ messages .add (Message .builder ().role ("user" ).content (userQuery ).build ());
818+
819+ // Query LLM
820+ LLMRequest chatRequest = LLMRequest .builder ().model ("gpt-4o-mini" ).messages (messages ).build ();
821+ var resp = llmService .askQuestion (execution , chatRequest );
822+ context .addMessages (messages );
823+ Response response = JsonUtil .MAPPER .readValue (resp , Response .class );
824+
825+ for (Response .Choice choice : response .getChoices ()) {
826+ var content = choice .getMessage ().getContentAsString ();
827+ if (content .startsWith ("```json" )) {
828+ content = content .substring (7 , content .length () - 3 );
829+ } else if (content .startsWith ("```" )) {
830+ content = content .substring (3 , content .length () - 3 );
831+ }
832+
833+ log .info ("LLM response content: {}" , content );
834+
835+ if (null != content && !content .isEmpty ()) {
836+ try {
837+ JsonNode responseNode = JsonUtil .MAPPER .enable (JsonParser .Feature .ALLOW_COMMENTS ).readTree (content );
838+ if (responseNode .isObject ()) {
839+ ObjectNode result = (ObjectNode ) responseNode ;
840+ result .set ("statusInfo" , statusInfo );
841+ return result ;
842+ }
843+ } catch (Exception e ) {
844+ log .warn ("Failed to parse LLM response as JSON, returning as plain text" , e );
845+ ObjectNode result = JsonUtil .MAPPER .createObjectNode ();
846+ result .put ("answer" , content );
847+ result .set ("statusInfo" , statusInfo );
848+ return result ;
849+ }
850+ }
851+ }
852+
853+ // Fallback response
854+ ObjectNode result = JsonUtil .MAPPER .createObjectNode ();
855+ result .put ("answer" , "Unable to generate a response" );
856+ result .set ("statusInfo" , statusInfo );
857+ return result ;
858+ }
859+
742860 @ Verb (name = "create_agent" , returnType = AgentExecutionContextDTO .class , description = "Creates an agent who has the " +
743861 "context. a previously defined contextId is required. previously defined endpoints can be used to build a " +
744862 "trust policy. must call create_agent_context before this verb. agent type is chat or chat-autonomous. chat is chat only, chat-autonomous is chat and autonomous. determine based on workload." ,
0 commit comments