### Setup Examples Dataset Fixture (Python) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/context.md Configures a pytest fixture 'examples_dataset' that prepares a dataset with examples for testing. It first deletes any existing examples within the dataset and then creates new ones using provided 'inputs' and 'outputs'. This ensures a clean and consistent dataset for evaluation runs. Dependencies include the 'dataset' fixture and a 'client' object. ```python import pytest # Assume 'client', 'inputs', and 'outputs' are defined elsewhere @pytest.fixture def examples_dataset(dataset): for ex in client.list_examples(dataset_id=dataset.id): client.delete_example(ex.id) client.create_examples(inputs=inputs, outputs=outputs, dataset_id=dataset.id) return dataset ``` -------------------------------- ### Install Project Dependencies (Bash) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/com.etendoerp.copilot.chat/README.md Installs all necessary project dependencies using yarn. This command should be run in the project's root directory before starting the application. ```bash yarn install ``` -------------------------------- ### Complete Client Flow Example Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md This Python snippet outlines the beginning of a client-side flow using the `httpx` library. It is intended to demonstrate how a client might interact with the MCP server, starting with establishing a connection. ```python import httpx ``` -------------------------------- ### Set Up Python Virtual Environment with uv Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md Instructions for setting up a Python 3.12 virtual environment using pyenv and uv, installing dependencies, and activating the environment. Covers common issues with PyTorch installation. ```bash pyenv install 3.12 pyenv local 3.12 uv venv source .venv/bin/activate # On macOS/Linux # or .venv\Scripts\activate # On Windows uv pip install -r requirements.txt ``` ```bash uv sync ``` ```bash source .venv/bin/activate uv pip install torch ``` ```bash python -c "import torch; print(torch.__version__)" ``` ```bash uv add uv add --dev ``` ```bash uv pip freeze > requirements.txt uv export --format requirements-txt > requirements.txt ``` -------------------------------- ### Install Dependencies Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/README.md Installs all Python package dependencies listed in the 'requirements.txt' file. Ensure this file is present in the current directory. ```bash pip install -r requirements.txt ``` -------------------------------- ### Manual Server Start Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md Instructions and code for manually starting the MCP server. ```APIDOC ## Manual Server Start ### Description This section details how to manually start the MCP (Model Context Protocol) server using provided Python utilities. It ensures the server is running before clients attempt to connect. ### Method N/A (Python script execution) ### Endpoint N/A ### Code Example ```python from copilot.core.mcp.simplified_dynamic_utils import start_simplified_dynamic_mcp_with_cleanup # Start with environment configuration success = start_simplified_dynamic_mcp_with_cleanup() if success: print("MCP server started successfully") else: print("Failed to start MCP server") ``` ``` -------------------------------- ### Example Response from Dynamic hello_world Tool Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md This is an example of the JSON response format for the `hello_world` tool within a dynamically created MCP instance. The response includes a personalized greeting indicating the connected instance and its uptime. ```json { "tool": "hello_world", "arguments": {} } "Hello! You are connected to company1 MCP! Created 45 seconds ago" ``` -------------------------------- ### Invoke Built-in MCP Tools Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md These cURL examples demonstrate how to invoke several built-in tools provided by the MCP server. They cover basic health checks (`ping`), retrieving server information (`server_info`), initializing a session (`init_session`), and getting agent-specific greetings (`agent_greeting`). ```bash # Ping tool curl -X POST http://localhost:5007/tools/ping # Response: "pong" # Server info tool curl -X POST http://localhost:5007/tools/server_info # Response: {"name": "etendo-copilot-mcp", "version": "0.1.0", ...} # Init session tool curl -X POST http://localhost:5007/tools/init_session \ -H "Content-Type: application/json" \ -d '{"agent_id": "sales-assistant"}' # Response: "Sesión inicializada para el agente: sales-assistant" # Agent greeting tool curl -X POST http://localhost:5007/tools/agent_greeting # Response: "¡El agente sales-assistant te envía saludos!" ``` -------------------------------- ### Setup LangGraph Agent and Invoke Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/context.md This Python code sets up a LangGraph agent with a defined graph structure, including multiple assistants with specific roles and prompts. It then validates the graph's output against predefined examples. The `setup_graph` function initializes the agent, and the `target` function invokes it with a given question, returning the response. ```python import pytest from copilot.core.agent.langgraph_agent import setup_graph from copilot.core.schemas import GraphQuestionSchema from langsmith import Client, wrappers from openai import OpenAI from pydantic import BaseModel, Field grafo = { "conversation_id": "ASAAASDADASDASD", "assistants": [ { "name": "Node2Emojis", "type": "multimodel", "description": "Add emojis to a text and traduce it to english. The " 'recommended input is "Process the following text: "', "assistant_id": "AC6C184726B149C28064FE4E8AC86D0B", "temperature": 1, "tools": [], "provider": "openai", "model": "gpt-4o", "kb_vectordb_id": "KB_AC6C184726B149C28064FE4E8AC86D0B", "system_prompt": "Recibes texto en cualquier idioma y devuelves exactamente" " la traduccion al ingles, con muchos emojis. No puedes" " realizar otra tarea.\n", }, { "name": "NODE1Text", "type": "langchain", "description": "Spanish stories generator", "assistant_id": "3C4D54A938E64DBCBCF1757EB71B54DC", "temperature": 1, "tools": [], "provider": "openai", "model": "gpt-4o", "kb_vectordb_id": "KB_3C4D54A938E64DBCBCF1757EB71B54DC", "system_prompt": "Eres un asistente que solo genera cuentos de 3 actos de" " menos de 10 palabras. Solo en Español y sin emojis.\n", }, ], "system_prompt": "Resuelves peticiones dividiendo la tarea en subtareas entre los" " miembros de tu equipo.\n\nCuando decidas que el flujo termina," " debes dar una respuesta final con lo que se hizo y lo que fallo." " No omitas informacion con esa respuesta final.", "temperature": 0.1, "graph": {"stages": [{"name": "stage1", "assistants": ["Node2Emojis", "NODE1Text"]}]}, "question": "What is the capital of France?", "local_file_ids": [], "extra_info": {"auth": {"ETENDO_TOKEN": "eyJhbGciOiJIUzI1NiJ9"}}, "history": [], } client = Client() openai_client = wrappers.wrap_openai(OpenAI()) # Create inputs and reference outputs examples = [{"input": "perros y gatos", "output": " Habia una vez un gato y un perro y fueron felices."}] # field impuyt in examples inputs = [{"question": elem["input"]} for elem in examples] outputs = [{"output": elem["output"]} for elem in examples] SYSTEM_PROMPT1 = """ Resuelves peticiones dividiendo la tarea en subtareas entre los miembros de tu equipo. Cuando decidas que el flujo termina, debes dar una respuesta final con lo que se hizo y lo que fallo. No omitas informacion con esa respuesta final. """ # Define the application logic you want to evaluate inside a target function def target(inputs: dict) -> dict: # set question to grafo grafo["question"] = inputs["question"] # convert graph dict to GraphQuestionSchema question = GraphQuestionSchema.model_validate(grafo) graph, conv = setup_graph(question=question, memory=None) response = graph.invoke(inputs["question"], thread_id=question.conversation_id) return response # Define instructions for the LLM judge evaluator instructions = """Evaluate the Assistant's response based on the Reference Instructions. - **False**: The response does not strictly follow the Reference Instructions. This includes: - Introducing new information or inventing data not present in the Reference Instructions. - Omitting required details explicitly stated in the Reference Instructions. - Misinterpreting or altering the intent of the Reference Instructions. - **True**: The response strictly adheres to the Reference Instructions by: - Including all requested details as specified. - Avoiding any additions, omissions, or modifications to the requested details. - Maintaining the intended purpose of the Reference Instructions. Key Criteria for Evaluation: - The response should follow the Reference Instructions exactly without adding or omitting information. - Additional creativity or elaboration beyond the Reference Instructions is not allowed. - Don't evaluate extra new lines or spaces that do not affect the meaning of the response. - In case of numbers is valid to use or ommit the $ symbol and the decimal part of the number if is 0 (e.g., $5.00 or $5). - If the user is not explicit with names or description, the assistant can fix grammar or spelling errors with changes that do not alter the meaning of the response. Provide your judgment as **True** or **False**, followed by a brief explanation of why the response is valid or invalid. """ # Define context for the LLM judge evaluator context = """Ground Truth instruccions: {instructions}, next: {next}; -- AI Generated: next: {next_generated} instructions: {generated_instructions} """ ``` -------------------------------- ### Python: Start MCP Server Manually Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md Provides a Python script to manually start the MCP server using the `start_simplified_dynamic_mcp_with_cleanup` utility function. It includes a check to confirm successful startup. ```python from copilot.core.mcp.simplified_dynamic_utils import start_simplified_dynamic_mcp_with_cleanup # Start with environment configuration success = start_simplified_dynamic_mcp_with_cleanup() if success: print("MCP server started successfully") ``` -------------------------------- ### Execute Copilot Agent to Save Examples Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/README.md Executes the Copilot agent to save new examples. This command requires the same parameters as the evaluation command, plus a '--save' parameter specifying the run ID of the example to be saved. The dataset and agent ID are also specified. ```bash PYTHONPATH=$(pwd) python3 evaluation/execute.py --user=admin --password=admin --etendohost=http://localhost:8080/etendo --envfile=../../gradle.properties --dataset=../../modules/com.etendoerp.copilot.agents/dataset --agent_id=49D1735ACAFE48E99A4A5CCFBBE6946C --save=20a3a6a8-6b08-4f28-9d71-90fea1ca44d1 ``` -------------------------------- ### Example Input JSON for Product Creation Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/README.md This JSON snippet demonstrates the initial structure of the dataset.json file, showing a single user message for creating a product with specific details. It outlines the expected AI behavior, excluding product price creation in this step. ```json [ { "run_id": "390a7874-7dfe-4694-a5be-7855da7b97a8", "messages": [ { "role": "user", "content": "Create product with this data \"Category ID\" : \"52DBC3E9A82C47F2B6298CBC3E12DA67\"' \"Price\":\"1000\" price list version: FDE536FE9D8C4B068C32CD6C3650B6B8 ' ' seachkey: 228 BARRA HUECA GRANDE PANTUPAS name: 228 BARRA HUECA GRANDE PANTUPAS" } ], "considerations": "In this call, te AI must create a product with the provided data. The creation of the product price is a subsequent step that will be handled in a different call. The AI should not include the product price creation in this call.", "expected_response": { "role": "assistant", "content": "", "tool_calls": [ { "id": "call_FI8tskwHyGiFWaYSKerYxWaA", "function": { "name": "POST_sws_com_etendoerp_etendorx_datasource_Product", "arguments": "{\"body\": {\"searchKey\": \"228 BARRA HUECA GRANDE PANTUPAS\", \"name\": \"228 BARRA HUECA GRANDE PANTUPAS\", \"productCategory\": \"52DBC3E9A82C47F2B6298CBC3E12DA67\", \"description\": \"228 BARRA HUECA GRANDE PANTUPAS\"}}" }, "type": "function" } ] }, "creation_date": "2025-05-14-10:19:10" } ] ``` -------------------------------- ### Python: Registering Basic Tools Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md Shows how to register basic tools for the MCP server. This example defines a simple tool `my_basic_tool` that takes a string parameter and returns a formatted string. ```python # In tools/basic_tools.py def register_basic_tools(app): @app.tool() def my_basic_tool(parameter: str) -> str: """Description of my basic tool.""" return f"Result: {parameter}" ``` -------------------------------- ### Start Etendo ERP Copilot Application (Bash) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/com.etendoerp.copilot.chat/README.md Starts the Etendo ERP Copilot application in development mode using yarn. This command makes the application accessible via a local web server. ```bash yarn dev ``` -------------------------------- ### Python: Custom Client Interaction with MCP Server Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md A Python example for a custom client to interact with the MCP server. It shows initializing a session and then calling the `agent_greeting` tool. ```python import httpx # Connect to MCP server async with httpx.AsyncClient() as client: # 1. Initialize session await client.post( "http://localhost:5007/tools/init_session", json={"agent_id": "my-assistant"} ) # 2. Use tools response = await client.post( "http://localhost:5007/tools/agent_greeting", json={} ) print(response.json()) ``` -------------------------------- ### Starting the MCP Server (Python) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/copilot/core/mcp/README.md A Python code snippet showing how the MCP server is automatically started when the main application runs. It typically involves calling a function like `start_simplified_dynamic_mcp_with_cleanup`. ```python # In run.py - automatically called start_simplified_dynamic_mcp_with_cleanup() ``` -------------------------------- ### Configuration Example: Environment Variables (Bash) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/copilot/core/mcp/README.md Shows how to configure the MCP server port and enable debug mode using environment variables. These settings affect the server's operation and accessibility. ```bash # Custom port configuration export COPILOT_PORT_MCP=8080 # Enable debug mode export COPILOT_PORT_DEBUG=5100 ``` -------------------------------- ### Quick Start: Dynamic MCP Server Instances (Bash) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/copilot/core/mcp/README.md Illustrates how to create or connect to isolated dynamic MCP instances by specifying an identifier in the URL. Each identifier maps to a unique instance. ```bash # Creates/connects to 'company1' instance curl http://localhost:5007/company1/mcp # Creates/connects to 'project-alpha' instance curl http://localhost:5007/project-alpha/mcp # Creates/connects to 'tenant-123' instance curl http://localhost:5007/tenant-123/mcp ``` -------------------------------- ### Deploy Etendo Copilot Docker Image Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md Commands to build and push the Etendo Copilot Docker image. Assumes Docker is installed and you are in the project root directory. ```bash docker build -t etendo/etendo_copilot_slim . docker push etendo/etendo_copilot_slim ``` -------------------------------- ### Python: Registering Session Tools Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md Illustrates how to register session-specific tools for the MCP server. This example defines `my_session_tool` which can access the current session's `agent_id`. ```python # In tools/session_tools.py def register_session_tools(app): @app.tool() def my_session_tool(parameter: str) -> str: """Description of my session tool.""" # Access current session agent_id agent_id = current_agent_id.get() return f"Result from {agent_id}: {parameter}" ``` -------------------------------- ### Quick Start: Static MCP Server (Bash) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/copilot/core/mcp/README.md Demonstrates how to send a request to the static MCP server using curl. The static server operates on a single default port. ```bash # Default port: 5007 curl http://localhost:5007/mcp ``` -------------------------------- ### Connecting to MCP Server via HTTP Streaming (Python) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/docs/MCP_SETUP.md Provides a Python example using `httpx` and `asyncio` to connect to the MCP server via HTTP streaming. It demonstrates how to asynchronously stream responses from the server. ```python import asyncio import httpx async def connect_to_mcp(): async with httpx.AsyncClient() as client: async with client.stream('GET', 'http://localhost:5007') as response: async for chunk in response.aiter_text(): print("MCP Response:", chunk) asyncio.run(connect_to_mcp()) ``` -------------------------------- ### Run Etendo Copilot Locally and with Docker Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md Guides for running Etendo Copilot locally using a Python script or via Docker containers, including Docker Compose. Emphasizes the importance of the `.env` file for configuration. ```bash python run.py ``` ```bash docker run --env-file .env -p 5000:5000 etendo/etendo_copilot_slim ``` ```bash docker-compose -f compose/com.etendoerp.copilot.yml up ``` ```bash docker run --env-file .env -p 5000:5000 -v $(pwd)/copilot:/app/copilot etendo/etendo_copilot_slim ``` -------------------------------- ### Claude Desktop Configuration for MCP Servers (JSON) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/copilot/core/mcp/README.md An example JSON configuration for Claude Desktop, specifying how to connect to an Etendo Copilot MCP server. It defines the command and arguments to establish the connection. ```json { "mcpServers": { "etendo-copilot": { "command": "curl", "args": ["-X", "GET", "http://localhost:5007/my-company/mcp"] } } } ``` -------------------------------- ### Get Current Agent Info (API) Source: https://context7.com/etendosoftware/com.etendoerp.copilot/llms.txt Retrieves detailed information about the current session agent, including its ID, session start time, and associated MCP instance. ```bash curl -X POST "http://localhost:5007/tools/get_agent_info" \ -H "Content-Type: application/json" \ -d '{}' ``` -------------------------------- ### Python Convert Conversations to Evaluation Examples Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/context.md Converts a list of conversation objects into a list of examples suitable for evaluation. Each example includes inputs (model, messages, tools, considerations) and expected outputs. This function is useful for preparing data for LLM evaluation frameworks. ```python def convert_conversations_to_examples(conversations, model, tools): """ Converts a list of conversations into a list of examples for evaluation. This function processes each conversation, extracting the messages and expected response, and formats them into a structure suitable for evaluation. Args: conversations (list): A list of Conversation objects, each containing messages and an expected response. model (str): The name of the model to be used in the evaluation. Returns: list: A list of examples, where each example is a dictionary containing: - 'inputs': A dictionary with the model name and a list of messages. - 'outputs': A dictionary with the expected response. """ examples = [] for conversation in conversations: example = { "inputs": { "model": model, "messages": conversation.messages, "tools": tools, "considerations": conversation.considerations, }, "outputs": { "answer": conversation.expected_response, }, } examples.append(example) return examples ``` -------------------------------- ### Python: Connect and Interact with MCP Server Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md Demonstrates how to establish a connection to the MCP server, initialize a session with an agent ID, and then use available tools like agent greeting and retrieving agent information. This snippet uses the httpx library for asynchronous HTTP requests. ```python async with httpx.AsyncClient() as client: # Initialize session with agent_id init_response = await client.post( "http://localhost:5007/tools/init_session", json={"agent_id": "my-custom-agent"} ) print(init_response.json()) # Use tools with session agent greeting_response = await client.post( "http://localhost:5007/tools/agent_greeting", json={} ) print(greeting_response.json()) # Check current agent info_response = await client.post( "http://localhost:5007/tools/get_agent_info", json={} ) print(info_response.json()) ``` -------------------------------- ### hello_world Tool (Dynamic Instances) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/copilot/core/mcp/README.md A custom tool available in dynamic MCP instances that provides a greeting including information about the specific instance. ```APIDOC ## hello_world Tool (Dynamic Instances) ### Description A custom tool available in dynamic MCP instances that provides a personalized greeting, including information about the specific instance and its creation time. ### Method POST ### Endpoint /mcp (or /[IDENTIFIER]/mcp for dynamic instances) ### Parameters #### Path Parameters None for static server, applicable for dynamic instances. #### Query Parameters None #### Request Body - **tool** (string) - Required - Must be 'hello_world'. - **arguments** (object) - Required - Empty for this tool. ### Request Example ```json { "tool": "hello_world", "arguments": {} } ``` ### Response #### Success Response (200) - A string containing a personalized greeting. #### Response Example ``` "Hello! You are connected to company1 MCP! Created 45 seconds ago" ``` ``` -------------------------------- ### Execute Copilot Agent for Evaluation Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/README.md Runs the Copilot agent to execute predefined examples for evaluation. It requires specifying user credentials, Etendo host, dataset path, agent ID, and the number of repetitions for each example. The PYTHONPATH is set to the current directory to ensure correct module resolution. ```bash PYTHONPATH=$(pwd) python3 evaluation/execute.py --user=admin --password=admin --etendohost=http://localhost:8080/etendo --envfile=../../gradle.properties --dataset=../../modules/com.etendoerp.copilot.agents/dataset --agent_id=49D1735ACAFE48E99A4A5CCFBBE6946C --k=1 ``` -------------------------------- ### GET /health Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md Checks the health status of the MCP server. ```APIDOC ## GET /health ### Description Endpoint to check if the MCP server is running and responsive. ### Method GET ### Endpoint `/health` ### Parameters (No parameters required) ### Request Example ```bash curl http://localhost:5007/health ``` ### Response #### Success Response (200) - **status** (string) - Indicates the server's health status (e.g., "OK"). #### Response Example ```json { "status": "OK" } ``` ``` -------------------------------- ### Python: Manage Evaluation Datasets Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/context.md Loads conversations, converts them into examples, and manages datasets for evaluation. It checks if a dataset with a specific MD5 hash exists; if not, it creates a new dataset and populates it with examples. Errors during dataset reading are caught, and the dataset remains None if not found. ```python conversations = load_conversations(agent_id, base_path=base_path, prompt=prompt) examples = convert_conversations_to_examples( conversations, model, tools=available_tools_openai ) ls_client_eval = Client() # Renamed to avoid conflict if another Client is used examples_md5 = calc_md5(examples) dat_name = f"Dataset for evaluation {agent_id} MD5:{examples_md5}" dataset = None try: dataset = ls_client_eval.read_dataset(dataset_name=dat_name) except Exception: # Catches if dataset not found, which is expected pass # dataset remains None if dataset is None or dataset.id is None: print(f"Dataset '{dat_name}' not found, creating new one.") dataset = ls_client_eval.create_dataset(dataset_name=dat_name) ls_client_eval.create_examples( dataset_id=dataset.id, examples=examples, ) else: print(f"Using existing dataset: '{dat_name}' with ID: {dataset.id}") ``` -------------------------------- ### Dynamic Instance hello_world Tool Usage (JSON) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/copilot/core/mcp/README.md Demonstrates the JSON payload for invoking the `hello_world` tool on a dynamic MCP instance. This tool provides instance-specific information. ```json { "tool": "hello_world", "arguments": {} } ``` -------------------------------- ### Get Etendo Agent Configuration via API Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/context.md Retrieves an agent's configuration from the Etendo system using its unique ID. It handles authentication by either using a provided token or logging in with user credentials. The function makes a GET request to the Etendo API and prints the response. ```python import json import os import sys import time import html import pandas as pd from copilot.core.agent import MultimodelAgent from copilot.core.agent.agent import get_kb_tool from copilot.core.etendo_utils import call_etendo, login_etendo from copilot.core.toolgen.ApiTool import generate_tools_from_openapi from langchain_core.utils.function_calling import convert_to_openai_function from langsmith import Client from openai.types.chat import ( ChatCompletionAssistantMessageParam, ChatCompletionMessageToolCallParam, ChatCompletionToolMessageParam, ChatCompletionUserMessageParam, ) from openai.types.chat.chat_completion_message_tool_call_param import Function from schemas import Conversation, Message def get_agent_config( agent_id, host, token=None, user=None, password=None, ): """ Retrieves the configuration of an agent from the Etendo system. This function constructs an API endpoint using the provided `agent_id` and sends a GET request to retrieve the agent's configuration. If no `token` is provided, it logs in to the Etendo system using the provided `user` and `password` to obtain one. Args: agent_id (str): The unique identifier of the agent whose configuration is being retrieved. token (str, optional): The authentication token for accessing the Etendo API. Defaults to None. user (str, optional): The username for authentication if `token` is not provided. Defaults to None. password (str, optional): The password for authentication if `token` is not provided. Defaults to None. Returns: dict: The response from the Etendo API containing the agent's configuration. Side Effects: - Prints the response from the Etendo API to the console. Raises: Exception: If the API call fails or authentication is unsuccessful. """ etendo_host = host endpoint = f"/sws/copilot/structure?app_id={agent_id}" if token is None: token = login_etendo(etendo_host, user, password) response = call_etendo( method="GET", url=etendo_host, endpoint=endpoint, body_params={}, access_token=token, ) print(response) return response ``` -------------------------------- ### GET /instances Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/copilot/core/mcp/README.md Retrieves a list of all active instances managed by the Etendo ERP Copilot. ```APIDOC ## GET /instances ### Description Retrieves a list of all active instances managed by the Etendo ERP Copilot. ### Method GET ### Endpoint /instances ### Parameters #### Query Parameters None ### Request Example ```bash GET http://localhost:5007/instances ``` ### Response #### Success Response (200) - **active_instances** (integer) - The total number of currently active instances. - **instances** (object) - An object containing details for each instance. - **[instance_identifier]** (object) - Details of a specific instance. - **identifier** (string) - Unique identifier for the instance. - **created_at** (string) - Timestamp when the instance was created (ISO 8601 format). - **port** (integer) - The port number the instance is running on. - **url** (string) - The URL to access the instance. - **status** (string) - The current status of the instance (e.g., "running"). #### Response Example ```json { "active_instances": 3, "instances": { "company1": { "identifier": "company1", "created_at": "2025-01-18T10:30:00Z", "port": 8001, "url": "http://localhost:8001", "status": "running" }, "project-alpha": { "identifier": "project-alpha", "created_at": "2025-01-18T11:15:00Z", "port": 8002, "url": "http://localhost:8002", "status": "running" } } } ``` ``` -------------------------------- ### Docker Command to Run Copilot with Volume Mounts Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md This Docker command starts the EtendoERP Copilot container, mounting the local project directory into the container at `/app`. This allows Copilot to load custom tools defined within the project's source code. The `--env-file` and `-p` flags are for environment variables and port mapping, respectively. ```bash docker run --env-file .env -p 5000:5000 -v $(pwd):/app etendo/etendo_copilot_slim ``` -------------------------------- ### Custom Tool Development Source: https://context7.com/etendosoftware/com.etendoerp.copilot/llms.txt Guides on creating, registering, and managing dependencies for custom tools to extend Copilot's capabilities. ```APIDOC ## Custom Tool Development ### Creating a Custom Tool Class To create a custom tool, extend the `ToolWrapper` class and define its properties, including its name, description, and argument schema. **Example:** ```python from typing import Type from copilot.core.tool_wrapper import ToolWrapper from copilot.core.tool_input import ToolInput, ToolField # Define input schema with Pydantic class WeatherInput(ToolInput): location: str = ToolField(description="City name or ZIP code") units: str = ToolField( description="Temperature units: 'celsius' or 'fahrenheit'", default="celsius" ) # Create custom tool class WeatherTool(ToolWrapper): name: str = "get_weather" description: str = "Retrieves current weather information for a location" args_schema: Type[ToolInput] = WeatherInput return_direct: bool = False def run(self, location: str, units: str = "celsius", *args, **kwargs) -> dict: # Implement your tool logic here import requests api_key = "your_api_key" url = f"https://api.weather.com/v1/current?location={location}&units={units}" try: response = requests.get(url, headers={"Authorization": f"Bearer {api_key}"}) response.raise_for_status() data = response.json() return { "location": location, "temperature": data["temp"], "conditions": data["conditions"], "humidity": data["humidity"], "units": units } except Exception as e: return {"error": f"Failed to fetch weather data: {str(e)}"} # Save to: tools/WeatherTool.py ``` ### Registering Custom Tools Enable your custom tools by configuring the `tools` JSON file. Set the corresponding key in `third_party_tools` to `true`. **Example `tools.json`:** ```json { "native_tools": { "kb_tool": true }, "third_party_tools": { "HelloWorldTool": false, "WeatherTool": true, "CustomDatabaseTool": true } } ``` ### Custom Tool with Dependencies Define dependencies for your custom tools in a `tools_deps.toml` file. These dependencies will be automatically installed when the tool is loaded. **Example `tools_deps.toml`:** ```toml # tools_deps.toml [WeatherTool] dependencies = [ "requests>=2.31.0", "python-dateutil>=2.8.2" ] [CustomDatabaseTool] dependencies = [ "psycopg2-binary>=2.9.6", "sqlalchemy>=2.0.0" ] ``` ``` -------------------------------- ### Get Agent Greeting (API) Source: https://context7.com/etendosoftware/com.etendoerp.copilot/llms.txt Fetches a personalized greeting from the current session agent. This tool can be used to provide user-friendly interactions. ```bash curl -X POST "http://localhost:5007/tools/agent_greeting" \ -H "Content-Type: application/json" \ -d '{}' ``` -------------------------------- ### Create and Activate Virtual Environment Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/README.md This command creates a Python virtual environment named '.venv_execution' if it does not already exist, and then activates it. This is a standard practice for isolating project dependencies. ```bash ENV_NAME=".venv_execution"; [ ! -d "$ENV_NAME" ] && python3 -m venv "$ENV_NAME"; source "$ENV_NAME/bin/activate" ``` -------------------------------- ### GET /history - Retrieve Chat History Source: https://context7.com/etendosoftware/com.etendoerp.copilot/llms.txt Returns the complete chat history, including all past conversations, questions, and their corresponding answers. ```APIDOC ## GET /history - Retrieve Chat History ### Description Returns the complete chat history with all conversations, questions, and answers. ### Method GET ### Endpoint /history ### Parameters None ### Request Example ```bash curl -X GET "http://localhost:5000/history" ``` ### Response #### Success Response (200) - **chat_history** (array) - An array of chat history objects. - **timestamp** (string) - The time the message was sent (ISO 8601 format). - **question** (string) - The user's question. - **answer** (string) - The AI's answer. - **conversation_id** (string) - Identifier for the conversation. #### Response Example ```json { "chat_history": [ { "timestamp": "2025-01-08T14:30:00Z", "question": "What is Etendo ERP?", "answer": "Etendo ERP is an enterprise resource planning system...", "conversation_id": "conv_12345" }, { "timestamp": "2025-01-08T14:32:15Z", "question": "How do I create custom tools?", "answer": "To create custom tools in Copilot...", "conversation_id": "conv_12345" } ] } ``` ``` -------------------------------- ### Dynamic MCP Instance Creation (Bash) Source: https://context7.com/etendosoftware/com.etendoerp.copilot/llms.txt Creates or connects to isolated MCP (Multi-tenant Communication Platform) instances based on URL identifiers. This is crucial for multi-tenant deployments, allowing distinct environments for different clients or projects. ```bash # Create/connect to 'company1' MCP instance curl -X GET "http://localhost:5007/company1/mcp" # Create/connect to 'project-alpha' instance curl -X GET "http://localhost:5007/project-alpha/mcp" # Response (instance info): # { # "name": "etendo-copilot-mcp", # "version": "0.1.0", # "identifier": "company1", # "port": 8001, # "created_at": "2025-01-08T14:30:00Z" # } ``` -------------------------------- ### Static MCP Server Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/copilot/core/mcp/README.md Starts a traditional single-instance MCP server that handles all requests. The default port is 5007. ```APIDOC ## Static MCP Server ### Description Starts a traditional single-instance MCP server that handles all requests. ### Method GET ### Endpoint /mcp ### Parameters #### Query Parameters None #### Request Body None ### Request Example ```bash curl http://localhost:5007/mcp ``` ### Response #### Success Response (200) - MCP server response #### Response Example (Varies based on MCP server interaction) ``` -------------------------------- ### POST /tools/init_session Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/README.md Initializes a session with the MCP server using a specified agent ID. ```APIDOC ## POST /tools/init_session ### Description Initializes a new session with the MCP server. This is typically the first step before interacting with other tools or agents. ### Method POST ### Endpoint `/tools/init_session` ### Parameters #### Request Body - **agent_id** (string) - Required - The unique identifier for the agent or session. ### Request Example ```json { "agent_id": "my-custom-agent" } ``` ### Response #### Success Response (200) - **message** (string) - A confirmation message indicating successful session initialization. #### Response Example ```json { "message": "Session initialized successfully" } ``` ``` -------------------------------- ### POST /tools/agent_greeting - Get Agent Greeting Source: https://context7.com/etendosoftware/com.etendoerp.copilot/llms.txt Retrieves a personalized greeting from the current session agent. This endpoint can be used to initiate interaction or provide a friendly response. ```APIDOC ## POST /tools/agent_greeting ### Description Returns a personalized greeting for the current session agent. ### Method POST ### Endpoint /tools/agent_greeting ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None (empty object is expected). ### Request Example ```json {} ``` ### Response #### Success Response (200) - Response body is a string containing the agent's greeting. #### Response Example ``` "¡El agente sales-assistant-001 te envía saludos!" ``` ``` -------------------------------- ### GET /health - MCP Server Health Check Source: https://context7.com/etendosoftware/com.etendoerp.copilot/llms.txt Returns the health status of the MCP server, including the number of active instances, the server port, and its uptime. ```APIDOC ## GET /health - MCP Server Health Check ### Description Returns the health status of the MCP server and active instances. ### Method GET ### Endpoint /health ### Parameters None ### Request Example ```bash curl -X GET "http://localhost:5007/health" ``` ### Response #### Success Response (200) - **status** (string) - The overall health status of the MCP server (e.g., "healthy"). - **active_instances** (integer) - The number of currently active MCP instances. - **server_port** (integer) - The port the MCP server is running on. - **uptime_seconds** (integer) - The uptime of the MCP server in seconds. #### Response Example ```json { "status": "healthy", "active_instances": 3, "server_port": 5007, "uptime_seconds": 3600 } ``` ``` -------------------------------- ### Instantiate Templates with CSV Data (Python) Source: https://github.com/etendosoftware/com.etendoerp.copilot/blob/master/evaluation/context.md This function takes a CSV file path, a list of AI-generated templates, and expected placeholder column names. It reads the CSV data, fills in placeholders in each template with corresponding CSV data, and returns a list of instantiated text strings. Includes error handling for file not found, CSV loading issues, missing columns, and instantiation errors. Limits the output to 50 strings to prevent memory issues. ```python def instantiate_templates_with_csv_data( csv_path: str, ai_generated_templates: List[str], placeholder_column_names: List[str] ) -> List[str]: """Instantiates templates by replacing placeholders with data from a CSV file. Args: csv_path: Path to the CSV file containing data. ai_generated_templates: A list of template strings with placeholders. placeholder_column_names: A list of column names in the CSV that correspond to placeholders. Returns: A list of strings where placeholders in templates have been replaced with CSV data. """ try: df_data = pd.read_csv(csv_path, dtype=str) df_data = df_data.fillna('') print(f"\nSuccessfully loaded {len(df_data)} records from '{csv_path}'.") except FileNotFoundError: print(f"CRITICAL ERROR: CSV file '{csv_path}' not found.") return [] except Exception as e: print(f"CRITICAL ERROR loading CSV '{csv_path}': {e}") traceback.print_exc() return [] if not ai_generated_templates: print("Warning: No AI-generated templates provided for instantiation. Returning empty list.") return [] final_instantiated_texts = [] warned_missing_cols = set() print(f"Instantiating {len(ai_generated_templates)} templates with CSV data...") for index, data_row in df_data.iterrows(): for template_str in ai_generated_templates: current_instance = template_str data_for_this_row: Dict[str, Any] = {} for csv_col_name in placeholder_column_names: if csv_col_name not in df_data.columns: if csv_col_name not in warned_missing_cols: print( f"Warning: CSV column '{csv_col_name}' (expected for placeholder '{{{{{csv_col_name}}}}}') not found in '{csv_path}'. Using empty string for this placeholder.") warned_missing_cols.add(csv_col_name) data_for_this_row[csv_col_name] = "" else: data_for_this_row[csv_col_name] = str(data_row[csv_col_name]) try: for placeholder_name, value in data_for_this_row.items(): current_instance = current_instance.replace(f"{{{{{placeholder_name}}}}}", value) final_instantiated_texts.append(current_instance) except Exception as ex: print(f"CRITICAL ERROR during template instantiation for CSV row {index}: {ex}") print(f" Original Template: {template_str}") print(f" Row Data (partial): {dict(list(data_for_this_row.items())[:3])}...") traceback.print_exc() # if final_instantiated_texts reach 300 elements, break to avoid memory issues if len(final_instantiated_texts) >= 50: print("Warning: Too many instantiated texts generated. Limiting to 50 for performance.") final_instantiated_texts = final_instantiated_texts[:50] return final_instantiated_texts ```