How do I create a custom tool?

Prev Next

Custom tools extend Candela with capabilities specific to your organisation - no code required for your end-users.

A tool wraps either of the following and exposes it as a named tool that your Candela agents can call:

For example, you could create a GetPortfolioProperties tool that returns all custom metadata attached to a portfolio, then assign it to a specialist agent so your team can retrieve that data through a simple conversation prompt.

This article explains how to create and assign custom tools via the LUSID Identity API.

Prerequisites

  • Suitable access permissions to create MCP tools in LUSID

  • For Luminesce tools: Your tested Luminesce SQL query

  • For Scheduler tools: Your Scheduler job’s scope and code

Step 1: Create a tool

Understanding the fields required to create a tool

All tools share the following fields:

Field

Description

name

A tool name that’s unique within your domain.

title

A friendly title to show in tool listings.

description

A specific, action-oriented description for the AI to use to decide when to call the tool.

destructive

Set to true to require user confirmation before executing. Read more.

readOnly

Set to false to have an agent confirm with a user before calling the tool.

parameters

A list of parameters that the tool can pass into the underlying Luminesce query or scheduler job. See parameters below.

luminescePayload or schedulerPayload

The query or job this tool executes; more information below.

Note

The idempotent and openWorld fields are currently reference-only. In future, they will be used to govern how tools are executed and what external services they can access.

parameters

Each parameter declared in the parameters array can be referenced in your luminescePayload query or schedulerPayload arguments using triple curly brace {{{<parameter>}}} syntax. When called, Candela substitutes each placeholder with the value provided in the conversation.

Each parameter requires the following fields:

Field

Description

name

The parameter name, which you can subsequently reference in the payload as {{{<parameter>}}}.

dataType

The expected data type.

description

A specific description of the parameter for the agent to use to determine what value to pass. For example, "The LUSID scope of the portfolio, for example 'acme'" is more effective than "The portfolio scope".

Luminesce-powered tools

Imagine you want to create a tool that can run the following Luminesce query:

select [PropertyScope], [PropertyCode], [Value] 
from [Lusid.Portfolio.Property] 
where [PortfolioScope] = '{{{portfolioScope}}}' and [PortfolioCode] = '{{{portfolioCode}}}'

You can call the CreateMcpTool API, passing in the fields from the table above, plus the following luminescePayload:

curl -X POST 'https://<your-domain>.lusid.com/identity/api/mcptools/Finbourne-Examples/GetPortfolioProperties'
  -H 'Accept: application/json' 
  -H 'Authorization: Bearer <your-API-access-token>'
  -H 'Content-Type: application/json-patch+json' 
  -d '{
    "name": "GetPortfolioProperties",
    "title": "Get custom properties for a portfolio",
    "description": "Returns all custom properties attached to a portfolio. Use when the user asks about portfolio metadata, tags, or custom attributes.",
    "destructive": false,
    "idempotent": true,
    "openWorld": false,
    "readOnly": true,
    "parameters": [
      { "name": "portfolioScope", "dataType": "String", "description": "The LUSID scope of the portfolio" },
      { "name": "portfolioCode", "dataType": "String", "description": "The LUSID code of the portfolio" }
    ],
    "luminescePayload": {
      "query": "select [PropertyScope], [PropertyCode], [Value] from [Lusid.Portfolio.Property] where [PortfolioScope] = '\''{{{portfolioScope}}}'\'' and [PortfolioCode] = '\''{{{portfolioCode}}}'\''"
    }
  }
'

Scheduler-powered tools

To create a tool that can trigger a scheduled job, you can call the CreateMcpTool API, passing in the fields from the table above, plus the following schedulerPayload:

curl -X POST 'https://<your-domain>.lusid.com/identity/api/mcptools/Finbourne-Examples/RunComplianceJob'
  -H 'Accept: application/json' 
  -H 'Authorization: Bearer <your-API-access-token>'
  -H 'Content-Type: application/json-patch+json' 
  -d '{
  "name": "RunComplianceJob",
  "title": "Run a compliance scheduler job",
  "description": "Triggers the nightly compliance job for a given set of rules.",
  "destructive": false,
  "idempotent": false,
  "readOnly": false,
  "parameters": [
    {
      "name": "ruleScope",
      "dataType": "String",
      "description": "The rules scope to run compliance on"
    },
        {
      "name": "runScope",
      "dataType": "String",
      "description": "The scope to run compliance for"
    }
  ],
  "schedulerPayload": {
    "jobScope": "Finbourne-Examples",
    "jobCode": "RunCompliance",
    "arguments": {
      "ruleScope": "{{{ruleScope}}}",
      "runScope": "{{{runScope}}}"
    }
  }
}'

Step 2: Assign the tool to an agent

Agents only call tools that you explicitly list in their toolNames array. See how to create or update an agent.