Skip to content
reaatechREAATECH

Files · Vertex AI Multi-Agent Handoff for ServiceTitan Dispatch Automation

69 (1 binary, 691.5 kB total)attempt 2

README.md·4512 B·markdown
markdown
# Vertex AI Multi-Agent Handoff for ServiceTitan Dispatch Automation
 
> An AI dispatch mesh that runs `classify → confidence gate → route → dispatch` to triage field service requests, schedule appointments, and assign technicians in ServiceTitan via REST, reducing manual coordination.
 
A tutorialized reference solution from [reaatech.com](https://reaatech.com), demonstrating how to build production-grade AI systems with the `@reaatech/*` package family.
 
## Architecture
 
```
Webhook → Intake Agent (classify) → Confidence Gate → Dispatch Agent → ServiceTitan API
```
 
The multi-agent mesh uses **Vertex AI** (Gemini) for natural language understanding to classify incoming service requests via `@reaatech/agent-mesh-classifier`. Classified requests are routed through a **confidence gate** (`@reaatech/agent-mesh-confidence`) that decides whether to route directly to the dispatch agent, ask for clarification, or fall back to a default handler. Stateful transfers between agents are managed by `@reaatech/agent-handoff-routing`. The dispatch agent reads/writes job data through ServiceTitan's REST API (OAuth2).
 
## Prerequisites
 
- **Node.js** >= 22
- **pnpm** 10.x
- **Google Cloud** project with Vertex AI API enabled
- **ServiceTitan** tenant with API credentials (OAuth2 client_credentials)
 
## Quick start
 
```bash
pnpm install
cp .env.example .env        # fill in your GCP + ServiceTitan + Langfuse credentials
pnpm dev                    # starts Next.js dev server
```
 
## API endpoints
 
| Method | Path | Description |
|--------|------|-------------|
| `POST` | `/api/webhook` | Accepts a service request JSON body (`{ raw_input: string }`), classifies it, optionally dispatches a technician, returns a decision |
| `GET`  | `/api/dispatch` | Returns dispatch job status given `?jobId=<id>` |
 
## Agent mesh flow
 
1. **Intake classification**`@reaatech/agent-mesh-classifier` classifies raw input against an agent registry (intake, dispatch)
2. **Confidence gating**`evaluateConfidenceGate` applies a 6-rule decision tree: unknown agent → default, default agent → route, session bypass → route, sufficient confidence → route, clarification enabled → clarify, otherwise → fallback
3. **Handoff routing**`@reaatech/agent-handoff-routing` selects the optimal agent using weighted scoring (skill match 40%, domain match 30%, load factor 20%, language match 10%)
4. **Dispatch execution** — The dispatch agent queries ServiceTitan for available technicians, validates scheduling constraints, and creates a job
 
## Environment variables
 
| Variable | Description |
|---|---|
| `GOOGLE_CLOUD_PROJECT` | GCP project ID for Vertex AI |
| `GOOGLE_CLOUD_LOCATION` | GCP region for Vertex AI (e.g., us-central1) |
| `GOOGLE_APPLICATION_CREDENTIALS` | Path to GCP service account JSON |
| `SERVICETITAN_CLIENT_ID` | ServiceTitan OAuth2 client ID |
| `SERVICETITAN_CLIENT_SECRET` | ServiceTitan OAuth2 client secret |
| `SERVICETITAN_TENANT_ID` | ServiceTitan tenant identifier |
| `SERVICETITAN_API_BASE_URL` | ServiceTitan API base URL |
| `LANGFUSE_PUBLIC_KEY` | Langfuse public key for tracing |
| `LANGFUSE_SECRET_KEY` | Langfuse secret key for tracing |
| `LANGFUSE_BASE_URL` | Langfuse host URL |
 
## Testing
 
```bash
pnpm test            # vitest run with coverage
pnpm typecheck       # tsc --noEmit
pnpm lint            # eslint .
```
 
All tests mock externals via `msw` (HTTP) and `vi.mock` (package-level). No live API calls during tests.
 
## Project layout
 
```
app/                  Next.js App Router pages + API routes
src/
  ├── agents/         Intake and dispatch agents
  ├── integration/    ServiceTitan REST client
  ├── lib/            LLM adapter, env config
  ├── mesh.ts         Orchestrator
  ├── observability.ts Langfuse tracing
  └── types/          Shared types and schemas
tests/                vitest suite (mirrors src/)
  ├── setup.ts        MSW server + global mocks
  ├── types.test.ts
  ├── env.test.ts
  ├── llm.test.ts
  ├── servicetitan.test.ts
  ├── intake.test.ts
  ├── dispatch.test.ts
  ├── mesh.test.ts
  ├── handoff-routing.test.ts
  ├── webhook.test.ts
  ├── dispatch-api.test.ts
  ├── observability.test.ts
  └── index.test.ts
packages/             API references for every dependency (read these first)
DEV_PLAN.md           build plan for this recipe
```
 
## License
 
MIT — see [LICENSE](./LICENSE).