***

title: CustomSkillsSkill
slug: /reference/typescript/agents/skills/custom-skills
description: A meta-skill that registers user-defined tools from configuration.
---------------------

For a complete index of all SignalWire documentation pages, fetch https://signalwire.com/docs/llms.txt

[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill

A meta-skill that registers user-defined tools from configuration. Define
tools with names, descriptions, parameters, and JavaScript handler code
without writing skill classes.

**Class:** `CustomSkillsSkill`

**Tools:** Dynamically created from the `tools` array

**Env vars:** `SWML_ALLOW_CUSTOM_HANDLER_CODE` must be set to `"true"` to enable handler execution.

<ParamField path="tools" type={"Record<string, unknown>[]"} toc={true}>
  Array of custom tool definitions. Each object has:

  * `name` (string, required) -- Unique tool name.
  * `description` (string, required) -- Tool description shown to the AI.
  * `handler_code` (string, required) -- JavaScript function body. Receives `(args, rawData, FunctionResult)` as arguments. Must return a `FunctionResult`, string, or object.
  * `parameters` (array, optional) -- Parameter definitions: `[{ name, type, description, required? }]`.
  * `required` (string\[], optional) -- Array of required parameter names.
  * `prompt_description` (string, optional) -- Description to include in the prompt section.
  * `secure` (boolean, optional) -- Whether to mark the tool as secure.
  * `fillers` (object, optional) -- Filler phrases keyed by language.
</ParamField>

<ParamField path="prompt_title" type="string" default="Custom Tools" toc={true}>
  Custom title for the prompt section.
</ParamField>

<ParamField path="prompt_body" type="string" toc={true}>
  Custom body text for the prompt section.
</ParamField>

```typescript {6-14}
import { AgentBase, CustomSkillsSkill } from '@signalwire/sdk';

const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
agent.setPromptText('You are a helpful assistant.');

await agent.addSkill(new CustomSkillsSkill({
  tools: [
    {
      name: 'greet_user',
      description: 'Greet the user by name.',
      parameters: [
        { name: 'name', type: 'string', description: 'The user name', required: true },
      ],
      required: ['name'],
      handler_code: 'return new FunctionResult("Hello, " + args.name + "! Welcome.");',
    },
  ],
}));

agent.run();
```