> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.instabase.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.instabase.com/_mcp/server.

# Calling LLMs from custom functions

> Follow these guidelines when writing custom functions to use in automation projects and deployments.

Single-tenant

In single-tenant environments, you can call an LLM from inside a custom function to get text or structured output—for example, to drive extraction, classification, or validation with AI. The context passed to your function includes an LLM client which is used to send the prompt and to receive the model's response. You don't need to specify an LLM provider or specific model in the code; these are derived from the tenant's configured LLM provider and the AI runtime model.

For the flow editor and supported flow steps, see [Calling LLMs from custom functions in flows](/flow/custom-functions/llms-custom-functions).

## Availability

In the app editor, this functionality is available when the project uses [agent mode](/automate/creating#agent-mode-and-legacy-mode) or the app uses [AI runtime](/automate/version-control#ai-runtime-versions) 2.x, in these custom function types:

* [Custom function fields](/automate/document-schema#custom-function-fields)

* [Classification functions](/automate/document-schema#classification-function)

* [Splitting functions](/automate/document-schema#splitting-function)

* [Validation functions](/automate/validating-documents#validation-function)

* [Cross-class validation functions](/automate/validating-packets#cross-class-validation-function)

* [Cross-class custom function fields](/automate/packet-schema#cross-class-custom-function-fields)

* [Deployment integration functions](/automate/deployments#integration-function)

## Using the LLM client

To use the LLM client, get it from the context, then call its `generate_content` method with your prompt and optional file data or response schema.

### Get the client from context

When the LLM client is available, the `context` dictionary has a `clients` property that contains a file client (`ibfile`) and an LLM client (`llm_client`). Use the file client's `read_file` to read document content. Use the LLM client's `generate_content` method to send a prompt to the model and get a response (optionally with file data or a response schema for structured output). If the LLM client isn't available for a given run (for example, the deployment or function type doesn't support it), `context.get('clients')` might be missing or `clients.get('llm_client')` might be `None`, so check before use.

### Call generate\_content

When you have the client, call `generate_content` for either text-only or file-aware generation:

```python
generate_content(
    prompt='str'
    file_data=None,
    mime_type=None,
    file_path=None,
    response_schema=None,
    enable_thinking=True,
    enable_logprobs=False,
)
```

| Parameter         | Required? | Type    | Description                                                                                                          |
| ----------------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
| `prompt`          | Yes       | string  | The text prompt to send to the model.                                                                                |
| `file_data`       | No        | bytes   | File data. Must be provided with `mime_type`. Default: None.                                                         |
| `mime_type`       | No        | string  | The multipurpose internet mail extensions (MIME) type of the file. Must be provided with `file_data`. Default: None. |
| `file_path`       | No        | string  | The file path. Default: None.                                                                                        |
| `response_schema` | No        | dict    | Schema for structured output. Default: None.                                                                         |
| `enable_thinking` | No        | boolean | Whether to enable thinking/reasoning mode. Default: True.                                                            |
| `enable_logprobs` | No        | boolean | Whether to include log probabilities (per-token confidence scores from the model) in the response. Default: False.   |

## Example: Deductions table with structured output

The following example reads the file at `context['file_path']`, uses the file client to get file content, then calls `generate_content` with a prompt, file data, and a `response_schema` to return a deductions table. When `clients` or `llm_client` isn't present the situation can be handled by returning a fallback value or skipping LLM-based logic.

```python
file_path = context['file_path']

clients = context.get('clients', {})
file_client = clients.get('ibfile')
llm_client = clients.get('llm_client')

if llm_client is None or file_client is None:
    return None  # or your fallback when the LLM client isn't available

file_content, err = file_client.read_file(file_path)

resp_text = llm_client.generate_content(
    prompt='Return the deductions table. remove any extra symbols from the amount deducted',
    file_data=file_content,
    mime_type='application/pdf',
    file_path=file_path,
    response_schema={
        "type": "array",
        "items": {
            "type": "object",
            "properties": {
                "description": {"type": "string"},
                "amount deducted": {"type": "float"},
            },
        },
        "description": "deductions table"
    }
)

return resp_text
```