Skip to content
Merged
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
46 changes: 46 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,49 @@ npm run demo:financial
is what tunes reported confidence over time.
- **Informational only — not investment advice.** Yahoo Finance data is
provided as-is for demonstration.

## `next-best-offer.ts` — which offer, when, and how it learns

A runnable sample for the lifecycle question: **which offer is right for a
contact, when should it go out, and how does the system get better each time an
offer lands?** The engine owns memory, pattern-mining, prediction, and
calibration; **Claude** (`claude-opus-4-8`) owns the judgement call (which offer,
when); this app is the glue.

| Step | What it does | Calls |
|------|--------------|-------|
| Learn | Ingest each contact's activity, mine behavior patterns | `tf.memory.observe` → `tf.lattice.mineMemories` |
| Understand | Read who the subject is + what they'll do next (the send-time signal) | `tf.lattice.getProfile` / `tf.lattice.predict` |
| Decide | Claude picks the offer + send time, grounded in the signal AND what has worked | `tf.learning.getEffectiveness` → Claude (`messages.parse`) → `tf.learning.recordDecision` |
| For a list | Rank a set of contacts by confidence / soonest send | loop the above |
| Act + learn | Record the realized outcome; every informing pattern is re-calibrated | `tf.learning.recordOutcome` → `tf.learning.getEffectiveness` |

The decision records `informedBy` the patterns/predictions it leaned on, so when
the outcome comes in, **those** patterns' calibrated confidence moves — that's
the closed loop. Run it twice: the second Decide step sees the first run's
effectiveness and shifts toward what actually converted.

### Run it

```bash
npm install # pulls @anthropic-ai/sdk + zod (dev deps for this example)

export THINKFLEET_API_KEY="sk-..."
export THINKFLEET_PROJECT_ID="..."
export ANTHROPIC_API_KEY="sk-ant-..."
export THINKFLEET_BASE_URL="https://memory.thinkfleet.ai" # optional
npm run demo:nbo
```

### Notes

- **Domain stays in your app.** The engine never sees "offer" — the loop records
the generic `action_type="send_offer"` with the chosen offer id as the
`decision_type`, so `getEffectiveness({ groupBy: 'decision_type' })` rolls up
per offer. Nothing consumer-specific leaks into the engine.
- **Cold start is honest.** On the first run there's no outcome history, so
Claude reasons from the profile + predictions; effectiveness fills in as
outcomes accumulate and steers later runs.
- **Flobyte pieces** (Activepieces) can drive the same loop as a no-code flow —
the `recordDecision` / `recordOutcome` / `getEffectiveness` REST routes are the
same ones this SDK calls. This example is the code-first version of that flow.
Loading
Loading