***

title: Helper Functions
slug: /reference/python/agents/helpers
description: Top-level convenience functions for creating contexts, data map tools, and managing skills.
max-toc-depth: 3
---------------------

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

[context]: /docs/server-sdks/reference/python/agents/context-builder/context

[contextbuilder]: /docs/server-sdks/reference/python/agents/context-builder

[datamap]: /docs/server-sdks/reference/python/agents/data-map

[skillbase]: /docs/server-sdks/reference/python/agents/skill-base

[ref-functionresult]: /docs/server-sdks/reference/python/agents/function-result

The SignalWire SDK exports several helper functions at the top level for common
tasks like creating simple contexts, building server-side API tools, and
managing the skill registry. All are imported directly from `signalwire`.

```python
from signalwire import (
    create_simple_context,
    create_simple_api_tool,
    create_expression_tool,
    list_skills_with_params,
    register_skill,
    add_skill_directory,
)
```

***

## create\_simple\_context

**create\_simple\_context**(`name="default"`) -> [`Context`][context]

Create a standalone [`Context`][context] object
without needing a full [`ContextBuilder`][contextbuilder].
Useful for quick single-context agents.

#### Parameters

<ParamField path="name" type="str" default="default" toc={true}>
  Context name. For single-context agents this must be `"default"`.
</ParamField>

#### Returns

[`Context`][context] -- A new Context
object ready for adding steps.

#### Example

```python
from signalwire import create_simple_context

ctx = create_simple_context()
ctx.add_step("greet").set_text("Say hello to the caller.")
ctx.add_step("help").set_text("Ask how you can help today.")
```

***

## create\_simple\_api\_tool

**create\_simple\_api\_tool**(`name`, `url`, `response_template`, `parameters=None`, `method="GET"`, `headers=None`, `body=None`, `error_keys=None`) -> [`DataMap`][datamap]

Create a server-side API tool with minimal configuration. Returns a configured
[`DataMap`][datamap] that executes an HTTP
request on the SignalWire server without requiring a webhook endpoint.

#### Parameters

<ParamField path="name" type="str" required={true} toc={true}>
  Function name for the SWAIG tool.
</ParamField>

<ParamField path="url" type="str" required={true} toc={true}>
  API endpoint URL. Supports `${variable}` substitution for injecting parameter
  values (e.g., `"https://api.example.com/search?q=${args.query}"`).
</ParamField>

<ParamField path="response_template" type="str" required={true} toc={true}>
  Template string for formatting the API response. Uses `${response.field}`
  syntax to reference fields from the API response JSON.
</ParamField>

<ParamField path="parameters" type="dict[str, dict]" toc={true}>
  Parameter definitions. Each key is a parameter name, and each value is a
  dictionary with `type`, `description`, and optionally `required`.
</ParamField>

<ParamField path="method" type="str" default="GET" toc={true}>
  HTTP method for the API call.
</ParamField>

<ParamField path="headers" type="dict[str, str]" toc={true}>
  Optional HTTP headers to include in the request.
</ParamField>

<ParamField path="body" type="dict[str, Any]" toc={true}>
  Optional request body for POST/PUT requests.
</ParamField>

<ParamField path="error_keys" type="list[str]" toc={true}>
  JSON keys whose presence in the response indicates an error.
</ParamField>

#### Returns

[`DataMap`][datamap] -- A configured DataMap
ready to be added to an agent.

#### Example

```python
from signalwire import create_simple_api_tool

weather_tool = create_simple_api_tool(
    name="get_weather",
    url="https://api.weather.com/v1/current?key=API_KEY&q=${args.location}",
    response_template="Weather in ${args.location}: ${response.current.condition.text}, ${response.current.temp_f}F",
    parameters={
        "location": {
            "type": "string",
            "description": "City name",
            "required": True
        }
    }
)
```

<Tip>
  For more complex API integrations with multiple webhooks, fallback outputs, or
  array processing, use the [`DataMap`][datamap]
  builder directly.
</Tip>

***

## create\_expression\_tool

**create\_expression\_tool**(`name`, `patterns`, `parameters=None`) -> [`DataMap`][datamap]

Create a pattern-matching tool that evaluates expressions locally on the
SignalWire server without making any HTTP requests. Useful for command routing
and conditional responses.

#### Parameters

<ParamField path="name" type="str" required={true} toc={true}>
  Function name for the SWAIG tool.
</ParamField>

<ParamField path="patterns" type="dict[str, tuple[str, FunctionResult]]" required={true} toc={true}>
  Dictionary mapping test values to `(pattern, [FunctionResult][ref-functionresult])` tuples. The test
  value is a template string (e.g., `"${args.command}"`), and the pattern is a
  regex string matched against it.
</ParamField>

<ParamField path="parameters" type="dict[str, dict]" toc={true}>
  Parameter definitions, same format as `create_simple_api_tool`.
</ParamField>

#### Returns

[`DataMap`][datamap] -- A configured DataMap
with expression-based routing.

#### Example

```python
from signalwire import create_expression_tool
from signalwire import FunctionResult

playback_tool = create_expression_tool(
    name="playback_control",
    patterns={
        "${args.command}": (
            r"play.*",
            FunctionResult().add_action("start_playbook", {"file": "${args.filename}"})
        ),
        "${args.command}": (
            r"stop.*",
            FunctionResult().add_action("stop_playback", True)
        ),
    },
    parameters={
        "command": {"type": "string", "description": "Playback command", "required": True},
        "filename": {"type": "string", "description": "File to play"},
    }
)
```

<Note>
  Since dictionary keys must be unique, use separate `DataMap.expression()` calls
  via the [`DataMap`][datamap] builder if you
  need multiple patterns against the same test value.
</Note>

***

## list\_skills\_with\_params

**list\_skills\_with\_params**() -> `dict[str, dict[str, Any]]`

Return a comprehensive schema for all available skills, including metadata and
parameter definitions. Useful for GUI configuration tools, API documentation,
or programmatic skill discovery.

#### Returns

`dict[str, dict[str, Any]]` -- Dictionary keyed by skill name. Each value
contains the skill's metadata and a `parameters` dictionary describing each
configurable parameter with its `type`, `description`, `required` status,
`hidden` flag, and `env_var` name.

#### Example

```python
from signalwire import list_skills_with_params

schema = list_skills_with_params()
for skill_name, skill_info in schema.items():
    print(f"{skill_name}: {skill_info.get('description', '')}")
    for param, meta in skill_info.get("parameters", {}).items():
        print(f"  {param}: {meta['type']} (required={meta.get('required', False)})")
```

***

## register\_skill

**register\_skill**(`skill_class`) -> `None`

Register a custom skill class with the global skill registry. This allows
third-party code to make skills available without placing them in a specific
directory structure.

#### Parameters

<ParamField path="skill_class" type="type" required={true} toc={true}>
  A class that inherits from
  [`SkillBase`][skillbase]. Must define
  `SKILL_NAME` and `SKILL_DESCRIPTION` class attributes.
</ParamField>

#### Example

```python
from signalwire import register_skill
from signalwire import AgentBase

class MyWeatherSkill:
    SKILL_NAME = "my_weather"
    SKILL_DESCRIPTION = "Custom weather lookup"

    def setup(self):
        return True

    def register_tools(self):
        self.define_tool(name="get_weather", handler=self._get_weather, description="Get weather")

    def _get_weather(self, args, raw_data):
        return {"response": "Sunny, 72F"}

register_skill(MyWeatherSkill)

agent = AgentBase(name="my-agent")
agent.add_skill("my_weather")
```

***

## add\_skill\_directory

**add\_skill\_directory**(`path`) -> `None`

Add a directory to the skill search path. Skills in this directory should follow
the same structure as built-in skills (each skill in its own subdirectory with
an `__init__.py` exporting a `SkillBase` subclass).

#### Parameters

<ParamField path="path" type="str" required={true} toc={true}>
  Path to a directory containing skill subdirectories.
</ParamField>

#### Example

```python
from signalwire import add_skill_directory, AgentBase

add_skill_directory("/opt/custom_skills")

agent = AgentBase()
agent.add_skill("my_custom_skill")  # Found in /opt/custom_skills/my_custom_skill/
```