# pillar-sdk

Python backend SDK for [Pillar](https://trypillar.com) — register server-side tools and handle tool calls from Pillar Cloud.

## Install

```bash
pip install pillar-sdk
```

## Quick start

```python
from pillar import Pillar, ToolContext

pillar = Pillar(secret="plr_...")

@pillar.tool(description="Look up a customer by email")
async def lookup_customer(email: str, ctx: ToolContext) -> dict:
    customer = await db.get_customer(email=email)
    return {"name": customer.name, "plan": customer.plan}
```

## Framework integration

### Django

```python
# urls.py
from myapp.pillar_tools import pillar

urlpatterns = [
    path("pillar/", pillar.django_view()),
]
```

### Flask

```python
from myapp.pillar_tools import pillar

app.route("/pillar", methods=["POST"])(pillar.flask_handler())
```

### Standalone

```python
pillar.serve(port=8787)
```

## Confirmation responses

When a tool needs user confirmation before performing an action, return a `ConfirmationResponse` from your handler. Pillar renders a channel-appropriate confirmation UI and re-calls your handler with `ctx.confirmed = True` after the user confirms.

```python
from pillar import Pillar, ToolContext, ConfirmationResponse

pillar = Pillar(secret="plr_...")

@pillar.tool(description="Create a new plan")
async def create_plan(name: str, price: float, ctx: ToolContext) -> dict:
    if not ctx.confirmed:
        return ConfirmationResponse(
            confirmation_required=True,
            title="Create plan",
            message=f'Create "{name}" at ${price}/mo?',
            details={"Plan name": name, "Price": f"${price}/mo"},
            confirm_payload={"name": name, "price": price},
        )

    await db.create_plan(name=name, price=price)
    return {"created": True}
```

### ConfirmationResponse fields

| Field | Required | Description |
|---|---|---|
| `confirmation_required` | yes | Must be `True`. |
| `title` | no | Short headline. Defaults to the tool name. |
| `message` | no | One-line description shown before the buttons. |
| `details` | no | Key-value pairs rendered as a summary card. |
| `confirm_payload` | no | Opaque data passed back to your handler on confirm. Defaults to the original arguments. |

### ToolContext

| Field | Type | Description |
|---|---|---|
| `caller` | `CallerInfo` | Identity and channel metadata for the user. |
| `conversation_id` | `str` | Current conversation ID. |
| `call_id` | `str` | Unique ID for this tool call. |
| `product_id` | `str \| None` | Product ID, if applicable. |
| `confirmed` | `bool` | `True` when re-executing after user confirmation. |
| `is_identified` | `bool` | `True` when the caller has a resolved external user ID. |
