Skip to main content
Glama

Jentic

Official
by jentic
agent_tools.py4.86 kB
"""Agent tool manager for integrating Jentic workflows with agent frameworks.""" import logging from typing import Any from .config import JenticConfig from .tool_execution import TaskExecutor from .tool_specs import LLMToolSpecManager logger = logging.getLogger(__name__) class AgentToolManager: """Manager for converting Jentic workflows into agent-compatible tools.""" def __init__( self, config_path: str = "./jentic.json", format: str = "anthropic", config_overrides: dict[str, Any] | None = None, api_hub_client=None, ) -> None: """Initialize the agent tool manager. Args: config_path: Path to the Jentic project format: Tool format ("anthropic" or "openai") config_overrides: Optional configuration overrides api_hub_client: Optional API hub client for TaskExecutor """ self.project = JenticConfig(config_path) self.format = format.lower() self.config_overrides = config_overrides or {} # Create combined configuration self.config = self._create_config() # Setup tool specification manager self.tool_spec_manager = LLMToolSpecManager() self.tool_spec_manager.load_from_jentic_config(self.project) # Setup tool executor from jentic.lib.agent_runtime.api_hub import JenticAPIClient self.tool_executor = TaskExecutor(api_hub_client or JenticAPIClient()) def _create_config(self) -> dict[str, Any]: """Create a merged configuration from the project and overrides. Returns: Merged configuration """ # Start with project config config = dict(self.project.config) # Apply overrides for key, value in self.config_overrides.items(): if isinstance(value, dict) and key in config and isinstance(config[key], dict): # Merge dictionaries config[key].update(value) else: # Replace value config[key] = value return config def generate_tool_definitions(self) -> list[dict[str, Any]]: """Get tool definitions for the specified format. Returns: List of tool definitions """ # Get tool specifications specs = self.tool_spec_manager.get_tool_specs(self.format) # Return just the tools list return specs["tools"] async def execute_tool(self, tool_name: str, inputs: dict[str, Any] = None) -> dict[str, Any]: """Execute a tool. Args: tool_name: Name of the tool (workflow or operation) to execute inputs: inputs for the tool Returns: Tool execution result """ if inputs is None: inputs = {} try: # Determine the type of tool tool_type = self.tool_spec_manager.get_tool_type(tool_name) if tool_type == "workflow": logger.info(f"Executing tool '{tool_name}' as a workflow.") workflow_uuid = self.tool_spec_manager.get_workflow_uuid(tool_name) if not workflow_uuid: # This case should ideally not happen if get_tool_type returned 'workflow' # but adding a fallback check for robustness. logger.error( f"Could not find UUID for workflow tool name {tool_name} despite type being 'workflow'." ) return { "success": False, "error": f"Could not find UUID for workflow tool name {tool_name}", } result = await self.tool_executor.execute_workflow(workflow_uuid, inputs) elif tool_type == "operation": logger.info(f"Executing tool '{tool_name}' as an operation.") operation_uuid = self.tool_spec_manager.get_operation_uuid(tool_name) if not operation_uuid: return { "success": False, "error": f"Could not find UUID for operation tool name {tool_name}", } result = await self.tool_executor.execute_operation(operation_uuid, inputs) else: # tool_type == "unknown" logger.error(f"Cannot execute unknown tool type for tool name: {tool_name}") return {"success": False, "error": f"Tool '{tool_name}' not found or type unknown."} return result # Assuming both execute methods return compatible dicts except Exception as e: error_msg = f"Error executing tool {tool_name}: {str(e)}" logger.error(error_msg) return {"success": False, "error": error_msg}

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jentic/jentic-tools'

If you have feedback or need assistance with the MCP directory API, please join our Discord server