> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xpander.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Custom Function

> Create a new custom function with Python source code

Create a new custom function. The code must define a function called `xpander_run_action(...)` that will be executed when the function is invoked. After creation, the function is automatically analyzed for safety and input schema extraction.

## Request Body

<ParamField body="name" type="string" required>
  Display name for the custom function
</ParamField>

<ParamField body="source_code" type="string" required>
  Python source code. Must contain a `xpander_run_action(...)` function definition.
</ParamField>

<ParamField body="function_name" type="string">
  Internal function name (defaults to sanitized version of `name`)
</ParamField>

<ParamField body="description" type="string">
  Human-readable description of what the function does
</ParamField>

<ParamField body="limits" type="object">
  Execution limits

  <Expandable title="Limits Object">
    <ParamField body="timeout" type="integer">
      Maximum execution time in seconds
    </ParamField>

    <ParamField body="memory" type="integer">
      Maximum memory in MB
    </ParamField>
  </Expandable>
</ParamField>

## Response

Returns the created `CustomFunctionItem` with status `analysing`. The function transitions to `ready` once analysis completes.

## Example Request

```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/custom_functions" \
  -H "Content-Type: application/json" \
  -H "x-api-key: <your-api-key>" \
  -d '{
    "name": "Weather Lookup",
    "description": "Fetches current weather for a given city",
    "source_code": "import requests\n\ndef xpander_run_action(city: str) -> str:\n    \"\"\"Get current weather for a city.\"\"\"\n    resp = requests.get(f\"https://wttr.in/{city}?format=3\")\n    return resp.text"
  }'
```

## Notes

* The `xpander_run_action` function is the entry point — it must be defined in the source code
* After creation, the function is automatically analyzed for safety and input schema extraction
* Status transitions: `analysing` → `ready` (success) or `analysing` → `error` (analysis failed)
* Check `analysis_error_details` if the function moves to `error` status


## OpenAPI

````yaml POST /v1/custom_functions
openapi: 3.1.0
info:
  title: xpander.ai API Service
  description: |2-

        The xpander.ai API Service provides a unified REST API for managing AI agents,
        executing tasks, managing knowledge bases, and integrating with external systems.
        
        Features:
        - Agent Management: Create, update, deploy, and delete AI agents
        - Task Execution: Invoke agents with support for sync, async, and streaming modes
        - Knowledge Bases: Manage knowledge bases and documents for RAG workflows
        - Tools: Discover, connect, and attach tools (connectors, custom functions, MCP servers, sub-agents, workflows) to agents and workflows
        - MCP Integration: Model Context Protocol support for standardized AI interactions
        
        Authentication: All endpoints require authentication via either an API key (`x-api-key`) or an OAuth2 JWT (`Authorization: Bearer <jwt>`).
        
  version: '0.001'
servers:
  - url: https://api.xpander.ai
security: []
paths:
  /v1/custom_functions:
    post:
      tags:
        - API v1
        - Custom Functions
        - Custom Functions CRUD
      summary: Create Custom Function
      description: >-
        Create a new custom function. Provide a name, optional description, and
        Python source code. The code must define a function called
        `xpander_run_action(...)` that will be executed when the function is
        invoked. After creation, the function is automatically analyzed for
        safety and input schema extraction. Status will transition from
        'analysing' to 'ready' once analysis completes.
      operationId: Create_custom_function_v1_custom_functions_post
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCustomFunctionRequest'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - APIKeyHeader: []
components:
  schemas:
    CreateCustomFunctionRequest:
      properties:
        name:
          type: string
          title: Name
          description: >-
            Human-readable name for the custom function. Used as the display
            name in the agent's tool list. Examples: 'Calculate Tax', 'Parse CSV
            Data'.
        function_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Function Name
          description: >-
            Optional programmatic function name. If not provided, defaults to
            'xpander_run_action'. The source_code must define a function with
            this name.
        description:
          anyOf:
            - type: string
            - type: 'null'
          title: Description
          description: >-
            Description of what the function does. This is shown to the LLM when
            the function is used as an agent tool, so make it clear and
            action-oriented.
          default: ''
        source_code:
          type: string
          title: Source Code
          description: >-
            Python source code for the custom function. Must define a function
            called `xpander_run_action(...)` (or the name specified in
            function_name).


            The function receives keyword arguments matching its parameter
            signature. It should return a dict or string result.


            Example:

            ```python

            def xpander_run_action(text: str, max_words: int = 100) -> dict:
                words = text.split()[:max_words]
                return {"word_count": len(words), "truncated_text": " ".join(words)}
            ```


            The function runs in a secure Python 3.12 sandbox with common
            libraries available (requests, json, re, datetime, etc.).

            Do NOT use: file system access, subprocess, os.system, eval/exec, or
            network access to internal services.
        limits:
          anyOf:
            - $ref: '#/components/schemas/CustomFunctionLimitsModel'
            - type: 'null'
          description: >-
            Resource limits for the function execution. Currently only
            max_run_time (seconds) is supported.
      type: object
      required:
        - name
        - source_code
      title: CreateCustomFunctionRequest
      description: |-
        Request model for creating a new custom function.

        The source code must define a function called `xpander_run_action(...)`.
        This is the entry point that will be called when the function is invoked
        by an agent or via the execute endpoint.

        After creation, the function is automatically analyzed for:
        - Safety (no malicious patterns)
        - Input schema extraction (parameters are auto-detected)
        - Runnability (syntax validation)

        The function status starts as 'analysing' and transitions to 'ready'
        once analysis completes successfully.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    CustomFunctionLimitsModel:
      properties:
        max_run_time:
          anyOf:
            - type: integer
            - type: 'null'
          title: Max Run Time
          description: >-
            Maximum execution time in seconds. The function will be terminated
            if it exceeds this limit. Default: 15 seconds.
          default: 15
      type: object
      title: CustomFunctionLimitsModel
      description: Resource limits for custom function execution.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
  securitySchemes:
    APIKeyHeader:
      type: apiKey
      description: API Key for authentication
      in: header
      name: x-api-key

````