Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/agents/mcp_tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,24 @@ The runtime reads `_meta` from `pixel_mcp.json` and `py_mcp.json` as written, so

See [run lifecycle](agent_runs.md) for approval states and [the harness](semoss_harness.md#tools-and-execution-policy) for the built-in tool groups.

## Pre-chat tool

One toolbox tool can run once, when a room is set up and before its first message. Its result goes in front of the text of that first user message: the model reads it there on this and every later turn, and the UI shows only what the user typed (the message's `uiText`). Nothing else is added to the room's history. A typical choice is a discovery tool such as ECU's `GetRoomResources`, so the model starts with the room's documents, skills and toolboxes in context instead of spending its first step calling the tool.

| Surface | Configured by |
| --- | --- |
| `RunAgent` (native `semoss` harness) | Deployment properties, only when `AGENT_DEFAULT_TOOLS_MCP_ID` replaces the default tools: `AGENT_DEFAULT_TOOLS_PRE_CHAT_TOOL` (tool name in that toolbox), optional `AGENT_DEFAULT_TOOLS_PRE_CHAT_ARGS` (JSON object) and `AGENT_DEFAULT_TOOLS_PRE_CHAT_MAX_CHARS`. Skipped when the agent turns default tools off or lists the tool in `tool_policy.default_tools.disabled`, and for PPTX workflow runs. |
| `AskPlayground` | `playground.preChatTool` in the active theme map: `{"tool": "GetRoomResources", "toolboxId": "<engine or project id>", "args": {}, "maxChars": 60000}`. Without `toolboxId`, the tool is looked up in `playground.defaultTools` (the toolboxes the UI attaches to every new room), in order. |

Both use [PreChatContext](../../src/prerna/reactor/agent/runtime/PreChatContext.java):

- The tool runs through `MCPUtility.executeTool`, so the user's access to the toolbox is checked and `SMSS_FUNCTION_NAME` applies.
- A tool that is missing, `disabled` or `ask` is skipped; nothing is shown to approve before the first message.
- The insight must be unbound or bound to the room (chat mode binds it with `SetRoomForInsight`); an unbound insight is bound to the room first.
- The result is cut to `maxChars` (default 60,000) and wrapped in `<pre_chat_context tool="...">` with a note telling the model it need not call the tool again unless something changed.
- Any failure is logged and skipped, and the chat continues as it would without the setting. The tool stays available, so the model can still call it itself.
- It runs once per room, only while the room has no messages. Files added later are not reflected until the model calls the tool again.

## Pitfalls

- Use lowercase execution values in hand-written JSON. The hide filter is case-sensitive.
Expand All @@ -238,4 +256,5 @@ See [run lifecycle](agent_runs.md) for approval states and [the harness](semoss_
| Room tool assembly and alias lookup | [Room](../../src/prerna/engine/impl/model/Room.java) |
| Deferred tools | [DeferredAgentTools](../../src/prerna/reactor/agent/run/DeferredAgentTools.java) |
| Platform tool defaults | [PlatformAgentTools](../../src/prerna/reactor/agent/runtime/PlatformAgentTools.java) |
| Pre-chat tool | [PreChatContext](../../src/prerna/reactor/agent/runtime/PreChatContext.java), [PlaygroundThemeUtils](../../src/prerna/theme/PlaygroundThemeUtils.java) |
| Approval pauses | [HarnessToolExecutor](../../src/prerna/reactor/agent/runtime/HarnessToolExecutor.java), [AgentToolDecisionHandler](../../src/prerna/reactor/agent/mcp/AgentToolDecisionHandler.java) |
6 changes: 6 additions & 0 deletions src/prerna/playground/reactors/AskPlaygroundReactor.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import prerna.playground.PlaygroundUtils;
import prerna.reactor.ReactorDefinition;
import prerna.reactor.agent.runtime.PreChatContext;
import prerna.reactor.model.AskRoomReactor;
import prerna.theme.PlaygroundThemeUtils;

Expand All @@ -44,6 +45,11 @@ protected boolean shouldHideSystemMessages() {
return PlaygroundThemeUtils.hidePlaygroundSystemMessages();
}

@Override
protected PreChatContext.Spec getPreChatTool() {
return PlaygroundThemeUtils.getPlaygroundPreChatTool();
}

@Override
public ReactorDefinition getReactorDefinition() {
return super.getReactorDefinition().description(
Expand Down
31 changes: 29 additions & 2 deletions src/prerna/reactor/agent/runtime/PlatformAgentTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import prerna.engine.api.IEngine;
import prerna.engine.api.ToolExecutionResult;
import prerna.reactor.agent.AgentRunContext;
import prerna.reactor.agent.config.AgentConfig;
import prerna.reactor.agent.mcp.MCPUtility;
import prerna.reactor.agent.mcp.MCPUtility.MCPExecution;
import prerna.reactor.agent.mcp.RunMCPToolReactor;
Expand All @@ -55,6 +56,9 @@ public final class PlatformAgentTools {
private static final String PARAM_TOOLS = "tools";
private static final String PROP_DEFAULT_TOOLS_MCP_ID = "AGENT_DEFAULT_TOOLS_MCP_ID";
private static final String PROP_DEFAULT_TOOLS_MCP_PROJECT_ID = "AGENT_DEFAULT_TOOLS_MCP_PROJECT_ID";
private static final String PROP_PRE_CHAT_TOOL = "AGENT_DEFAULT_TOOLS_PRE_CHAT_TOOL";
private static final String PROP_PRE_CHAT_ARGS = "AGENT_DEFAULT_TOOLS_PRE_CHAT_ARGS";
private static final String PROP_PRE_CHAT_MAX_CHARS = "AGENT_DEFAULT_TOOLS_PRE_CHAT_MAX_CHARS";
private static final Set<String> DEFERRED_DEFAULT_TOOLS = Set.of("InspectPptx", "MultiEdit");

private static final Map<String, PlatformAgentToolHandlers.ToolHandler> PLATFORM_TOOLS =
Expand Down Expand Up @@ -90,6 +94,29 @@ static List<Map<String, Object>> resolveDefaultTools(Map<String, Object> paramMa
return resolved;
}

/**
* The tool to run before a room's first message, from
* {@code AGENT_DEFAULT_TOOLS_PRE_CHAT_TOOL}. Only set when the deployment
* replaces the default tools ({@code AGENT_DEFAULT_TOOLS_MCP_ID}); the tool is
* looked up in that toolbox. Returns {@code null} when unset, or when this
* agent turns default tools off or disables that tool.
*/
static PreChatContext.Spec preChatSpec(AgentConfig agentConfig) {
String mcpId = getDefaultToolsMcpId();
String tool = Utility.getDIHelperProperty(PROP_PRE_CHAT_TOOL);
tool = tool != null ? tool.trim() : null;
if (mcpId == null || tool == null || tool.isEmpty()) {
return null;
}
if (agentConfig != null
&& (!agentConfig.useDefaultAgentTools() || agentConfig.getDisabledDefaultTools().contains(tool))) {
return null;
}
return PreChatContext.Spec.of(mcpId, tool,
PreChatContext.parseArgs(Utility.getDIHelperProperty(PROP_PRE_CHAT_ARGS)),
PreChatContext.parseInt(Utility.getDIHelperProperty(PROP_PRE_CHAT_MAX_CHARS)));
}

static ToolExecutionResult policyDenialResult(String toolName, AgentRunContext ctx) {
if (toolName == null || toolName.trim().isEmpty() || ctx == null) {
return null;
Expand Down Expand Up @@ -169,7 +196,7 @@ private static boolean useDefaultAgentTools(Map<String, Object> paramMap) {
return !("false".equals(normalized) || "0".equals(normalized) || "no".equals(normalized));
}

private static String getDefaultToolsMcpId() {
static String getDefaultToolsMcpId() {
String id = Utility.getDIHelperProperty(PROP_DEFAULT_TOOLS_MCP_ID);
if (id == null || id.trim().isEmpty()) {
id = Utility.getDIHelperProperty(PROP_DEFAULT_TOOLS_MCP_PROJECT_ID);
Expand Down Expand Up @@ -206,7 +233,7 @@ private static List<Map<String, Object>> getMcpToolDefinitions(String mcpId) {
return tools;
}

private static JSONObject findMcpTool(String mcpId, String toolName) {
static JSONObject findMcpTool(String mcpId, String toolName) {
JSONObject toolMap = getMcpToolsJson(mcpId);
JSONArray arr = toolMap != null ? toolMap.optJSONArray(PARAM_TOOLS) : null;
if (arr == null) {
Expand Down
Loading
Loading