Run the Demo
The demo is a self-contained chat app that shows Adzen delivering contextual ads inside an AI assistant conversation. By default it uses mock agent responses and a mock Adzen API. Optionally, set environment variables to connect to a real LLM and/or the real Adzen ad API.
The demo lives inside the @adzenai/ai package at packages/ai/src/copilotkit/demo/.
What The Demo Shows
- A chat UI where you type any message and receive a streamed response
AdzenAsyncMiddlewareprocessing the AG-UI event stream in real time- An
AdzenCardrendering a contextual ad in the chin (between the chat area and the input) - Client-side impression beacons (GET requests) fired directly to the delivery API
- Viewability tracking firing view beacons after the ad is visible (logged to the console)
- The full data flow: agent → middleware → event bridge → React
Prerequisites
- Node.js
>=18 - pnpm
>=9
Install Dependencies
From the workspace root:
pnpm installThis installs all workspace packages including @adzenai/ai and @adzenai/core.
Configure Environment
The demo supports three modes controlled by two optional environment variables. Create a .env file in packages/ai/src/copilotkit/demo/ (copy from .env.example):
cp packages/ai/src/copilotkit/demo/.env.example packages/ai/src/copilotkit/demo/.env| OPENAI_KEY | ADZEN_KEY | Agent | Ad API |
|---|---|---|---|
| unset | unset | Mock canned responses | Mock sample ads |
| set | unset | gpt-4.1-mini streaming | Mock sample ads |
| unset | set | Mock canned responses | Real Adzen API |
| set | set | gpt-4.1-mini streaming | Real Adzen API |
Mock mode (default)
No .env file needed. The demo uses canned multi-chunk text responses and rotates through fictional sample ads with mock impression URLs. No network calls are made.
Real LLM mode
Set OPENAI_KEY in your .env:
OPENAI_KEY=sk-...The demo streams responses from OpenAI's gpt-4.1-mini model. Requests are proxied through the Vite dev server to avoid CORS.
Real ad API mode
Set ADZEN_KEY in your .env:
ADZEN_KEY=your_adzen_keyThe demo calls the real Adzen API at https://api.adzen.ai/v1/ai/process. The middleware consumes the API response directly (no transformation needed). Requests are proxied through the Vite dev server.
Both
Set both variables to use a real LLM for agent responses and the real Adzen API for ad matching.
Run The Demo
From the packages/ai directory:
pnpm demoOpen http://localhost:5188/ (opens in a new tab) in your browser. The header bar shows which mode is active (e.g., "Agent: gpt-4.1-mini · Ads: live API" or "Agent: mock · Ads: mock").
How It Works
The demo wires four components together:
| Component | File | Role |
|---|---|---|
| Agent | demo/mockAgent.ts or demo/openaiAgent.ts | Produces AG-UI event streams (mock canned chunks or real OpenAI SSE) |
| Ad API | demo/mockAdApi.ts or demo/liveAdApi.ts | Mock fetch interceptor returning ProcessResponse shape, or passthrough to real API |
| Middleware | ../middleware.ts | AdzenAsyncMiddleware — buffers text, calls /process, emits adzen_placement events |
| Chat UI | demo/App.tsx | Renders messages, bridges events to the browser, displays AdzenCard in the chin |
Data Flow
User types prompt
→ agentStream() yields AG-UI events (mock or OpenAI)
→ AdzenAsyncMiddleware.processEvent() buffers text, fetches ad
→ dispatchPlacementEvents() bridges to browser CustomEvents
→ useAdzenPlacement() picks up placement
→ AdzenCard renders ad in the chin
→ GET render_impression_url (on mount)
→ observeViewability() → GET view_impression_url (after 1s visible)Test Manually
Mock mode
- Type any message.
- Watch the canned response stream in chunks.
- After the message completes, an ad appears in the chin below the chat.
- Open the browser console to see impression beacon logs:
[adzen-demo] Impression beacon fired: render 1001
[adzen-demo] Impression beacon fired: view 1001Each message shows a different sample ad (the mock API rotates through three fictitious creatives).
Real LLM + real ad API mode
- Set both
OPENAI_KEYandADZEN_KEYin.envand restart the demo. - Type a natural prompt (e.g., "What's a good recipe for pizza dough?").
- The assistant response streams from gpt-4.1-mini.
- After the response completes, a contextual ad from the Adzen API appears in the chin.
- The ad is matched to the assistant's response content.
- Check the Network tab — impression beacons are GET requests to
delivery.adzen.ai.
Build Verification
To verify the package builds cleanly:
pnpm run build --filter=@adzenai/ai
pnpm run typecheck --filter=@adzenai/aiNext Steps
- Add Adzen to CopilotKit — integrate with a real CopilotKit app
- Developer Guide — architecture and public API reference
- Configuration — environment variables and adapter options