# Runbook — Lead Qualification Agent

**Client:** Apex Marketing Agency  
**Platform:** N8N  

---

## Overview

This automation runs **Lead Qualification Agent** on N8N. When the trigger fires it runs 5 step(s) — 2 of them powered by Claude — and delivers the result to HubSpot CRM + Slack #leads channel. It runs unattended; your team only steps in for the reply/exception paths and the checks below.

## Trigger — How Work Enters the Automation

**Event:** HTTP POST from external service (form, CRM event, ad platform)  
**Source:** Typeform — new lead form submission  

**Required input fields:**

| Field | Required | Notes |
|-------|----------|-------|
| `name` | Recommended |  |
| `email` | Yes |  |
| `company` | Recommended |  |
| `use_case` | If used |  |
| `budget` | Recommended |  |
| `timeline` | If used |  |

## Step-by-Step Operation

### Step 1 — Extract Contact Info  (`llm_call`)

Runs prompt `extract` (claude-haiku-4-5) and returns json (name, email, company, use_case, budget, timeline).  
_Data: form_payload → contact_json_

### Step 2 — Score Lead  (`llm_call`)

Runs prompt `score` (claude-haiku-4-5) and returns json (score, tier, reason).  
_Data: contact_json, use_case, budget → score_json_

### Step 3 — Route by Score  (`conditional`)

Branches on `score_json.tier == 'high'`.  
_Data: score_json → routed_

### Step 4 — Create HubSpot Contact  (`api_call`)

HubSpot: create_contact  
_Data: contact_json, score_json → crm_id_

### Step 5 — Slack Alert — High Score  (`notification`)

Slack: post_message  
_Data: contact_json, score_json → —_

## Field Maps — Connected Systems

| Tool | Action | Auth |
|------|--------|------|
| HubSpot | create_contact | api_key |
| Slack | post_message | oauth |
| Typeform | webhook_trigger | webhook_secret |

## Failure & Alert Paths

- **LLM API timeout or rate-limit** → Retry up to 3 times with exponential backoff; alert on final failure.
- **Invalid or empty LLM output (output does not match expected format)** → Log raw output; route to human review queue; send Slack/email alert.
- **External API call fails (non-2xx response)** → Catch error, log payload, notify team, halt step (do not skip silently).
- **Missing required input field** → Halt workflow; return error to trigger source with field name.

## What to Monitor

- LLM output quality — spot-check that each Claude step still returns the expected format on a few real records.
- Latency — execution time per run stays within the acceptance bar (Haiku < 5s, Sonnet/Opus < 15s per LLM step).
- LLM cost/token spend — watch for prompt drift or oversized inputs inflating token usage.
- Integration health — CRM/Slack/API steps returning 2xx, no silent skips.
- Human-review queue — items routed there on invalid output are being actioned, not piling up.

## Routine Maintenance

- [ ] Review the execution log for failed or retried runs.
- [ ] Confirm every LLM step's output still parses (schema hasn't drifted).
- [ ] Check the error-alert channel is still receiving test alerts.
- [ ] Re-run any runs that halted on an external API failure.

## Updating the Automation

- **To change what a Claude step does:** edit its prompt in `prompt_registry.md`, update the node's system/user text in the tool, and re-run the acceptance checks for that step before go-live.
- **To add a step:** add it to the process map, register any new prompt, then extend the acceptance checklist.
- **To pause:** disable the trigger in the platform — in-flight runs finish, no new runs start.
- **Never** edit a live prompt without re-running its acceptance check — a bad prompt fails silently on real data.

## Ongoing Support

Ongoing maintenance covers: prompt updates as your ICP/offer/process changes, adding new steps as the workflow grows, monitoring execution logs and LLM output quality, tuning alerts, and latency/cost optimization.