# Project export: Negotiator AI

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: OpenAI Build Week
- Tagline: Negotiator AI is an autonomous agent that discovers local vendors, places live conversational phone calls, extracts itemized prices, and negotiates binding price discounts using AI leverage strategies
- Devpost: https://devpost.com/software/negotiator-ai
- GitHub: https://github.com/gargieesingh/NegotiatorAI
- Demo: https://negotiator-ai-pied.vercel.app/
- Video: https://www.youtube.com/embed/GJPLVQ_692s?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 2 GitHub contributor(s) — gargieesingh (31 commits), harshsinghsv (16 commits)

## Devpost submission (written by the team)

### Overview

The problem Getting a fair price should not require becoming a part-time procurement specialist. Yet hiring a contractor, buying a laptop, planning a wedding, or sourcing a business service often means chasing vendors, repeating the same brief, comparing vague totals, and hoping the lowest number does not hide the most expensive surprise. Negotiator AI is a voice-first procurement agent that turns that messy process into one auditable workflow: discover relevant local businesses, call approved contacts, turn spoken answers into comparable quotes, and use verified pricing as negotiation leverage. What we built A user can describe a need by voice or upload an existing quote, invoice, PDF, or PNG. Negotiator AI then: Builds one locked brief - captures the requirements that every vendor should receive so the comparison stays fair. Discovers local options - searches Google Places for nearby businesses, including address, rating, maps link, and business phone data. Runs live outbound conversations - uses ElevenLabs Conversational AI and Twilio to contact approved, consented demo participants for a real phone-call experience. Tracks real call outcomes - distinguishes calling, processing a completed call, no answer, a documented decline, and a quote received. Creates evidence-backed quote records - extracts only amounts explicitly spoken in the transcript, flags missing terms, and keeps the transcript beside the resulting quote. Finds negotiation leverage - selects the lowest comparable verified quote and uses it to request a price match or measurable added value from the higher-priced vendor. Produces an executive comparison - presents line items, totals, terms, red flags, and savings in one decision-ready report. For the live demo, calls are deliberately limited to three verified, consented participants. That keeps the experience safe and testable while showing the same orchestration pattern a production, user-approved vendor-calling workflow would use. Why Codex and GPT-5.6 mattered Codex was not a one-time autocomplete tool for this project. It was the engineering partner that let us turn a deceptively simple idea - “call multiple vendors and compare prices” - into a real, failure-aware system. Using Codex with GPT-5.6, we designed and implemented: the Next.js App Router API surface for discovery, call initiation, call status, webhooks, negotiation, and reporting; the TypeScript domain model that preserves a locked job brief, call state, transcript, quote, leverage, and audit output; the event-driven call lifecycle that reconciles Twilio telephony state with ElevenLabs post-call transcripts; durable cross-instance call storage for serverless deployment, so a webhook can update the same call that initiated in a different function instance; guardrails that prevent invented prices: quotes only use values stated in the source transcript, and incomplete calls remain declines rather than fabricated estimates; the responsive six-vendor discovery and three-call experience, including explicit Not picked up and Processing quote states. GPT-5.6 was especially valuable for reasoning across these connected constraints: asynchronous webhooks, serverless persistence, telephony failure states, and a UI that must remain honest when a vendor does not answer or a transcript is delayed. Codex accelerated implementation, but every workflow was reviewed, tested, and shaped around the real system behavior.

### How we built it

Product and frontend: Next.js 16, React 19, TypeScript, Tailwind CSS Voice and telephony: ElevenLabs Conversational AI and Twilio outbound calling Discovery: Google Places API (New Text Search) Quote intelligence: structured transcript normalization with evidence constraints Reporting: GPT 5.6-generated executive report from the collected quote and negotiation data Reliability: Redis-compatible durable state for webhooks and serverless status polling The hard parts Voice calls do not end when the UI thinks they do A phone can ring forever, go unanswered, be cut short, or finish while its transcript is still being processed. We had to model those states separately. The interface now stops pretending every call is active: Twilio status reconciliation surfaces Not picked up and Processing quote, while the transcript webhook supplies the final evidence. “A price” is not a comparable quote A vendor saying one number is not enough. We needed scope, fees, validity, binding terms, and exclusions. The system treats absent details as absent details. It does not fill the gap with an AI guess. Serverless webhooks need durable memory An outbound call can begin in one Vercel function and finish in another. In-memory state loses that connection. We added durable call records keyed by the internal call ID and provider conversation identifiers so callbacks can recover the right quote workflow.

### What we learned

The most exciting lesson was that useful agents are not just chat interfaces with a phone number. They need a trustworthy state machine, evidence boundaries, graceful failure handling, and a product experience that explains uncertainty instead of hiding it. Negotiator AI is our answer to a practical question: what if everyone had a procurement officer that could do the calling, keep the receipts, and still let the human make the final decision?

## README (from the GitHub repository)

# Negotiator AI
<img width="1324" height="493" alt="image" src="https://github.com/user-attachments/assets/514abc98-fdae-49ba-a3e5-cf9b35ef11f9" />


> **Autonomous AI Procurement & Price Negotiation Agent** Built for the OpenAI Hackathon.
>
> Negotiator AI delegates your vendor outreach, price comparisons, and rate negotiations to AI. Describe your service scope or attach a quote; our autonomous agent discovers local service providers via Google Places, places real conversational phone calls with ElevenLabs AI, extracts itemized pricing, and negotiates binding deals using AI leverage strategies.
> 
>[Visit Site](https://negotiator-ai-pied.vercel.app/report)
---

## The problem

Getting a fair price should not require becoming a part-time procurement specialist. Yet hiring a contractor, buying a laptop, planning a wedding, or sourcing a business service often means chasing vendors, repeating the same brief, comparing vague totals, and hoping the lowest number does not hide the most expensive surprise.

**Negotiator AI is a voice-first procurement agent that turns that messy process into one auditable workflow:** discover relevant local businesses, call approved contacts, turn spoken answers into comparable quotes, and use verified pricing as negotiation leverage.

## What we built

A user can describe a need by voice or upload an existing quote, invoice, PDF, or PNG. Negotiator AI then:

1. **Builds one locked brief** - captures the requirements that every vendor should receive so the comparison stays fair.
2. **Discovers local options** - searches Google Places for nearby businesses, including address, rating, maps link, and business phone data.
3. **Runs live outbound conversations** - uses ElevenLabs Conversational AI and Twilio to contact approved, consented demo participants for a real phone-call experience.
4. **Tracks real call outcomes** - distinguishes calling, processing a completed call, no answer, a documented decline, and a quote received.
5. **Creates evidence-backed quote records** - extracts only amounts explicitly spoken in the transcript, flags missing terms, and keeps the transcript beside the resulting quote.
6. **Finds negotiation leverage** - selects the lowest comparable verified quote and uses it to request a price match or measurable added value from the higher-priced vendor.
7. **Produces an executive comparison** - presents line items, totals, terms, red flags, and savings in one decision-ready report.

For the live demo, calls are deliberately limited to three verified, consented participants. That keeps the experience safe and testable while showing the same orchestration pattern a production, user-approved vendor-calling workflow would use.

## Why Codex and GPT-5.6 mattered

Codex was not a one-time autocomplete tool for this project. It was the engineering partner that let us turn a deceptively simple idea - “call multiple vendors and compare prices” - into a real, failure-aware system.

Using Codex with GPT-5.6, we designed and implemented:

- the Next.js App Router API surface for discovery, call initiation, call status, webhooks, negotiation, and reporting;
- the TypeScript domain model that preserves a locked job brief, call state, transcript, quote, leverage, and audit output;
- the event-driven call lifecycle that reconciles Twilio telephony state with ElevenLabs post-call transcripts;
- durable cross-instance call storage for serverless deployment, so a webhook can update the same call that initiated in a different function instance;
- guardrails that prevent invented prices: quotes only use values stated in the source transcript, and incomplete calls remain declines rather than fabricated estimates;
- the responsive six-vendor discovery and three-call experience, including explicit **Not picked up** and **Processing quote** states.

GPT-5.6 was especially valuable for reasoning across these connected constraints: asynchronous webhooks, serverless persistence, telephony failure states, and a UI that must remain honest when a vendor does not answer or a transcript is delayed. Codex accelerated implementation, but every workflow was reviewed, tested, and shaped around the real system behavior.

## How we built it

- **Product and frontend:** Next.js 16, React 19, TypeScript, Tailwind CSS
- **Voice and telephony:** ElevenLabs Conversational AI and Twilio outbound calling
- **Discovery:** Google Places API (New Text Search)
- **Quote intelligence:** structured transcript normalization with evidence constraints
- **Reporting:** GPT 5.6-generated executive report from the collected quote and negotiation data
- **Reliability:** Redis-compatible durable state for webhooks and serverless status polling

## The hard parts

### Voice calls do not end when the UI thinks they do

A phone can ring forever, go unanswered, be cut short, or finish while its transcript is still being processed. We had to model those states separately. The interface now stops pretending every call is active: Twilio status reconciliation surfaces **Not picked up** and **Processing quote**, while the transcript webhook supplies the final evidence.

### “A price” is not a comparable quote

A vendor saying one number is not enough. We needed scope, fees, validity, binding terms, and exclusions. The system treats absent details as absent details. It does not fill the gap with an AI guess.

### Serverless webhooks need durable memory

An outbound call can begin in one Vercel function and finish in another. In-memory state loses that connection. We added durable call records keyed by the internal call ID and provider conversation identifiers so callbacks can recover the right quote workflow.

## What we learned

The most exciting lesson was that useful agents are not just chat interfaces with a phone number. They need a trustworthy state machine, evidence boundaries, graceful failure handling, and a product experience that explains uncertainty instead of hiding it.

Negotiator AI is our answer to a practical question: **what if everyone had a procurement officer that could do the calling, keep the receipts, and still let the human make the final decision?**

---

## ⚡ Workflow & Architecture

```mermaid
flowchart TD
    A[User Brief: Voice / Text / Doc] --> B[AI Intent & Vertical Classification]
    B --> C[Google Places Vendor Discovery]
    C --> D[Autonomous Outbound AI Dialing]
    D --> E[ElevenLabs Post-Call Transcript Webhook]
    E --> F[AI Line-Item Metric Extraction]
    F --> G[AI Price Match Leverage Strategy]
    G --> H[Executive Evidence Audit Report]
```

1. **Intake (`/`)**: Voice conversation via `InlineVoicePrompt` or document upload (`/api/intake/parse-document`).
2. **Autonomous Stream (`/agent-run`)**: Orchestrates classification, discovery, outbound dialing, metric extraction, leverage calculation, and report generation in a unified stream.
3. **Call Execution (`/calls`)**: Manages batch outbound calls, live audio waveforms, and transcript displays.
4. **Negotiation (`/negotiate`)**: Surfaces calculated price-match leverage strategy, target vs. benchmark quotes, and potential savings.
5. **Executive Report (`/report`)**: Renders audited quote comparisons, verified binding badges, line-item breakdowns, and PDF/export tools.

---

## 🌐 Routes Overview

| Route | Purpose |
| --- | --- |
| `/` | Product landing page with in-place voice assistant & text input. |
| `/agent-run` | End-to-end autonomous agent execution stream. |
| `/discover` | Vendor discovery results powered by Google Places API. |
| `/calls` | Outbound AI call batch manager with live audio spectrum visualizers. |
| `/negotiate` | AI price-matching leverage strategy and savings tracker. |
| `/report` | Cryptographically verified executive quote audit report. |

---

## 🛠️ API Endpoints

| Endpoint | Method | Description |
| --- | --- | --- |
| `/api/verticals/classify` | `POST` | Classifies user prompt into service vertical schemas. |
| `/api/discovery/google-places`

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 155 recognized source files, 642 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- JavaScript (language) — detected in the code
- Next.js (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Node.js (technology) — claimed on Devpost, not found in the code
- Vercel (technology) — claimed on Devpost, not found in the code
- AI coding agent: Codex — evidence: config files committed to the repository

## Codebase structure (from repository index)

### Files (120 of 189)

```
.agents/AGENTS.md
.codex/environments/environment.toml
.env.local.example
.gitignore
components.json
docs/AGENT_RUN_CALLS_METRICS.md
docs/ELEVENLABS_GENERAL_AGENT_SETUP.md
docs/ELEVENLABS_WEDDING_SETUP.md
docs/GENERAL_PURPOSE_NEGOTIATOR_PLAN.md
docs/WEDDING_PHOTOGRAPHY_MIGRATION.md
eslint.config.mjs
next-env.d.ts
next.config.js
package.json
postcss.config.js
public/fonts/.DS_Store
public/images/.DS_Store
README.md
scripts/document_parser.py
scripts/test-anthropic-api.mjs
src/app/agent-run/page.tsx
src/app/api/calls/[id]/status/route.ts
src/app/api/calls/initiate/route.ts
src/app/api/discovery/google-places/route.ts
src/app/api/intake/normalize-generic-document/route.ts
src/app/api/intake/parse-document/route.ts
src/app/api/negotiate/route.ts
src/app/api/report/generate/route.ts
src/app/api/verticals/classify/route.ts
src/app/api/webhooks/elevenlabs/route.ts
src/app/calls/page.tsx
src/app/discover/page.tsx
src/app/globals.css
src/app/intake/page.tsx
src/app/layout.tsx
src/app/negotiate/page.tsx
src/app/not-found.tsx
src/app/page.tsx
src/app/providers.tsx
src/app/report/page.tsx
src/components/.DS_Store
src/components/Actions/index.tsx
src/components/Answer/index.tsx
src/components/ApiIntegrator/index.tsx
src/components/Article/index.tsx
src/components/Browser/content.tsx
src/components/Browser/index.tsx
src/components/Button/index.tsx
src/components/Calculator/index.tsx
src/components/calls/CallCard.tsx
src/components/calls/CallGrid.tsx
src/components/calls/WaveformAnim.tsx
src/components/Chart/data.tsx
src/components/Chart/index.tsx
src/components/Chat/Head/index.tsx
src/components/Chat/index.tsx
src/components/CodeEditor/index.tsx
src/components/EditorArticle/index.tsx
src/components/Field/index.tsx
src/components/FileConverter/.DS_Store
src/components/FileConverter/Converter/index.tsx
src/components/FileConverter/File/index.tsx
src/components/FileConverter/index.tsx
src/components/Gallery/index.tsx
src/components/Gallery/Preview/index.tsx
src/components/Header/index.tsx
src/components/Header/SpecialOffer/index.tsx
src/components/Icon/index.tsx
src/components/Image/index.tsx
src/components/InlineVoicePrompt/index.tsx
src/components/intake/DocumentUpload.tsx
src/components/intake/GenericBriefForm.tsx
src/components/intake/GenericDocumentUpload.tsx
src/components/intake/GenericVoiceIntake.tsx
src/components/intake/JobSpecConfirm.tsx
src/components/intake/VoiceIntake.tsx
src/components/LanguageTranslator/index.tsx
src/components/Layout/index.tsx
src/components/LayoutLogin/index.tsx
src/components/LayoutLogin/Slider/index.tsx
src/components/LayoutLogin/Slider/items.tsx
src/components/Modal/index.tsx
src/components/ModalPlan/index.tsx
src/components/ModalPlan/plans.tsx
src/components/ModalSettings/.DS_Store
src/components/ModalSettings/DataControls/index.tsx
src/components/ModalSettings/General/index.tsx
src/components/ModalSettings/General/UploadImage/index.tsx
src/components/ModalSettings/index.tsx
src/components/ModalSettings/menu.tsx
src/components/ModalSettings/Notifications/index.tsx
src/components/ModalSettings/Security/index.tsx
src/components/ModalSettings/Speech/index.tsx
src/components/ModalSettings/Theme/index.tsx
src/components/ModalShare/Images/index.tsx
src/components/ModalShare/index.tsx
src/components/ModalView/index.tsx
src/components/negotiate/PriceTracker.tsx
src/components/negotiator-layout/AiDisclosure.tsx
src/components/negotiator-layout/index.tsx
src/components/negotiator-layout/Navbar.tsx
src/components/negotiator-layout/StepProgress.tsx
src/components/PanelMessage/.DS_Store
src/components/PanelMessage/index.tsx
src/components/PanelMessage/Menu/HotKeys/index.tsx
src/components/PanelMessage/Menu/index.tsx
src/components/PanelMessage/Menu/items.tsx
src/components/PanelMessage/Note/index.tsx
src/components/PanelMessage/Search/index.tsx
src/components/PanelMessage/Search/items.tsx
src/components/PanelMessage/Speed/index.tsx
src/components/PythonRunner/index.tsx
src/components/Question/index.tsx
src/components/Select/index.tsx
src/components/Sidebar/.DS_Store
src/components/Sidebar/Button/index.tsx
src/components/Sidebar/Folders/folders.tsx
src/components/Sidebar/Folders/index.tsx
src/components/Sidebar/index.tsx
src/components/Sidebar/InvitePeople/index.tsx
[69 more files omitted for size]
```

### Dependencies

- package.json: @11labs/react@latest, @anthropic-ai/sdk@latest, @elevenlabs/client@^1.15.1, @headlessui/react@^2.2.8, @monaco-editor/react@^4.7.0, @tailwindcss/postcss@^4.3.3, @types/node@^20.0.0, @types/react@^19.0.0, @types/react-dom@^19.0.0, autoprefixer@10.x, class-variance-authority@latest, clsx@latest, date-fns@latest, elevenlabs@latest, eslint@^9.0.0, eslint-config-next@^16.2.10, framer-motion@^12.42.2, lucide-react@latest, millify@^6.1.0, monaco-editor@^0.53.0, next@^16.2.10, next-themes@^0.4.6, openai@^6.48.0, postcss@8.x, react@^19.2.7, react-animate-height@^3.2.3, react-dom@^19.2.7, react-spinners@^0.17.0, react-textarea-autosize@^8.5.9, react-use@^17.6.0, recharts@^3.2.1, sonner@latest, swiper@^12.0.2, tailwind-merge@latest, tailwind-scrollbar@^4.0.2, tailwindcss@^4.3.3, tesseract.js@^7.0.0, typescript@5.x

### Recent commits (newest first)

- add site link
- fix /report route
- trigger vercel deploy
- trigger vercel deploy
- fix: remove silent redirects to /calls when report/negotiation data is missing
- Trigger Vercel deployment
- Merge branch 'main' of https://github.com/gargieesingh/NegotiatorAI
- Update README with new image and project details
- Refine README description and formatting
- Trigger Vercel deployment
- Revise README to enhance project clarity and details
- fix(sidebar): update AI stack badges to Codex and GPT-5.6, fix step 7 done indicator and report banner
- Trigger Vercel deployment
- refactor(ui): clean up Report, Intake, Discover, Calls, and Negotiate pages to match NeuraTalk design system and remove step progress clutter
- refactor(agent-run): simplify UI layout to match NeuraTalk clean design with 3 active vendor call cards
- refactor: remove step progress and module 04 subtitle from report page
- refactor: remove user profile footer from sidebar and use local font for build stability
- Revert "update cerebras api key to gemini api key"
- docs: update README.md for OpenAI Hackathon submission
- update cerebras api key to gemini api key

## Key source files (fetched from GitHub, selected and truncated for size)

### .agents/AGENTS.md

```markdown
# NegotiatorAI — Agent Rules

## Core UI Rule: Always Inspired by NeuraTalk

**Every UI component, page, and layout in this project must be designed with inspiration from the NeuraTalk project (`C:\Users\Harsh\Desktop\neuratalk`).**

NeuraTalk is the design reference. Before building any new UI, study how NeuraTalk handles similar patterns and replicate that aesthetic.

---

## NeuraTalk Design Language Summary

### Typography
- **Primary font**: Satoshi (light 300, regular 400, medium 500, bold 700)
- **Secondary font**: Inter (for labels, UI text)
- **Display font**: InterDisplay (medium 500, headings)
- Body default: `font-satoshi text-p-sm text-strong-950`

### Color Tokens (Light Mode)
| Token | Value | Usage |
|---|---|---|
| `white-0` | `#ffffff` | Card/panel backgrounds |
| `strong-950` | `#0e121b` | Primary text |
| `weak-50` | `#f9fafc` | Page background, secondary fills |
| `sub-600` | `#525866` | Secondary/muted text |
| `soft-400` | `#99a0ae` | Placeholder text |
| `stroke-soft-200` | `#e1e4ea` | All borders, dividers |
| `information-base` | `#335cff` | Primary blue / CTA |
| `success-base` | `#1fc16b` | Success green |
| `error-base` | `#fb3748` | Errors |
| `feature-base` | `#7d52f4` | Purple / AI accent |

### Spacing & Shape
- **Border radius**: `rounded-3xl` (cards/panels), `rounded-2xl` (inner cards), `rounded-xl` (buttons/chips)
- **Card shadow**: `shadow-[0_0_1.25rem_0_rgba(0,0,0,0.03)]`
- **Panel padding**: `p-5` or `p-7.5` internally
- **Gaps**: `gap-4`, `gap-2`, `gap-1.5` — consistent 4px grid

### Sidebar & Layout
- Sidebar: `fixed top-5 left-5 bottom-5 w-80 bg-white-0 rounded-3xl shadow-[0_0_1.25rem_0_rgba(0,0,0,0.03)]`
- Main content area: sits beside sidebar, `bg-weak-50` page background
- Cards/chat wrappers: `bg-white-0 rounded-3xl shadow-[0_0_1.25rem_0_rgba(0,0,0,0.03)]`

### Interactive Elements
- **Buttons**: `rounded-xl`, `text-label-sm`, hover transitions via `transition-colors`
- **Active/selected nav items**: `bg-weak-50` background fill
- **Hover**: `hover:text-blue-500`, `hover:fill-blue-500`
- **Focus**: clean, no harsh outlines — uses `ring` only where needed

### Design Patterns
- Clean white cards with very subtle shadows — **no heavy drop shadows, no dark backgrounds**
- Borders are always `border-stroke-soft-200` (never black/dark)
- Status indicators: small dot, pastel pill badges
- Icons: consistently sized (`size-4`, `size-5`, `size-6`), filled, muted default colour
- Smooth `transition-colors` on all interactive elements (`duration-200`)
- Scrollbars hidden: `scrollbar-none`
- Dark mode supported via `[data-theme="dark"]` but light mode is primary

### What to Avoid
- ❌ No dark backgrounds invented on whims (slate-950, black terminals, etc.)
- ❌ No gradients unless NeuraTalk uses them
- ❌ No custom one-off shadow values (always use the `0_0_1.25rem_0_rgba(0,0,0,0.03)` pattern)
- ❌ No mismatched fonts — always Satoshi/Inter
- ❌ No raw text dumps in headers or titles

```

### docs/ELEVENLABS_WEDDING_SETUP.md

```markdown
# ElevenLabs Wedding Demo Setup

Create two ElevenLabs agents: **The Wedding Estimator** and **The Negotiator**. Connect a Twilio number to the Negotiator agent before placing human-in-the-loop demo calls.

For both agents, ensure the built-in **End call** system tool is enabled. It lets the agent hang up immediately after the natural closing described below.

## Wedding Estimator prompt

```text
You are an AI wedding-photography intake assistant. You are working for a customer and must build one complete, accurate photography brief before any vendor is contacted.

Introduce yourself honestly as an AI assistant. If asked whether you are a robot, say yes and explain that the customer authorized you to gather comparable quotes.

Collect, conversationally and one or two questions at a time:
- wedding date
- venue name and city
- events requiring coverage and coverage hours for each event
- photography-only or photography plus videography
- drone coverage
- albums
- special requests

Never promise a price. Never invent information. Ask the customer to confirm your summary.

After the customer confirms the summary, call the `submit_wedding_brief` client tool with this exact object. Do not say JSON, tags, property names, or field values aloud.

After the tool confirms it saved the brief, say only a short natural closing such as: “Thanks — I’ll now speak with photographers to compare current market prices. I’ll bring the options back for your review.” Then end the call.
```

## Confirm your photography brief

The confirmation screen must display only the fields returned by the current estimator prompt:

- Wedding date
- Venue name and city
- Events and coverage hours
- Photography only or photography plus videography
- Drone coverage
- Albums
- Special requests

Do not display or require guest count, travel, overnight stay, photography style, cinematic film, highlight reel, album count, or other legacy fields on the intake confirmation screen. The customer must confirm this brief before any photographer is contacted.

## Negotiator prompt essentials

The agent must introduce itself as an authorized AI assistant, read only the confirmed wedding brief, and request an itemized quote for every requested event and deliverable. It must use the brief's `wedding_date`, `venue`, `events`, `coverage_type`, `drone_coverage_required`, `albums_required`, and `special_requests` exactly as confirmed by the customer.

During the call, it must ask the photographer to itemize base coverage for every requested event, photography-only versus photography-plus-videography pricing, drone charges, album charges, travel or accommodation charges if applicable, taxes, deposit, overtime rate, quote validity, and whether the quote is binding. It must not ask the customer for additional intake fields that are not present in the confirmed brief.

It may cite only a competing quote supplied by the application. It must never invent a quote, package inclusion, customer detail, or bindin
[truncated — 2550 more characters]
```

### package.json

```
{
  "name": "the-negotiator",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "test:anthropic": "node --env-file=.env.local scripts/test-anthropic-api.mjs"
  },
  "dependencies": {
    "@11labs/react": "latest",
    "@anthropic-ai/sdk": "latest",
    "@elevenlabs/client": "^1.15.1",
    "@headlessui/react": "^2.2.8",
    "@monaco-editor/react": "^4.7.0",
    "@tailwindcss/postcss": "^4.3.3",
    "class-variance-authority": "latest",
    "clsx": "latest",
    "date-fns": "latest",
    "elevenlabs": "latest",
    "framer-motion": "^12.42.2",
    "lucide-react": "latest",
    "millify": "^6.1.0",
    "monaco-editor": "^0.53.0",
    "next": "^16.2.10",
    "next-themes": "^0.4.6",
    "openai": "^6.48.0",
    "react": "^19.2.7",
    "react-animate-height": "^3.2.3",
    "react-dom": "^19.2.7",
    "react-spinners": "^0.17.0",
    "react-textarea-autosize": "^8.5.9",
    "react-use": "^17.6.0",
    "recharts": "^3.2.1",
    "sonner": "latest",
    "swiper": "^12.0.2",
    "tailwind-merge": "latest",
    "tailwind-scrollbar": "^4.0.2",
    "tesseract.js": "^7.0.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "@types/react": "^19.0.0",
    "@types/react-dom": "^19.0.0",
    "autoprefixer": "10.x",
    "eslint": "^9.0.0",
    "eslint-config-next": "^16.2.10",
    "postcss": "8.x",
    "tailwindcss": "^4.3.3",
    "typescript": "5.x"
  }
}

```

### src/app/page.tsx

```typescript
import HomePage from '@/templates/HomePage';

export default function Page() {
  return <HomePage />;
}

```

### src/app/layout.tsx

```typescript
import type { Metadata } from 'next';
import localFont from 'next/font/local';
import Providers from './providers';
import './globals.css';

const inter = localFont({
  src: [
    { path: '../../public/fonts/InterDisplay-Medium.woff2', weight: '400' },
  ],
  variable: '--font-inter',
  fallback: ['system-ui', 'sans-serif'],
});

const satoshi = localFont({
  src: [
    { path: '../../public/fonts/Satoshi-Light.woff2', weight: '300' },
    { path: '../../public/fonts/Satoshi-Regular.woff2', weight: '400' },
    { path: '../../public/fonts/Satoshi-Medium.woff2', weight: '500' },
    { path: '../../public/fonts/Satoshi-Bold.woff2', weight: '700' },
  ],
  variable: '--font-satoshi',
});

const interDisplay = localFont({
  src: [
    { path: '../../public/fonts/InterDisplay-Medium.woff2', weight: '500' },
  ],
  variable: '--font-inter-display',
});

export const metadata: Metadata = {
  title: 'The Negotiator',
  description: 'Your AI negotiation agent.',
};

export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
  return (
    <html
      className="text-[calc(0.7rem+0.35vw)] max-[2300px]:text-[calc(0.7rem+0.32vw)] max-[2150px]:text-[calc(0.7rem+0.28vw)] max-4xl:text-[1rem]"
      lang="en"
      suppressHydrationWarning
    >
      <body className={`${satoshi.variable} ${inter.variable} ${interDisplay.variable} bg-weak-50 font-satoshi text-p-sm text-strong-950 antialiased`}>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

```

### src/components/negotiator-layout/index.tsx

```typescript
import Layout from "@/components/Layout";

export default Layout;

```

### src/components/Image/index.tsx

```typescript
import { useState } from "react";
import { default as NextImage, ImageProps } from "next/image";

const Image = ({ className, ...props }: ImageProps) => {
    const [loaded, setLoaded] = useState(false);

    return (
        <NextImage
            className={`inline-block align-top opacity-0 transition-opacity ${
                loaded && "opacity-100"
            } ${className || ""}`}
            onLoad={() => setLoaded(true)}
            {...props}
        />
    );
};

export default Image;

```

### src/components/Test/index.tsx

```typescript
type TestProps = {
    title?: string;
    description?: string;
    className?: string;
};

const Test = ({
    title = "Test Component",
    description = "Neuratalk White Theme Test",
    className = "",
}: TestProps) => (
    <div
        className={`bg-white-0 border border-stroke-soft-200 rounded-xl p-4 text-strong-950 ${className}`}
    >
        <h3 className="text-strong-950 font-semibold text-base mb-1">
            {title}
        </h3>
        <p className="text-sub-600 text-sm">{description}</p>
    </div>
);

export default Test;

```

### src/components/Answer/index.tsx

```typescript
import Image from "@/components/Image";

type Props = {
    children: React.ReactNode;
};

const Answer = ({ children }: Props) => (
    <div className="flex">
        <div className="shrink-0">
            <Image
                className="size-9 opacity-100 rounded-full object-cover"
                src="/images/avatar-chat.svg"
                width={36}
                height={36}
                alt="Avatar"
            />
        </div>
        <div className="w-[calc(100%-2.25rem)] pl-3">
            <div className="mb-1 text-label-sm text-strong-950 font-medium">Odyssey AI</div>
            <div className="text-sub-600">{children}</div>
        </div>
    </div>
);

export default Answer;

```

### src/components/Gallery/index.tsx

```typescript
import Preview from "./Preview";

const Gallery = ({}) => {
    return (
        <div className="relative h-160 bg-white-0 border border-stroke-soft-200 rounded-2xl p-1 overflow-hidden max-4xl:h-106 max-md:h-60">
            {[
                "/images/image-2.jpg",
                "/images/image-3.jpg",
                "/images/image-4.jpg",
            ].map((image, index) => (
                <Preview
                    className="w-[calc(50%-0.25rem)] first:top-1 first:left-1 first:bottom-1 not-first:h-[calc(50%-0.25rem)] not-first:right-1 nth-2:top-1 nth-3:bottom-1"
                    image={image}
                    key={index}
                    index={index}
                />
            ))}
        </div>
    );
};

export default Gallery;

```

[144 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]