Skip to content

Commit 60ef1ff

Browse files
Copilotphrocker
andauthored
Add get_current_agent_status verb for querying agent memory and history (#43)
* Initial plan * Add get_current_agent_status verb with comprehensive tests Co-authored-by: phrocker <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: phrocker <[email protected]>
1 parent 69e300d commit 60ef1ff

File tree

2 files changed

+407
-0
lines changed

2 files changed

+407
-0
lines changed

enterprise-agent/src/main/java/io/sentrius/agent/analysis/agents/verbs/AgentVerbs.java

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)