# How to Configure Custom Personas in the NotebookLM Chat API

> Configure custom personas in NotebookLM Chat API using NotebookLMClient.chat.configure() with ChatGoal.CUSTOM and a custom_prompt for persistent system personas. Learn more now!

- Repository: [Teng Lin/notebooklm-py](https://github.com/teng-lin/notebooklm-py)
- Tags: how-to-guide
- Published: 2026-03-09

---

**Use the `NotebookLMClient.chat.configure()` method with `goal=ChatGoal.CUSTOM` and a `custom_prompt` string to define a persistent system persona that governs all chat responses for a specific notebook.**

The notebooklm-py library exposes Google’s internal `s0tc2d` RPC interface, allowing you to inject custom system prompts—personas—that persist at the notebook level. When configured, every subsequent chat request for that notebook automatically adopts the specified role, such as a chemistry tutor or data-science mentor, without requiring you to resend the prompt text each time.

## Architecture and Implementation

Understanding how the library structures the RPC payload helps explain why the configuration requires specific enum values and nested arrays.

### The Configure Method

The entry point is `NotebookLMClient.chat.configure()` in [`src/notebooklm/_chat.py`](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_chat.py) (lines 56‑71). This async method validates arguments, constructs the payload, and invokes `self._core.rpc_call` using the `RENAME_NOTEBOOK` method identifier. According to the source code, this method does not merely rename notebooks—it acts as the generic configuration endpoint for notebook-level chat settings.

### RPC Payload Structure

The underlying Google service expects a specific nested array format. The library builds two key structures:

- **`goal_array`** – Contains `[ChatGoal.CUSTOM.value, custom_prompt]` when using a custom persona, or `[ChatGoal.DEFAULT.value]` for standard behavior.
- **`chat_settings`** – A wrapper array `[goal_array, [ChatResponseLength.DEFAULT.value]]` that also encodes the desired verbosity level.

These structures are defined in [`src/notebooklm/_chat.py`](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_chat.py) (lines 85‑91) and map directly to the undocumented `s0tc2d` contract.

### Enum Definitions

The `ChatGoal` enum in [`src/notebooklm/rpc/types.py`](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/rpc/types.py) (lines 50‑58) defines the configuration modes:

- `DEFAULT = 1` – Standard NotebookLM behavior.
- `CUSTOM = 2` – Signals that a custom prompt string will follow.
- `REFINE_AUDIO = 3` – Specialized mode for audio refinement (not typically used for text personas).

The `ChatResponseLength` enum (lines 61‑69) controls verbosity with `DEFAULT`, `LONGER`, or `SHORTER` values.

### Validation Guards

The `configure` method enforces data integrity. If you specify `goal=ChatGoal.CUSTOM` without providing the `custom_prompt` parameter, the library raises a `ValidationError` immediately before making the network request (see the guard clause in [`src/notebooklm/_chat.py`](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_chat.py) lines 56‑71).

## Configuring Personas via the Python API

Use the async `configure` method to apply a persona programmatically. You must import the enums from `notebooklm.rpc` to ensure correct integer values are sent to the backend.

```python
import asyncio
from notebooklm import NotebookLMClient
from notebooklm.rpc import ChatGoal, ChatResponseLength

async def set_custom_persona():
    async with NotebookLMClient.from_storage() as client:
        notebook_id = "nb_12345"  # Replace with your notebook ID

        
        await client.chat.configure(
            notebook_id,
            goal=ChatGoal.CUSTOM,
            response_length=ChatResponseLength.DEFAULT,
            custom_prompt=(
                "You are a senior data-science mentor. Explain concepts "
                "step-by-step with code examples and focus on practical "
                "applications."
            )
        )
        print("✅ Custom persona applied")

asyncio.run(set_custom_persona())

```

**Key implementation details:**
- The `custom_prompt` accepts up to 10,000 characters.
- The persona persists until explicitly changed via another `configure` call.
- The method uses the `RENAME_NOTEBOOK` RPC under the hood, as implemented in [`src/notebooklm/_chat.py`](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_chat.py).

## Using the CLI to Set Personas

The command-line interface in [`src/notebooklm/cli/chat.py`](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/cli/chat.py) (lines 24‑70) wraps the same API. The `notebooklm configure` command resolves the current notebook context and maps flags to the appropriate enum values.

```bash

# Set a custom persona with default response length

notebooklm configure \
  --persona "You are a friendly math tutor. Explain ideas with simple analogies."

# Combine with verbosity control

notebooklm configure \
  --persona "You are a concise legal advisor." \
  --response-length shorter

```

The CLI handler validates that the `--persona` flag populates the `custom_prompt` field and automatically sets `goal` to `ChatGoal.CUSTOM` before invoking `client.chat.configure()`.

## Reverting to Default Behavior

To remove a custom persona and restore standard NotebookLM responses, call `configure` with `ChatGoal.DEFAULT`:

```python
await client.chat.configure(notebook_id, goal=ChatGoal.DEFAULT)

```

Or via CLI:

```bash
notebooklm configure  # No flags resets to defaults

```

This sends `[ChatGoal.DEFAULT.value]` in the `goal_array`, effectively clearing the custom prompt from the notebook’s chat configuration.

## Summary

- **Entry point:** Use `NotebookLMClient.chat.configure()` defined in [`src/notebooklm/_chat.py`](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_chat.py) to set notebook-level personas.
- **Custom mode:** Pass `goal=ChatGoal.CUSTOM` (value 2) along with a `custom_prompt` string; omitting the prompt raises a `ValidationError`.
- **Payload structure:** The library constructs nested arrays (`goal_array` and `chat_settings`) to satisfy the Google `s0tc2d` RPC contract.
- **Persistence:** Configurations are stored server-side via the `RENAME_NOTEBOOK` method and apply to all future `client.chat.ask()` calls for that notebook.
- **CLI support:** The `notebooklm configure --persona "..."` command provides a synchronous interface to the same functionality.

## Frequently Asked Questions

### What happens if I use ChatGoal.CUSTOM without providing a custom prompt?

The library raises a `ValidationError` during argument validation. The guard clause in [`src/notebooklm/_chat.py`](https://github.com/teng-lin/notebooklm-py/blob/main/src/notebooklm/_chat.py) explicitly checks that `custom_prompt` is truthy when `goal == ChatGoal.CUSTOM`, preventing malformed RPC requests.

### Is there a character limit for custom personas?

Yes. While the RPC contract does not strictly enforce limits, the library documentation and examples indicate you should keep custom prompts under 10,000 characters to ensure reliable transmission through the `s0tc2d` service.

### How long does a custom persona remain active?

The persona persists indefinitely at the notebook level until you explicitly reconfigure it. Because the setting is stored server-side via the `RENAME_NOTEBOOK` RPC call, it survives client restarts and applies to all chat sessions for that notebook ID, regardless of which device or session initiates the conversation.

### Can I combine a custom persona with specific response lengths?

Absolutely. The `configure` method accepts both `goal` and `response_length` parameters simultaneously. Pass `ChatResponseLength.LONGER` or `ChatResponseLength.SHORTER` alongside your `ChatGoal.CUSTOM` to control verbosity while maintaining your custom role definition.