Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 206 additions & 0 deletions outcome-shopping-template/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# Created by https://www.toptal.com/developers/gitignore/api/macos,node,git
# Edit at https://www.toptal.com/developers/gitignore?templates=macos,node,git

### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig

# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt

### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### macOS Patch ###
# iCloud generated files
*.icloud

### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

### Node Patch ###
# Serverless Webpack directories
.webpack/

# Optional stylelint cache

# SvelteKit build / generate output
.svelte-kit

# End of https://www.toptal.com/developers/gitignore/api/macos,node,git

### Wrangler ###
.wrangler/
.env*
!.env.example
.dev.vars*
!.dev.vars.example

### Turbo ###
.turbo/

### Playwright ###
/test-results/
/playwright-report/
123 changes: 123 additions & 0 deletions outcome-shopping-template/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Outcome Shopping Orchestrator

![Status: Demo-ready](https://img.shields.io/badge/status-demo--ready-green) ![Type: Agent orchestrator](https://img.shields.io/badge/type-agent--orchestrator-blueviolet)

**Part of the [agent-commerce](https://gitlab.cfdata.org/mconroy/agent-commerce) portfolio** — the demand-side orchestration layer.

**Live demo:** https://outcome-shopping.chambers-testing-7ff.workers.dev/shop _(Cloudflare SSO)_

Multi-vendor, outcome-based shopping powered by [commerce llms.txt](https://gitlab.cfdata.org/mconroy/commerce-llms-txt). Describe what you want to achieve and this agent decomposes your intent into component needs, searches across multiple merchants' AI-enriched catalogs, and assembles a cross-merchant recommendation.

## What it demonstrates

This is a proof of concept for **outcome-based agent commerce** — the idea that agents should shop by intent ("outfit my 3-year-old for skiing"), not by product search ("toddler ski set size 70cm").

The key insight: **each merchant's commerce llms.txt becomes more valuable as more merchants adopt it**, because agents can compose across them. A single merchant's catalog solves discovery. Multiple merchants' catalogs solve outcomes.

### How it works

```
"outfit my 3-year-old for skiing"
┌─────────────────────────────┐
│ Intent Decomposition │ Workers AI (Llama 3.1 8B)
│ → skis, boots, helmet, │ Breaks intent into 5-8
│ jacket, pants, gloves, │ component product needs
│ base layers, socks │
└─────────────────────────────┘
┌─────────────────────────────┐
│ Catalog Aggregation │ Fetches /api/products from
│ → 9 products across │ each registered merchant's
│ 3 merchants │ commerce llms.txt Worker
└─────────────────────────────┘
┌─────────────────────────────┐
│ Per-Need Matching │ Workers AI (Llama 3.1 8B)
│ → Best product per need │ One AI call per need for
│ from any merchant, │ accuracy; tracks used
│ with alternatives │ products for variety
└─────────────────────────────┘
Cross-merchant recommendation
with total cost and sourcing
```

### Architecture

- **Runtime:** Cloudflare Workers (Hono framework)
- **AI:** Workers AI binding (`@cf/meta/llama-3.1-8b-instruct`)
- **Caching:** KV namespace for aggregated merchant catalogs (5 min TTL)
- **Merchant data:** Each merchant runs a [commerce-llms-txt](https://gitlab.cfdata.org/mconroy/commerce-llms-txt) Worker that serves AI-enriched product data

## Endpoints

| Endpoint | Description |
| -------------------------- | -------------------------------------------------------------------------------------- |
| `GET /shop?q=<intent>` | Human-friendly UI with loading states and styled results |
| `GET /api/shop?q=<intent>` | JSON API for agents — returns decomposition, recommendations, alternatives, total cost |
| `GET /llms.txt` | Agent-readable capability description of this orchestrator |
| `GET /api/catalogs` | Aggregated multi-merchant catalog (JSON) |
| `GET /api/merchants` | Registered merchants and their connectivity status |
| `GET /` | Service discovery (JSON) |

## Project structure

```
src/
├── index.ts # Hono app, routes, HTML rendering
├── ai/
│ ├── decompose.ts # Intent → component needs (Workers AI)
│ └── match.ts # Needs × products → recommendations (Workers AI)
└── lib/
├── types.ts # TypeScript interfaces
├── catalog.ts # Merchant catalog fetching and aggregation
└── sample-catalogs.ts # Demo data (3 merchants, 9 products)
```

## Setup

```bash
npm install
```

### Local development

```bash
npm run dev
```

Note: The AI binding requires `--remote` mode or a deployed Worker. Local dev without remote bindings will fail on AI calls.

### Configuration

All config is in `wrangler.jsonc`:

| Variable | Description |
| -------------------- | ----------------------------------------------------------------------- |
| `MERCHANT_ENDPOINTS` | JSON array of `{name, url}` merchant endpoints |
| `AI_MODEL` | Workers AI model identifier (default: `@cf/meta/llama-3.1-8b-instruct`) |
| `CACHE_TTL` | Catalog cache TTL in seconds (default: 300) |

### Deploy

```bash
npm run deploy
```

## Current status

This is a working prototype using sample catalog data from 3 simulated merchants (Summit Sprouts, Peak Riders Gear Co., Snow Bunny Kids). When real merchant endpoints are available on the public internet, update `MERCHANT_ENDPOINTS` in `wrangler.jsonc` and the sample data fallback will be bypassed automatically.

### Known limitations

- **Sample data fallback:** When all merchant fetches fail (e.g., behind Cloudflare Access), demo data is served. There's no visible indicator to the user.
- **Model quality:** Llama 3.1 8B occasionally confuses product indices. A relevance-score validation step catches most of these, but alternatives can still be slightly off.
- **Sequential matching:** Per-need AI calls add 1-4s latency. This is a deliberate tradeoff for accuracy over the batch approach.
- **No test coverage:** The AI response parsing logic is the most fragile surface and would benefit from unit tests.

## Relationship to commerce llms.txt

This project is the **demand-side counterpart** to [commerce-llms-txt](https://gitlab.cfdata.org/mconroy/commerce-llms-txt) (supply side). Commerce llms.txt makes a single merchant's catalog agent-readable. This orchestrator composes across multiple merchants' catalogs to fulfill outcome-based intents that no single merchant can satisfy alone.

The strategic thesis: the more merchants that deploy commerce llms.txt, the more useful this orchestration layer becomes. That's the network effect story for merchant adoption.
12 changes: 12 additions & 0 deletions outcome-shopping-template/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Outcome Shopping — Multi-Vendor Recommendations</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/react-app/main.tsx"></script>
</body>
</html>
Loading