Direct answer

The signal watch: remember the baseline, alert only on real movement

A signal watch is one agent checking the same signal on a schedule: an asset price, a lead source, a mention feed, your own receipts and download totals. Reading the signal is the easy part. What breaks is everything around it: the baseline lives in a chat that scrolls away, the threshold is whatever the agent feels that day, quiet days leave no record, and when the alert finally fires nobody can check what it was measured against. Zambo is the layer under the watch: memory that persists between the agent's sessions under its own identity, a verifiable receipt for every call, and a digest handover for every pass. This page teaches the pattern twice: once as a paste for people new to watches, and once at full depth, with a real run and every receipt linked. The whole pattern also ships as an installable agent package: pip install zambo-watch or npm install zambo-watch.

See the instrument first: the live demo runs one real call and hands you its verifiable receipt, no signup. New here? Add Zambo to your AI in one step, then run the paste below. Reading as an agent? This guide has a plain markdown twin, same content, no styling.

Updated November 2, 2026. First published November 2, 2026. The worked example is a real run executed against the live service on November 2, 2026, with every receipt read back the same day.

New to watches? Start here, no code

You need one chat AI on a loop, or one you check in with daily. Add the Zambo endpoint to it first (the one-step setup at zambo.dev/add), paste the watcher block into its instructions, and tell it what to watch and what move counts as news. It saves the identity (its caller handle) the endpoint issues inside its own conversation, saves the baseline on the first pass, and recalls that baseline on every later pass. Nothing else needs to be built.

The paste, for the watcher:

Run a signal watch on Zambo:
1. Connect to https://zambo.dev/mcp. When the endpoint issues your caller handle, save it in this conversation and present it on every call. Your memory, including the baseline you are about to save, keys to that handle. Keep one job id for the whole watch and reuse it on every pass.
2. First pass only: read the signal (for a price watch, call live_price for each asset). Then save ONE fact with memory_remember: the values, each value's receipt link, and the rule in plain words, for example "alert when any watched asset moves 3 percent or more from its baseline". Keep the remember receipt.
3. Every later pass: recall the baseline with memory_recall and read the values out of the recalled fact. Never work from your chat transcript; the remembered fact is the baseline of record.
4. Read the signal again. Compute each move against the recalled baseline and apply the rule exactly as stated. A move under the threshold is a quiet day, even if it is close.
5. Save the reading with memory_remember either way: the values, the moves, and the rule's outcome. A quiet day with no saved reading is a gap in the record.
6. Wrap the pass with handover: a summary (lead with the alert and the size of the move if the rule fired; say "quiet check, no alert" with the values and moves if it did not), a goal naming the watch and the rule, the operator as recipient, and next steps. Send the operator the handover link. That link is the digest: the record anyone can verify at https://zambo.dev/verify/ .

What a watch actually struggles with

Not the signal. Price feeds, search results, and mention streams are all readable in one call. A watch struggles with time. The baseline was set in a session that ended. The threshold was a sentence in a prompt that got edited twice since. The agent that checked yesterday is not obviously the agent checking today, and on a quiet week there is no evidence the watch ran at all, right up until the day it matters that it did. Every one of those failures is a memory and record failure, and that is the layer this pattern puts on Zambo: the baseline and the rule as one remembered fact under the watcher's own handle, the readings saved pass after pass, and the whole history checkable receipt by receipt.

The pattern

One watch is one job id (a single _session_id the watcher picks once and reuses on every pass) and one identity: the watcher initializes once, is issued its own caller handle, saves that handle, and presents it on every call. Memory keys to the handle, so the baseline the watcher saves on day one is the baseline it recalls on day thirty, across restarts and reconnects, as long as the handle survives. The first pass reads the signal and saves the baseline fact: the values, the source receipts, and the rule in plain words. Each later pass recalls that fact, reads the values back out of it, reads the signal again, computes the moves, applies the rule exactly as stated, saves the reading either way, and wraps a digest handover. When the rule fires, the digest leads with the alert. When it does not, the digest is the quiet format: the values, the moves, and the words "no alert", so a reader can always tell a checked quiet day from a day the watch never ran.

The real run: a three-asset price watch, one fresh identity

November 2, 2026, one fresh identity (signal-watch-demo), one job id (signal-watch-2026-11-02), run with the package's own watch.py. The rule, stated in the baseline fact: alert when any watched asset moves 3 percent or more from its baseline.

The baseline pass (20:45 UTC) read BTC at $76,800.00 (receipt), ETH at $2,244.62 (receipt), and SOL at $91.29 (receipt), then saved the baseline fact with the rule and all three receipts inside it: the baseline, saved.

The canonical check pass recalled the baseline from memory alone (BTC 76800.0, ETH 2244.62, SOL 91.29, verbatim), then read BTC at $76,793.00 (receipt), ETH at $2,245.12 (receipt), and SOL at $91.34 (receipt). The moves: BTC -0.01 percent, ETH +0.02 percent, SOL +0.05 percent. No asset reached 3 percent, so the rule returned no alert, and that is what the record says: the reading saved (receipt) and the quiet-day digest wrapped: the digest handover. A check run minutes after its baseline should be quiet; a digest that cried alert here would be the failure. (An earlier check pass the same hour returned the same honest shape: its digest.)

The package also proves itself from fresh installs: the copies of watch.py installed from PyPI and from npm were each run baseline plus check against the live endpoint by separate fresh identities, and each wrapped its own digest (PyPI install's digest, npm install's digest).

Audit this run

Pick any link above and open it. Each receipt shows the saved result of that call, and the check at zambo.dev/verify recomputes whether the saved result was changed after it was saved. The digest handover lists the pass's steps, each opening to its own receipt. A receipt proves the saved result was not changed since it was saved; it does not prove the price was right, and nothing on this page claims otherwise. If a receipt from this run ever fails to verify, that is news and worth reporting to brennanzambo@zambo.dev.

Step zero, at depth: one handle, one watch

The watcher initializes once and is issued a caller handle (in the initialize result and the X-Zambo-Caller-Handle header). It saves that handle in its own state file before making any other call, and presents it as _caller_handle on every call, with its name as _caller_label. Memory, job timelines, and the daily free allowance all key to the handle. A second watch gets its own handle: two watches sharing one handle share one memory, and their baselines collide. The heartbeat demo that runs publicly every day on this estate holds a different identity from the watch in the run above for exactly that reason: one handle per watch, never shared, never reused across watches.

Quota rule, in the placement that works: Put _caller_handle inside the tool arguments on every call, as a field of the arguments object itself, not in _meta and not in a header. That argument placement is what meters your own daily bucket. Presenting a handle only at _meta level or in a header can route you onto a shared network bucket and wall you early.

Why quiet days get wrapped

The wrap is a handover: a summary, a goal, a named recipient, and next steps. A handover call without a summary and a recipient is refused, with its own receipt; a digest is a deliverable being published and it is held to that standard. The quiet format exists because the alert format cannot be trusted without it. If digests only appear on alert days, then a missing digest is ambiguous: quiet, or broken. When every pass wraps, the absence of a digest is itself a signal, and a reader scanning a month of digests sees the watch's whole life: baseline, readings, moves, and the one day the rule fired, each step opening to its receipt.

Proof the installed package runs

The run above was executed from source. The shipped package was then installed fresh, twice, and run from the installed copy both times. From a clean Python environment, pip install zambo-watch saved its baseline (1ff0cf90) and its check pass wrapped the digest as handover ef9b1633. From a clean npm install, the bundle byte-identical to the PyPI one, the baseline saved as e6960255 and the digest wrapped as handover d91d82c8 (wrap receipts e0d58c41 and 5a4f7639). What installs is what runs.

The accounting: what a watch costs

The free tier is per agent: 20 calls + 1 wrap-up free every day, keyed to the watcher's own caller handle, and picking up a handover is always free. The run on this page cost 4 counted calls for the baseline pass (3 prices and the baseline save) and 5 per check pass (the recall, 3 prices, the reading save); the digest wrap was the free daily wrap-up and left the counter untouched. Run once a day, a three-signal watch costs 5 counted calls a day after day one, well inside free. Past free, the line is per agent: a Day Pass is $0.99 for one agent, unlimited for 24 hours; the Zambo Pass is $29 for one agent for 30 days. One-time payments, never subscriptions. Three watches are three identities with three allowances: the estate's own public heartbeat demo, this package's run identity, and the fresh-install identities all ran today without touching each other's counters.

Standing instructions, at depth

The code route is the package's watch.py: python3 watch.py baseline on the first pass and python3 watch.py check on every later pass, with the identity persisted in a state file next to the script. Symbols, threshold, job id, and label are environment settings (ZAMBO_WATCH_SYMBOLS, ZAMBO_WATCH_THRESHOLD, ZAMBO_WATCH_JOB, ZAMBO_WATCH_LABEL), so the same file watches leads or mentions by changing what the passes read. Scheduling belongs to the reader: wire the check pass to a cron line, a framework scheduler, or a daily standup job. One caution from the record: one check per scheduled pass. A watch that checks five times an hour spends its allowance proving nothing moved; a watch that checks once a day and saves every reading builds the record that makes the alert believable when it finally fires.

What Zambo is not here

Zambo is not a scheduler and does not start the watcher's passes. It does not pick the threshold: 3 percent on three assets is the worked example, and the right rule for a lead watch or a mention watch is the operator's call, stated inside the baseline fact where a reader can argue with it. It does not make the signal correct. What it does is give the watch a memory that survives the session, a rule that cannot quietly drift, and a record where every number the digest cites opens to its own receipt.

Frequently asked questions

What is a signal watch, in plain words?

A signal watch is one agent checking the same signal again and again on a schedule: an asset price, a lead source, a mention feed, a number of your own. On the first pass the agent saves a baseline and the rule it will judge by. On every later pass it recalls the baseline, reads the signal again, computes the move, and reports a digest: an alert when the rule fires, a quiet note when it does not. The watching is the easy part. The pattern exists to fix what usually breaks: the baseline, the rule, and the record of the quiet days.

Does Zambo run the schedule?

No. Your cron, your agent loop, or your framework's scheduler starts each pass. Zambo is where the watch's memory and record live between passes: the baseline as a remembered fact under the agent's own caller handle, every reading saved, and a verifiable receipt for every call, so an alert can always be traced back to the baseline it was measured against.

Why save readings on quiet days, when nothing moved?

Because a record with gaps on quiet days cannot prove the watch was running. When the alert finally fires, the first question is whether the baseline and the passes before it are real. A digest wrapped on every pass, quiet ones included, is the evidence. It also costs nothing extra in kind: the check pass is 5 counted calls whether or not the reading gets saved, and saving it is what makes the watch a record instead of a rumor.

What does a daily watch cost on the free tier?

The free tier is per agent: 20 calls + 1 wrap-up free every day for the agent's own caller handle, and picking up a handover is always free. The run on this page cost 4 counted calls for the baseline pass and 5 per check pass, and the digest wrap was the free daily wrap-up. A daily three-signal watch therefore runs free at 5 counted calls a day after day one. When a watch outgrows the free tier, a Day Pass makes that agent unlimited for 24 hours for $0.99, and the Zambo Pass covers an agent for 30 days for $29; both are one-time payments, never subscriptions.

Can I run this pattern with no code?

Yes. Add https://zambo.dev/mcp to a chat AI, paste the watcher block from the start-here section of this guide into its instructions, and put the check pass on whatever loop the chat runs on. The AI saves the caller handle it is issued inside its conversation, saves the baseline on the first pass, and recalls it on every later pass. It is the same pattern the code runs, worked by hand. The installable package (pip install zambo-watch, npm install zambo-watch) carries the same paste plus runnable code.

Related

The Loop kit

One routine, every piece of it in one place: the data that found the loop, the recipe, the library of pre-built jobs, the two shapes a daily loop takes, and a starter repo with Zambo already wired in.

The package family

One pattern per package, each teaching by doing, with Zambo as the mechanism inside. Five guides, one family: