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

# Setup Checklist

> One-time resource provisioning before your first call.

# Setup Checklist

Before your first call routes to your Speech Pipe, complete these steps once.

## 1. Create a Voice Profile

```python theme={null}
import asyncio
from unpod import AsyncClient

async def list_profiles():
    client = AsyncClient()
    profiles = await client.voice_profiles.list()
    for p in profiles:
        print(p.name)

asyncio.run(list_profiles())
```

## 2. Create a Speech Pipe

```python theme={null}
import asyncio
from unpod import AsyncClient

async def create_pipe():
    client = AsyncClient()
    pipe = await client.pipes.create(
        name="My Agent",
        voice_profile="vp_en_female_hd",   # use a profile_id from step 1
        agent_id="my-agent",           # MUST match AgentRunner(agent_id=...)
    )
    print(pipe.pipe_id)  # UUID - used for REST API calls
    return pipe

asyncio.run(create_pipe())
```

<Warning>
  **`agent_id` vs `pipe.pipe_id`**

  * `pipe.pipe_id` - UUID assigned by Unpod, used in REST API calls
  * `agent_id` - string name you choose; must exactly match `AgentRunner(agent_id=...)`

  These are different. Mismatching them is the most common first-run failure.
</Warning>

<Note>
  Replace `"vp_en_female_hd"` with a `profile_id` from Step 1. Run Step 1 first to see available profiles.
</Note>

## 3. Assign a Phone Number

```python theme={null}
import asyncio
from unpod import AsyncClient

async def assign_number(pipe_id: str) -> None:
    client = AsyncClient()
    numbers = await client.numbers.list()
    if not numbers:
        print("No numbers available. Provision one in the Unpod dashboard first.")
        return
    await client.numbers.attach(numbers[0].id, pipe_id=pipe_id)
    print(f"Assigned {numbers[0].number}")

asyncio.run(assign_number("YOUR_PIPE_UUID"))
```

## 4. Start Your Runner

```python theme={null}
from unpod import AgentRunner

AgentRunner(
    entrypoint=entrypoint,
    agent_id="my-agent",   # must match the pipe's agent_id above
).start()
```

## Which Setting To Use

* Use `UNPOD_BASE_URL` when the management API and runner should both point to
  the same host.
* Use `UNPOD_SERVICE_BASE_URL` only for management REST overrides.
* Use `UNPOD_ORCHESTRATOR_URL` only for runner WebSocket overrides.
* Use `base_url=` / `orchestrator_base_url=` in code when a single script or
  test needs to override `.env`.

## Full Setup Script

```python theme={null}
import asyncio
from unpod import AsyncClient, AgentRunner, CallContext
from unpod.adapters.langchain import LangChainAdapter

async def setup():
    client = AsyncClient()

    # List available voice profiles
    profiles = await client.voice_profiles.list()
    profile = profiles[0]

    # Create Speech Pipe
    pipe = await client.pipes.create(
        name="My Agent",
        voice_profile=profile.profile_id,
        agent_id="my-agent",
    )

    # Assign first available number
    numbers = await client.numbers.list()
    if numbers:
        await client.numbers.attach(numbers[0].id, pipe_id=pipe.pipe_id)

    print(f"Speech Pipe created: {pipe.pipe_id}")
    print(f"Number: {numbers[0].number if numbers else 'none assigned'}")

asyncio.run(setup())
```

Then start your runner in a separate process:

```python theme={null}
async def entrypoint(ctx: CallContext) -> None:
    ctx.session.dialog_machine = LangChainAdapter(your_chain)
    await ctx.session.run()

AgentRunner(entrypoint=entrypoint, agent_id="my-agent").start()
```

## Environment Variables

| Variable                 | Required | Description                                                                                                                                                   |
| ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `UNPOD_API_KEY`          | Yes      | Direct-mode Bearer key. **Required by the `AgentRunner`** (orchestrator connection); also the management-client fallback when `UNPOD_PLATFORM_TOKEN` is unset |
| `UNPOD_PLATFORM_TOKEN`   | No       | Backend-core DRF token — enables management **proxy mode** (preferred for the `AsyncClient`/`Client`). Falls back to `UNPOD_API_KEY` if unset                 |
| `UNPOD_ORG_HANDLE`       | No       | Org handle sent as the `Org-Handle` header alongside `UNPOD_PLATFORM_TOKEN` (required for org-scoped / telephony endpoints)                                   |
| `UNPOD_BASE_URL`         | No       | Single shared endpoint. REST derives `https://<host>/platform` and the runner derives `wss://<host>`                                                          |
| `UNPOD_SERVICE_BASE_URL` | No       | Management REST override only. Takes precedence over `UNPOD_BASE_URL` when set                                                                                |
| `UNPOD_ORCHESTRATOR_URL` | No       | Runner WebSocket override only. Takes precedence over `UNPOD_BASE_URL` when set                                                                               |
