# Мини-проект: бот поддержки интернет-магазина

Курс: Claude API для разработчиков — https://zero2claude.ru/learn/api
Канонический URL: https://zero2claude.ru/learn/api/3-4-mini-proekt-bot

Бот поддержки магазина из system prompt, tool use и обработки ошибок: рабочий сценарий ответа на вопрос о заказе.

Соберём всё вместе: бот поддержки, который отвечает на «где мой заказ?». Три кирпича — **роль в system**, **инструмент** для данных, **обработка ошибок**.

## 1. Роль и правила в system

System-промпт задаёт характер бота и рамки: тон, что можно, чего нельзя. Именно он превращает «универсальную модель» в «вежливого оператора магазина».

## 2. Инструмент для реальных данных

Модель не знает статус заказа — у неё нет твоей базы. Даём ей инструмент: она попросит вызвать его, ты выполнишь функцию у себя и вернёшь результат.

```python
tools = [{
    "name": "get_order_status",
    "description": "Статус заказа по номеру. Вызывай, когда клиент спрашивает о своём заказе.",
    "input_schema": {
        "type": "object",
        "properties": {"order_id": {"type": "string"}},
        "required": ["order_id"],
    },
}]

resp = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    system="Ты — оператор поддержки магазина. Вежливо, по делу. Статусы заказов бери только из инструмента, не выдумывай.",
    tools=tools,
    messages=[{"role": "user", "content": "Где заказ 4821?"}],
)
```

Если `stop_reason == "tool_use"`, в ответе будет блок `tool_use` с `id`, `name` и `input`. Выполняешь функцию и шлёшь результат обратно — **новым user-сообщением** с блоком `tool_result`:

```python
messages.append({"role": "assistant", "content": resp.content})
messages.append({"role": "user", "content": [{
    "type": "tool_result",
    "tool_use_id": tool_block.id,
    "content": "Заказ 4821: в пути, доставка завтра",
}]})
final = client.messages.create(model="claude-opus-4-8", max_tokens=1024,
                               system="...", tools=tools, messages=messages)
```

## 3. Ошибки

Оборачивай вызовы в try/except: 400 — чинить, 429/5xx — SDK ретраит сам. API без состояния — всю историю `messages` (включая `tool_use` и `tool_result`) шлёшь заново на каждом шаге.

## Порепетируй

Попробуй сам: один и тот же вопрос клиента, но с разным system-промптом — и почувствуй, как меняется ответ.

System задаёт характер, инструмент даёт факты, обработка ошибок держит бота на ногах. Это и есть скелет любого продакшен-сценария.
