mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-07-21 19:21:03 +02:00
Agent call to mcp-tool is working with a hard-coded service.
- Added ToolClientSpec and ToolClient to implement a tool call. - Updated agent-manager-react to invoke an MCP tool with a tool defined with 'mcp-tool' type. Not generic, need to work out how to call the right parameters.
This commit is contained in:
parent
e56186054a
commit
3978d35545
5 changed files with 85 additions and 5 deletions
|
|
@ -29,4 +29,5 @@ from . document_embeddings_client import DocumentEmbeddingsClientSpec
|
||||||
from . agent_service import AgentService
|
from . agent_service import AgentService
|
||||||
from . graph_rag_client import GraphRagClientSpec
|
from . graph_rag_client import GraphRagClientSpec
|
||||||
from . tool_service import ToolService
|
from . tool_service import ToolService
|
||||||
|
from . tool_client import ToolClientSpec
|
||||||
|
|
||||||
|
|
|
||||||
40
trustgraph-base/trustgraph/base/tool_client.py
Normal file
40
trustgraph-base/trustgraph/base/tool_client.py
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from . request_response_spec import RequestResponse, RequestResponseSpec
|
||||||
|
from .. schema import ToolRequest, ToolResponse
|
||||||
|
|
||||||
|
class ToolClient(RequestResponse):
|
||||||
|
|
||||||
|
async def invoke(self, name, parameters={}, timeout=600):
|
||||||
|
|
||||||
|
if parameters is None:
|
||||||
|
parameters = {}
|
||||||
|
|
||||||
|
resp = await self.request(
|
||||||
|
ToolRequest(
|
||||||
|
name = name,
|
||||||
|
parameters = json.dumps(parameters),
|
||||||
|
),
|
||||||
|
timeout=timeout
|
||||||
|
)
|
||||||
|
|
||||||
|
if resp.error:
|
||||||
|
raise RuntimeError(resp.error.message)
|
||||||
|
|
||||||
|
if resp.text: return resp.text
|
||||||
|
|
||||||
|
return json.loads(resp.object)
|
||||||
|
|
||||||
|
class ToolClientSpec(RequestResponseSpec):
|
||||||
|
def __init__(
|
||||||
|
self, request_name, response_name,
|
||||||
|
):
|
||||||
|
super(ToolClientSpec, self).__init__(
|
||||||
|
request_name = request_name,
|
||||||
|
request_schema = ToolRequest,
|
||||||
|
response_name = response_name,
|
||||||
|
response_schema = ToolResponse,
|
||||||
|
impl = ToolClient,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
@ -14,12 +14,19 @@ class AgentManager:
|
||||||
|
|
||||||
async def reason(self, question, history, context):
|
async def reason(self, question, history, context):
|
||||||
|
|
||||||
|
print(f"calling reason: {question}", flush=True)
|
||||||
|
|
||||||
tools = self.tools
|
tools = self.tools
|
||||||
|
|
||||||
|
print(f"in reason", flush=True)
|
||||||
|
print(tools, flush=True)
|
||||||
|
|
||||||
tool_names = ",".join([
|
tool_names = ",".join([
|
||||||
t for t in self.tools.keys()
|
t for t in self.tools.keys()
|
||||||
])
|
])
|
||||||
|
|
||||||
|
print("Tool names:", tool_names, flush=True)
|
||||||
|
|
||||||
variables = {
|
variables = {
|
||||||
"question": question,
|
"question": question,
|
||||||
"tools": [
|
"tools": [
|
||||||
|
|
@ -83,6 +90,9 @@ class AgentManager:
|
||||||
|
|
||||||
async def react(self, question, history, think, observe, context):
|
async def react(self, question, history, think, observe, context):
|
||||||
|
|
||||||
|
logger.info(f"question: {question}")
|
||||||
|
print(f"question: {question}", flush=True)
|
||||||
|
|
||||||
act = await self.reason(
|
act = await self.reason(
|
||||||
question = question,
|
question = question,
|
||||||
history = history,
|
history = history,
|
||||||
|
|
@ -104,13 +114,12 @@ class AgentManager:
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f"No action for {act.name}!")
|
raise RuntimeError(f"No action for {act.name}!")
|
||||||
|
|
||||||
print("TOOL>>>", act)
|
print("TOOL>>>", act, flush=True)
|
||||||
|
|
||||||
resp = await action.implementation(context).invoke(
|
resp = await action.implementation(context).invoke(
|
||||||
**act.arguments
|
**act.arguments
|
||||||
)
|
)
|
||||||
|
|
||||||
print("RSETUL", resp)
|
|
||||||
|
|
||||||
resp = resp.strip()
|
resp = resp.strip()
|
||||||
|
|
||||||
logger.info(f"resp: {resp}")
|
logger.info(f"resp: {resp}")
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from ... base import AgentService, TextCompletionClientSpec, PromptClientSpec
|
from ... base import AgentService, TextCompletionClientSpec, PromptClientSpec
|
||||||
from ... base import GraphRagClientSpec
|
from ... base import GraphRagClientSpec, ToolClientSpec
|
||||||
|
|
||||||
from ... schema import AgentRequest, AgentResponse, AgentStep, Error
|
from ... schema import AgentRequest, AgentResponse, AgentStep, Error
|
||||||
|
|
||||||
from . tools import KnowledgeQueryImpl, TextCompletionImpl
|
from . tools import KnowledgeQueryImpl, TextCompletionImpl, McpToolImpl
|
||||||
from . agent_manager import AgentManager
|
from . agent_manager import AgentManager
|
||||||
|
|
||||||
from . types import Final, Action, Tool, Argument
|
from . types import Final, Action, Tool, Argument
|
||||||
|
|
@ -67,6 +67,13 @@ class Processor(AgentService):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.register_specification(
|
||||||
|
ToolClientSpec(
|
||||||
|
request_name = "mcp-tool-request",
|
||||||
|
response_name = "mcp-tool-response",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
async def on_tools_config(self, config, version):
|
async def on_tools_config(self, config, version):
|
||||||
|
|
||||||
print("Loading configuration version", version)
|
print("Loading configuration version", version)
|
||||||
|
|
@ -106,6 +113,8 @@ class Processor(AgentService):
|
||||||
impl = KnowledgeQueryImpl
|
impl = KnowledgeQueryImpl
|
||||||
elif impl_id == "text-completion":
|
elif impl_id == "text-completion":
|
||||||
impl = TextCompletionImpl
|
impl = TextCompletionImpl
|
||||||
|
elif impl_id == "mcp-tool":
|
||||||
|
impl = McpToolImpl
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"Tool-kind {impl_id} not known"
|
f"Tool-kind {impl_id} not known"
|
||||||
|
|
@ -181,6 +190,8 @@ class Processor(AgentService):
|
||||||
|
|
||||||
await respond(r)
|
await respond(r)
|
||||||
|
|
||||||
|
print("Call React", flush=True)
|
||||||
|
|
||||||
act = await self.agent.react(
|
act = await self.agent.react(
|
||||||
question = request.question,
|
question = request.question,
|
||||||
history = history,
|
history = history,
|
||||||
|
|
|
||||||
|
|
@ -23,3 +23,22 @@ class TextCompletionImpl:
|
||||||
arguments.get("question")
|
arguments.get("question")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# This tool implementation knows how to do MCP tool invocation. This uses
|
||||||
|
# the mcp-tool service.
|
||||||
|
class McpToolImpl:
|
||||||
|
def __init__(self, context):
|
||||||
|
self.context = context
|
||||||
|
async def invoke(self, **arguments):
|
||||||
|
client = self.context("mcp-tool-request")
|
||||||
|
print("MCP tool invocation...", flush=True)
|
||||||
|
output = await client.invoke(
|
||||||
|
name = "time",
|
||||||
|
parameters = {},
|
||||||
|
)
|
||||||
|
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
print(type(output))
|
||||||
|
|
||||||
|
return output["result"]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue