---
name: ghl-automation
description: Audit, build, and edit GoHighLevel (GHL) subaccounts through AI Bridge. Purpose-built power modules — Aristotle (workflows), Plato (forms), Daedalus (Vibe / AI Studio code) — plus read-only audit (Socrates), all driven through your local AI Bridge server using the browser session you're already logged into. Use when the user wants to audit a GHL account, build/modify workflows or forms, or read/edit a GHL Vibe site's source.
---

# GHL Automation via AI Bridge

Automate GoHighLevel with any AI agent through the local AI Bridge server. No API
keys to configure — the bridge uses the authenticated session you're already
logged into in Chrome.

## Prerequisites

1. AI Bridge extension installed and the bridge running — see https://ai-bridge.online/docs
2. Logged into GHL (`app.gohighlevel.com` or your white-label domain) in Chrome, so
   the bridge captures a session token. Navigate around once to trigger capture.
3. Bridge reachable at `http://127.0.0.1:9124`; key in `~/.ai-bridge/key`
   (sent as the `X-Bridge-Key` header).

Verify first:
```bash
curl http://127.0.0.1:9124/health          # active_tokens should be non-empty
```

## The one rule: pick the right tool

Work down this ladder. Don't start at the bottom.

1. **Structured GHL / Vibe op** (workflow, form, AI-Studio code) -> use a **power
   module** via `POST /skill/{name}` (below). These call GHL's internal API through
   your captured token and are far more reliable than the UI, because the GHL
   builders are cross-origin iframes that DOM automation can't reach.
2. **General page, no module fits** -> browser-use tools: `POST /tab/action`
   `{action:"tree"}` to see numbered elements, then `click` / `type` / `read`.
3. **You need a site's API but don't know the shape** -> **deep-capture**: do the
   action once in the UI, read what the browser sent via `GET /requests` (or
   `GET /cdp/requests` for full bodies), then call it directly with `/proxy`.

## Power modules — `POST /skill/{name}` (body = kwargs)

Bundled in the bridge, so no local Python setup. Also exposed as MCP tools
(`ghl_build_workflow`, `ghl_build_form`, `vibe_edit_code`, ...) via the bridge's
MCP server for Claude Desktop / Cursor / Cline.

### Aristotle — workflows

```bash
curl -X POST http://127.0.0.1:9124/skill/workflow_build -H "X-Bridge-Key: $(cat ~/.ai-bridge/key)" \
  -d '{"name":"New Lead Follow-up","location_id":"LOC","steps":[
        {"type":"add_contact_tag","attrs":{"tags":["new-lead"]}},
        {"type":"wait","attrs":{"duration":1,"unit":"hours"}},
        {"type":"email","name":"Welcome","attrs":{"subject":"Hi","body":"..."}}
      ]}'
```
Step types: `add_contact_tag, remove_from_workflow, create_opportunity,
add_to_workflow, create_update_contact, assign_user, internal_notification,
email, sms, call, voicemail, webhook, wait, if_else` (branches go in
`children:[{branch_name, steps:[...]}]`). Other skills: `workflow_list`,
`workflow_read`, `workflow_update`, `workflow_publish`.

**Triggers are a known gap.** In the GHL v2 builder, triggers are **not** part of
the REST workflow object — they persist to Firestore, and a plain workflow PUT
silently drops them. Build the workflow body with Aristotle, then set the trigger
in the UI, or deep-capture the trigger save and replay it. Don't invent a trigger
payload; it won't stick.

### Plato — forms

```bash
curl -X POST http://127.0.0.1:9124/skill/form_build -H "X-Bridge-Key: $(cat ~/.ai-bridge/key)" \
  -d '{"name":"Intake","location_id":"LOC","fields":[
        {"type":"full_name"},{"type":"email"},{"type":"phone"},
        {"type":"textarea","label":"How can we help?"}]}'
```
Field types: `full_name, email, phone, date, address, header, textarea,
single_line, submit`. Custom fields (textarea/single_line) are materialized
automatically; a submit button is appended if omitted. Other skills: `form_list`,
`form_read`.

### Daedalus — GHL Vibe / AI Studio code

Read and write a Vibe site's React/Vite source **via its internal API** — no
clicking inside the editor iframe (cross-origin, can't be automated). GHL bills
these as manual edits, so they burn no AI credits.

```bash
curl -X POST http://127.0.0.1:9124/skill/vibe_edit_code -H "X-Bridge-Key: $(cat ~/.ai-bridge/key)" \
  -d '{"project_id":"PID","changes":[{"path":"src/App.tsx","content":"..."}],"commit_message":"..."}'
```
Skills: `vibe_list_files`, `vibe_read_file`, `vibe_get_routes`, `vibe_edit_code`
(returns a `version_id` you can restore). `project_id`/`location_id` come from the
editor URL.

**Gotchas:** `edit-code` does **not** auto-publish — going live needs a manual
**Publish** in the editor. A write can `403` "token not valid" if the Vibe token is
stale; fix by reloading the GHL tab (or typing in the Vibe chat) to mint a fresh
one, then retry — **do not blind-retry** (the bridge will cascade every token and
hammer GHL). Verify a publish against a path that existed **before** your edit, not
a brand-new one (new paths bypass the CDN cache and give false positives).

## Socrates — read-only audit

Audit a subaccount and produce a report. **Never writes.** Use `skill/workflow_list`
+ `form_list` and `/proxy` GETs to read Workflows · Funnels · Pipelines · Forms ·
Calendars · Contacts · Email templates. Output: account overview -> per-area counts
-> issues (prioritized by severity) -> actionable recommendations.

## Calling internal endpoints directly — `POST /proxy`

For anything without a purpose-built skill:
```json
{ "url": "https://…", "method": "GET|POST|…", "headers": { }, "body": { }, "use_token": true }
```
`use_token:true` injects the freshest captured Bearer and retries across cached
tokens (and a forced refresh) on 401/403.

### Deep capture (for iframe / WebSocket / Firestore builders)

When a modern builder uses WebSockets, cross-origin iframes, or Firestore, normal
request capture won't show the payload. Then:
1. Ask the user to enable **Deep Capture (CDP)** in the side panel.
2. Ask them to perform the save action manually.
3. Read the raw traffic: `GET /cdp/requests` (full bodies) or `GET /ws-frames`.
4. Reverse-engineer the payload and replay it via `/proxy`.

## Safety

- Writing to a live client site or workflow is a **real change**. Show the exact
  diff/plan and get explicit sign-off; keep any returned `version_id` to revert.
- Session tokens last roughly an hour — check `/health` before a write rather than
  reusing whatever worked earlier.
- Never invent IDs, tokens, sub-accounts, or sender addresses — read them.

---

*Bonus skill included with your AI Bridge license · https://ai-bridge.online*
