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

# PatterTool — phone as a tool

> Wrap a Patter instance so external agents (LangChain, OpenAI Assistants, Anthropic Claude, Hermes, MCP) can place real phone calls as a single tool invocation.

# PatterTool

`PatterTool` exposes a live `Patter` instance as a single **`make_phone_call`** tool that any text-based agent framework can register and dispatch. The agent picks up the phone, Patter runs a short conversation against the caller, and the tool returns a JSON envelope with the call ID, status, transcript, cost, and metrics.

This complements the **bring-your-own-agent** pattern (`serve(on_message=...)`) with the **inverse pattern** — phone-as-tool — exposing any Patter-built voice agent as an MCP-compatible tool that other agent frameworks can call as if it were a local function.

| Pattern                                         | Where the brain lives       | Where Patter sits                | Use this when…                                                                                                                                      |
| ----------------------------------------------- | --------------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **A — Bring-your-own agent** (HTTP/WS endpoint) | Customer's existing service | Patter is STT + LLM proxy + TTS  | Customer already runs a voice agent and wants to swap the voice transport but keep their conversation logic. Use `serve(on_message='https://...')`. |
| **B — Phone as a tool** (this page)             | Customer's text-based agent | Patter is a tool the agent calls | Customer's agent is text-driven but needs to make phone calls during a conversation.                                                                |

## Quickstart

```python theme={null}
import asyncio
from getpatter import Patter, Twilio, DeepgramSTT, AnthropicLLM, ElevenLabsTTS, PatterTool

phone = Patter(
    carrier=Twilio(),
    phone_number="+15550001234",
    webhook_url="api.example.com",          # stable hostname — not a tunnel
)

tool = PatterTool(
    phone=phone,
    agent={
        "stt": DeepgramSTT(),
        "llm": AnthropicLLM(),
        "tts": ElevenLabsTTS(voice_id="rachel"),
    },
)

async def main():
    await tool.start()                       # boots phone.serve() once (idempotent)

    result = await tool.execute({
        "to": "+15551234567",
        "goal": "Book a haircut for tomorrow at 3 pm.",
    })
    print(result)                            # PatterToolResult
    # → call_id, status, duration_seconds, cost_usd, transcript, metrics

asyncio.run(main())
```

## Schema exporters

`PatterTool` ships three schema exporters with identical wire shape (parameter JSON-schema + result envelope), so a customer can switch frameworks without re-mapping fields.

```python theme={null}
tool.openai_schema()      # { "type": "function", "function": { "name", "description", "parameters" } }
tool.anthropic_schema()   # { "name", "description", "input_schema" }
tool.hermes_schema()      # { "name", "description", "parameters" }   # same shape as Anthropic input_schema
```

For [Hermes Agent](https://hermes-agent.nousresearch.com), there's a one-line registry helper:

```python theme={null}
tool.register_hermes(registry, toolset="patter")
```

## Tool arguments (JSON-schema)

Identical across all three exporters:

| Field              | Type    | Required | Notes                                     |
| ------------------ | ------- | -------- | ----------------------------------------- |
| `to`               | string  | ✓        | E.164 phone number                        |
| `goal`             | string  | —        | Becomes the in-call agent's system prompt |
| `first_message`    | string  | —        | First thing the agent speaks on answer    |
| `max_duration_sec` | integer | —        | Hard timeout, default `180`, max `1800`   |

## Result envelope

```python theme={null}
@dataclass(frozen=True)
class PatterToolResult:
    call_id: str
    status: str                  # "completed" | "no-answer" | "busy" | "failed" | "timeout"
    duration_seconds: float
    cost_usd: float
    transcript: list[dict]       # [{"role": "agent" | "user", "text": "..."}]
    metrics: dict                # { p95_latency_ms, cost: { stt, tts, llm, telephony } }
```

When the model framework expects a JSON string (e.g. Hermes), use `tool.hermes_handler()` — it returns exactly that and wraps errors as `{"error": "..."}`.

## Concurrency & timeouts

* `start()` is idempotent — call it from your bootstrap, or let `execute()` boot it lazily.
* Concurrent `execute()` calls are serialised through an `asyncio.Lock` so the per-`call_id` Future never races.
* `max_duration_sec` is enforced by `asyncio.wait_for`; on timeout the tool hangs up the call and returns `status="timeout"`.

## Production deployment

`PatterTool` boots `phone.serve()` once. Make sure the `Patter` instance was constructed with a **stable webhook hostname** in `webhook_url` — never a tunnel — because Twilio/Telnyx need a long-lived HTTPS URL.

For local development, use `tunnel=True` on the `Patter` constructor and let it spawn a cloudflared. For production deploys (Fly.io / Cloud Run / Fargate behind ALB), set `webhook_url` to your public hostname and disable the tunnel.

## Examples

Runnable integration examples live in their own repo (see the [Patter examples organization](https://github.com/PatterAI)):

* `hermes_phone_tool.py` — drop-in `tools/patter.py` for Hermes Agent.
* `openai_assistant_phone_tool.ts` — minimal OpenAI Assistants run dispatching the tool.
* Pattern A vs Pattern B decision matrix in the example repo's README.

## What's next

<CardGroup cols={2}>
  <Card title="Tools" icon="wrench" href="/python-sdk/tools">In-call tool calling (function calling within a Patter agent).</Card>
  <Card title="Agents" icon="robot" href="/python-sdk/agents">Configure the in-call agent that PatterTool wraps.</Card>
</CardGroup>
