Zenmem
Login
๐Ÿ”

Competitor watch

MarketingCompetitive intelligencePython ยท FastAPI

About this agent

A watch on a competitor's public surface โ€” a pricing page, a product page, a changelog. You register what to watch along with our own position on the same thing, then feed it snapshots over time. The first snapshot is never news; there is nothing to compare it to, and it records a baseline and says so rather than manufacturing a finding. From the second onward it reports only what actually moved: a reworded heading and a reworded CTA are not a finding, but prices coming down, retention cut from 30 days to 7, and self-hosting quietly dropped are โ€” and the last one is flagged as overlapping the position we lead on.

RUNTIMEPython ยท FastAPI
MEMORY TYPELong-term, per watch
SDKzenmem 0.4.4
LOCAL PORT8880

What changed with Zenmem?

The same agent, built twice against the same contract โ€” once on Zenmem, once on MongoDB + LangChain/LangGraph.

Before โ†’ after

Code for the snapshot APIโˆ’24%

Code for overlap detectionโˆ’52%

New infrastructure to stand upnone

New dependencies to install0

Schema, collection and index worknone

Keeping every snapshot, not just the latestfree

Semantic overlap search over the historyincluded

Before With Zenmem

What the team gained

  • The whole snapshot history is the store, so a claim quietly dropped in September can still be read against the one made in March โ€” retention is not a TTL policy someone has to design.
  • Overlap between their message and ours is a semantic search over what is already kept, rather than a second vector store bolted on beside the record.
  • A new watch kind is a value on a document, not a new collection and a new index.
  • Registering a watch and appending a snapshot are the same call shape, so the diff logic has one source of truth to read from.
  • Nothing in the service has to decide what to evict, which is what keeps a quiet retreat from an old claim visible months later.

How memory is scoped

One scope, held for as long as the watch exists. Every snapshot is kept, not just the latest, because the value is in the difference between them: a claim a competitor made in March and quietly retreated from in September is only visible if both are still there. The registered `we_claim` sits alongside that history, which is what lets overlap be detected rather than eyeballed.

How it works

The run order the collection walks through.

Register the watch

A URL, what kind of page it is, and our own position on the same subject โ€” so overlap can be detected later rather than argued about.

Snapshot over time

The first snapshot is the baseline. Byte-identical content on a later one produces nothing, and cosmetic rewording is filtered out.

Read the difference

Material changes only, with the ones that land on our own positioning called out.

Brief the campaign

The change history turned into something a marketer can take into the next campaign.

API surface

The whole agent, endpoint by endpoint.

Endpoints

  • POST /api/watch โ€” register what to watch: watch_id, competitor, url, kind, and our own claim on the same thing.
  • POST /api/snapshot โ€” submit the current content of the watched page. The first is a baseline; later ones are diffed.
  • GET /api/history/{watchId} โ€” every snapshot taken, so an abandoned claim stays visible months later.
  • GET /api/overlap/{competitor} โ€” where their message has moved onto ours.
  • POST /api/brief โ€” turns the difference into a brief a marketer can act on, for a named campaign.