From c165bb3522cf3663f6c378dff52a7870a53db9f4 Mon Sep 17 00:00:00 2001 From: Cyber MacGeddon Date: Wed, 3 Sep 2025 16:16:30 +0100 Subject: [PATCH] Partial tool group implementation --- .../trustgraph/schema/services/agent.py | 2 +- trustgraph-cli/trustgraph/cli/set_tool.py | 29 +++++++++++++++++ .../trustgraph/agent/react/service.py | 31 +++++++++++++++++-- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/trustgraph-base/trustgraph/schema/services/agent.py b/trustgraph-base/trustgraph/schema/services/agent.py index 21d2fe1f..55f2ae0f 100644 --- a/trustgraph-base/trustgraph/schema/services/agent.py +++ b/trustgraph-base/trustgraph/schema/services/agent.py @@ -16,8 +16,8 @@ class AgentStep(Record): class AgentRequest(Record): question = String() - plan = String() state = String() + group = Array(String()) history = Array(AgentStep()) class AgentResponse(Record): diff --git a/trustgraph-cli/trustgraph/cli/set_tool.py b/trustgraph-cli/trustgraph/cli/set_tool.py index e39dfad7..b336a990 100644 --- a/trustgraph-cli/trustgraph/cli/set_tool.py +++ b/trustgraph-cli/trustgraph/cli/set_tool.py @@ -63,6 +63,9 @@ def set_tool( collection : str, template : str, arguments : List[Argument], + group : List[str], + state : str, + available_in_states : List[str], ): api = Api(url).config() @@ -93,6 +96,12 @@ def set_tool( for a in arguments ] + if group: object["group"] = group + + if state: object["state"] = state + + if available_in_states: object["available_in_states"] = available_in_states + values = api.put([ ConfigValue( type="tool", key=f"{id}", value=json.dumps(object) @@ -179,6 +188,23 @@ def main(): help=f'Tool arguments in the form: name:type:description (can specify multiple)', ) + parser.add_argument( + '--group', + nargs="*", + help=f'Tool groups (e.g., read-only, knowledge, admin)', + ) + + parser.add_argument( + '--state', + help=f'State to transition to after successful execution', + ) + + parser.add_argument( + '--available-in-states', + nargs="*", + help=f'States in which this tool is available', + ) + args = parser.parse_args() try: @@ -219,6 +245,9 @@ def main(): collection=args.collection, template=args.template, arguments=arguments, + group=args.group or [], + state=args.state, + available_in_states=getattr(args, 'available_in_states', None) or [], ) except Exception as e: diff --git a/trustgraph-flow/trustgraph/agent/react/service.py b/trustgraph-flow/trustgraph/agent/react/service.py index 74b89a1e..fbdb3f96 100755 --- a/trustgraph-flow/trustgraph/agent/react/service.py +++ b/trustgraph-flow/trustgraph/agent/react/service.py @@ -18,6 +18,7 @@ from ... schema import AgentRequest, AgentResponse, AgentStep, Error from . tools import KnowledgeQueryImpl, TextCompletionImpl, McpToolImpl, PromptImpl from . agent_manager import AgentManager +from ..tool_filter import validate_tool_config, filter_tools_by_group_and_state, get_next_state from . types import Final, Action, Tool, Argument @@ -142,6 +143,9 @@ class Processor(AgentService): f"Tool type {impl_id} not known" ) + # Validate tool configuration + validate_tool_config(data) + tools[name] = Tool( name=name, description=data.get("description"), @@ -219,9 +223,24 @@ class Processor(AgentService): await respond(r) + # Apply tool filtering based on request groups and state + filtered_tools = filter_tools_by_group_and_state( + tools=self.agent.tools, + requested_groups=getattr(request, 'group', None), + current_state=getattr(request, 'state', None) + ) + + logger.info(f"Filtered from {len(self.agent.tools)} to {len(filtered_tools)} available tools") + + # Create temporary agent with filtered tools + temp_agent = AgentManager( + tools=filtered_tools, + additional_context=self.agent.additional_context + ) + logger.debug("Call React") - act = await self.agent.react( + act = await temp_agent.react( question = request.question, history = history, think = think, @@ -255,11 +274,17 @@ class Processor(AgentService): logger.debug("Send next...") history.append(act) + + # Handle state transitions if tool execution was successful + next_state = request.state + if act.name in filtered_tools: + executed_tool = filtered_tools[act.name] + next_state = get_next_state(executed_tool, request.state or "undefined") r = AgentRequest( question=request.question, - plan=request.plan, - state=request.state, + state=next_state, + group=getattr(request, 'group', []), history=[ AgentStep( thought=h.thought,