|
| 1 | +--- |
| 2 | +id: extensions-studio |
| 3 | +title: CMND Extensions Studio |
| 4 | +description: Create and deploy custom tools easily inside CMND using the Extensions Studio. |
| 5 | +sidebar_position: 3 |
| 6 | +--- |
| 7 | + |
| 8 | +import Tabs from '@theme/Tabs'; |
| 9 | +import TabItem from '@theme/TabItem'; |
| 10 | + |
| 11 | +# Extensions Studio |
| 12 | + |
| 13 | +The CMND Extensions Studio provides an easier way to create and connect custom tools to CMND — without needing to deploy your own server. |
| 14 | + |
| 15 | +It offers the same functionality as building through the Extensions API, but streamlines the process by allowing you to develop, configure, and host your tool directly inside the CMND platform. |
| 16 | + |
| 17 | +:::note |
| 18 | +This guide walks through how to create and deploy a custom tool using JavaScript or Python inside the CMND Extensions Studio. |
| 19 | +::: |
| 20 | + |
| 21 | +--- |
| 22 | + |
| 23 | +## How to Use the Extensions Studio |
| 24 | + |
| 25 | +### 1. Open the CMND Dashboard |
| 26 | + |
| 27 | +- Go to [app.cmnd.ai](https://app.cmnd.ai) and log in to your account. |
| 28 | +- From the sidebar, navigate to the **Connections** section. |
| 29 | + |
| 30 | +  |
| 31 | + |
| 32 | +--- |
| 33 | + |
| 34 | +### 2. Launch the Extensions Studio |
| 35 | + |
| 36 | +- In the search bar, enter "CMND Extension Studio" and select it from the results. |
| 37 | + |
| 38 | +  |
| 39 | + |
| 40 | +--- |
| 41 | + |
| 42 | +### 3. Configure Your Tool |
| 43 | + |
| 44 | +- Enter the name of your new tool. |
| 45 | +- Choose your development language (**Python** or **JavaScript**). |
| 46 | +- Click **Start**. |
| 47 | + |
| 48 | + <!-- ![Extensions Studio Configurations]() --> |
| 49 | + |
| 50 | + Once you click Start, you’ll be taken to the code editor with a boilerplate project ready, depending on the language you chose. |
| 51 | + |
| 52 | +--- |
| 53 | + |
| 54 | +## Defining Your Tool |
| 55 | + |
| 56 | +Each project will contain a base file (`tools.py` or `tools.js`) where you define your tool logic, input schema, and metadata. |
| 57 | + |
| 58 | +<Tabs> |
| 59 | +<TabItem value="python" label="Python" default> |
| 60 | + |
| 61 | +Inside `tools.py`: |
| 62 | + |
| 63 | +```python title="tools.py" showLineNumbers |
| 64 | +from pydantic import BaseModel, Field |
| 65 | +import httpx |
| 66 | +import os |
| 67 | + |
| 68 | +class WeatherCitySchema(BaseModel): |
| 69 | + city: str = Field(..., title="City", description="City name required") |
| 70 | + |
| 71 | +async def weather_from_location(city: str): |
| 72 | + api_key = os.getenv('WEATHER_API_KEY') |
| 73 | + url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}" |
| 74 | + async with httpx.AsyncClient() as client: |
| 75 | + response = await client.get(url) |
| 76 | + return response.json() |
| 77 | + |
| 78 | +tool = [ |
| 79 | + { |
| 80 | + "name": "weather_from_location", |
| 81 | + "description": "Gets the weather details from a given city name", |
| 82 | + "parameters": WeatherCitySchema.schema(), |
| 83 | + "runCmd": weather_from_location, |
| 84 | + "isDangerous": False, |
| 85 | + "functionType": "backend", |
| 86 | + "isLongRunningTool": False, |
| 87 | + "rerun": True, |
| 88 | + "rerunWithDifferentParameters": True |
| 89 | + } |
| 90 | +] |
| 91 | +``` |
| 92 | + |
| 93 | +- Use **Pydantic** to define your input schema |
| 94 | +- Write the tool's logic |
| 95 | +- Register the tool by adding it to the `tool` array |
| 96 | + |
| 97 | +</TabItem> |
| 98 | + |
| 99 | +<TabItem value="javascript" label="JavaScript"> |
| 100 | + |
| 101 | +Inside `tools.js`: |
| 102 | + |
| 103 | +```javascript title="tools.js" showLineNumbers |
| 104 | +const axios = require("axios"); |
| 105 | +const yup = require("yup"); |
| 106 | +const yupToJsonSchema = require("./yupToJsonSchema"); |
| 107 | + |
| 108 | +const WeatherSchema = yup.object({ |
| 109 | + city: yup.string().required(), |
| 110 | +}); |
| 111 | + |
| 112 | +const WeatherTool = { |
| 113 | + name: "weather_from_location", |
| 114 | + description: "Fetches current weather for a given city", |
| 115 | + category: "weather", |
| 116 | + subcategory: "forecast", |
| 117 | + functionType: "backend", |
| 118 | + dangerous: false, |
| 119 | + associatedCommands: [], |
| 120 | + prerequisites: [], |
| 121 | + parameters: yupToJsonSchema(WeatherSchema), |
| 122 | + rerun: true, |
| 123 | + rerunWithDifferentParameters: true, |
| 124 | + runCmd: async ({ city }) => { |
| 125 | + try { |
| 126 | + const response = await axios.get( |
| 127 | + `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${process.env.WEATHER_API_KEY}` |
| 128 | + ); |
| 129 | + return JSON.stringify(response.data); |
| 130 | + } catch (err) { |
| 131 | + return "Error trying to execute the tool"; |
| 132 | + } |
| 133 | + }, |
| 134 | +}; |
| 135 | + |
| 136 | +const tools = [WeatherTool]; |
| 137 | +module.exports = tools; |
| 138 | +``` |
| 139 | + |
| 140 | +- Use **Yup** to define your input schema |
| 141 | +- Implement the tool logic |
| 142 | +- Export your tool properly for CMND to pick up |
| 143 | + |
| 144 | +</TabItem> |
| 145 | +</Tabs> |
| 146 | + |
| 147 | +--- |
| 148 | + |
| 149 | +## Deploying Your Tool |
| 150 | + |
| 151 | +Once you finish defining your tool: |
| 152 | + |
| 153 | +- Click the **Deploy** button in the Extensions Studio editor. |
| 154 | +- CMND will build and host the tool for you automatically. |
| 155 | +- Your tool will be available immediately inside the platform for use in conversations and assistants. |
| 156 | + |
| 157 | +--- |
| 158 | + |
| 159 | +The CMND Extensions Studio allows you to go from an idea to a live, integrated tool — without worrying about servers, hosting, or infrastructure. |
0 commit comments