# StarAgent

StarAgent is a phone layer for small businesses. It provisions a Twilio number, handles missed-call greetings and voicemail, transcribes or extracts structured fields from audio, and can notify external systems over HTTP.

Use this file as a quick integration map. The product site is https://staragent.io .

## Human-readable docs

| Topic | URL |
|-------|-----|
| Webhook payload reference (events, fields, examples) | https://staragent.io/docs/webhooks |
| OpenClaw gateway hooks (Bearer auth, `/hooks/agent`) | https://staragent.io/docs/integrations/openclaw |
| NemoClaw tunnel URL and StarAgent Setup | https://staragent.io/docs/integrations/nemoclaw |
| BlueBubbles and managed `bb-*.staragent.io` tunnels | https://staragent.io/docs/integrations/bluebubbles |
| Setup (greeting, voicemail modes, webhooks, SMS) | https://staragent.io/setup |

## Webhook events

StarAgent `POST`s JSON to the business-configured URL when webhooks are enabled in Setup.

1. **`incoming_call`** — Fires when a call hits the Twilio number (new call row). Includes caller id and carrier metadata when available.
2. **`voicemail`** — Fires after a recording is processed. Includes transcription (or extract/prompt output), signed recording URL, duration, and mode.

Correlate rows with **`call_id`** (StarAgent id) and **`call_sid`** (Twilio).

## Standard JSON payload (default)

- Content-Type: `application/json`
- No auth header unless the business saved an optional **hook secret** (then `Authorization: Bearer <secret>`).

Voicemail payloads may include:

- **`extracted_fields`** — Object whose keys are lowercased labels from `Label: value` lines in the transcript (extract mode). Omitted when empty.
- **`inferred_contact`** — `{ name, email, phone }` best-effort from transcript + extraction. Omitted when all null.

Full field list and examples: https://staragent.io/docs/webhooks

## OpenClaw and similar agent gateways

When the business selects **OpenClaw gateway** format in Setup, StarAgent posts to the URL they provide (typically ending in **`/hooks/agent`**) a body shaped for OpenClaw:

- `message` (string): Human-readable summary built from the StarAgent payload (event type, business, caller, transcript, extracted fields when present).
- `name`: `"StarAgent"`
- `wakeMode`: `"now"`
- `deliver`: `false`

Auth: **`Authorization: Bearer <hooks.token>`** using the same value as OpenClaw `hooks.token`. Query-string tokens are not supported by OpenClaw; use the header.

Upstream reference: https://docs.openclaw.ai/automation/webhook

## NemoClaw

If the gateway runs inside [NemoClaw](https://github.com/NVIDIA/NemoClaw), run `nemoclaw start` so cloudflared exposes a public HTTPS URL to the local gateway. Use that host with path **`/hooks/agent`** as the StarAgent webhook URL. Details: https://staragent.io/docs/integrations/nemoclaw

## Managed hostnames (Cloudflare Tunnel)

StarAgent uses **Cloudflare Tunnel** (`cloudflared`) for managed hostnames because it gives you HTTPS and a stable DNS name without opening inbound ports on your router. The connector only makes an **outbound** connection from your computer to Cloudflare.

### `oc-*.staragent.io` (OpenClaw gateway)

In **Setup**, with webhooks set to **OpenClaw gateway**, you can choose **Create stable hostname**. StarAgent provisions `https://oc-<words>.staragent.io` and routes it to **`http://localhost:18789`** on the machine where you run the install command. Your webhook endpoint is **`https://oc-<words>.staragent.io/hooks/agent`** (use **Fill endpoint URL** in Setup or paste manually). The tunnel local port defaults to **18789**; StarAgent operators can override it for all tenants with server env **`OPENCLAW_GATEWAY_TUNNEL_LOCAL_PORT`**.

### `bb-*.staragent.io` (BlueBubbles only)

When you enable **BlueBubbles**, StarAgent can provision `https://bb-<words>.staragent.io`, which forwards to **`http://localhost:1234`**. That is **not** the OpenClaw hook URL unless you have reconfigured routing yourself. BlueBubbles setup: https://staragent.io/docs/integrations/bluebubbles

You can still use any other public URL for OpenClaw (NemoClaw quick tunnel, your own tunnel, Tailscale, a VPS) if you prefer not to use managed `oc-*`.

For **standard JSON** into OpenClaw instead, keep payload format on “Standard JSON” and use OpenClaw `hooks.mappings` or middleware to transform the body.

## Operational constraints

- Webhooks are fire-and-forget; **retries are not implemented**. Consumers should be idempotent where possible (key on `call_id` + `event`).
- **`incoming_call`** is only sent when **webhooks are enabled** and a URL is set (same gate as voicemail dispatch).
- Recording URLs in payloads are **signed** and stable; they point at StarAgent’s recording API.

## Source code pointers (this repository)

| Area | Path |
|------|------|
| Webhook types, OpenClaw message builder, dispatch | `lib/webhook.ts` |
| Label/value parsing for `extracted_fields` | `lib/transcription-parse.ts` |
| Voicemail pipeline (transcribe, metadata, webhook) | `app/api/twilio/recording-status/route.ts` |
| Incoming call webhook | `app/api/twilio/incoming-call/route.ts` |
| Test webhook from dashboard setup | `app/api/webhooks/test/route.ts` |
| Business settings (URL, format, bearer, managed OpenClaw tunnel) | `prisma/schema.prisma` (`Business.webhookUrl`, `webhookEnabled`, `webhookPayloadFormat`, `webhookBearerToken`, `openClawGateway*`) |

## Where this file lives

- **Repository:** `public/llm.md` (also linked from the repo root as `llm.md` so it shows next to README).
- **Production:** https://staragent.io/llm.md (static file) for agents that fetch one URL.
