WATCHD v0.1
AGENTS THAT COMPOUND
FIG. 01 / THE OUTCOME

Wake up to what changed.

Run one Python agent on a schedule. It compares against prior runs, keeps memory in SQLite, and leaves a timestamped finding before breakfast.

watchd_agents/pricing_watch.py7 LINES
INSIGHTOVERNIGHT
STATEPERSISTENT
HISTORYQUERYABLE
DEPLOY1 COMMAND
FIG. 02 / PROOFREAL RUN OUTPUT

One concrete agent.
One concrete finding.

This is a real two-run transcript from a pricing monitor. Run 1 captured baseline. Run 2 detected a price change and persisted the finding to state. No hypothetical architecture.

AGENT LOGIC
watchd_agents/pricing_watch.py
from watchd import agent

@agent(name="pricing_watch")
def pricing_watch(ctx):
    run = ctx.state.get("run", 0) + 1
    previous = ctx.state.get("last_plan")
    current = fetch_pricing_page()

    if previous and previous["price"] != current["price"]:
        ctx.log.info("pricing_change", old=previous["price"], new=current["price"])
        return f"pricing_change detected: ${previous["price"]} -> ${current["price"]}"

    ctx.state["run"] = run
    ctx.state["last_plan"] = current
    return "baseline captured"
RUN OUTPUT
watchd history + watchd logs
2026-02-23 20:35:02 [info     ] agent_finished                 result='baseline captured' run_id=addcb912460d
[success] pricing_watch (addcb912460d) in 1ms

2026-02-23 20:35:02 [info     ] pricing_change                 new=79 old=49 plan=Starter run_id=332c200308a1
[success] pricing_watch (332c200308a1) in 1ms
result: pricing_change detected: Starter $49 -> $79
PERSISTED STATE
watchd state pricing_watch
{
  "findings": [
    {
      "run": 2,
      "finding": "pricing_change detected: Starter $49 -> $79"
    }
  ],
  "last_plan": {
    "run": 2,
    "plan": "Starter",
    "price": 79,
    "seats": 3
  },
  "run": 2
}
FIG. 03 / WHY NOT RAW CRON

Cron can schedule. It does not compound.

The activation energy is only worth it if you feel the difference on run two. watchd gives you state, history, and observability as defaults, so your agent can compare now vs then without extra plumbing.

CRON + CUSTOM SCRIPT
0103:00: scrape /pricing and print current value.
02Next run sees only current value again.
03No built-in prior snapshot unless you build storage.
04No run history table unless you wire your own schema.
05When alerted, you still reconstruct what changed by hand.
WATCHD
01Run 1 stores baseline in ctx.state["last_plan"].
02Run 2 compares previous price against current.
03Finding includes explicit diff: $49 -> $79.
04history/logs/state are queryable from one CLI.
05Alert carries context because memory is native.
FIG. 04 / HOW TO GET VALUE TONIGHT
01PICK

Start with one painful signal.

Choose one thing you care about overnight: pricing drift, contract creep, stale docs, uptime checks. Keep the scope narrow.

$ watchd init
$ watchd new compliance_check

# point it at one source
URL = "https://vendor.com/terms"
02REMEMBER

Make run two smarter than run one.

Use ctx.state to compare against prior runs. watchd stores the baseline, run history, and logs so your finding has context by default.

previous = ctx.state.get("last_terms")
current = scrape_terms_page()

if previous and previous["hash"] != current["hash"]:
    return f"terms changed: {diff(previous, current)}"

ctx.state["last_terms"] = current
03SHIP

Deploy once, then let it run.

Push to any VPS in one command. You can inspect history, logs, and state at any time without stitching together extra tooling.

$ watchd run compliance_check
$ watchd deploy

# inspect later
$ watchd history compliance_check
$ watchd logs compliance_check
$ watchd state compliance_check
FIG. 05 / UNDER THE HOOD9 MODULES

You write agent logic. watchd handles the rest.

Scheduling, state, history, logs, deploy. Nine modules, zero external dependencies.

scheduler
Cron + interval triggers
runner
Execute with retries and capture
state
Persistent memory across runs
logger
Structured, queryable logs
retry
Automatic backoff on failure
history
Every run tracked and searchable
deployer
Atomic deploys, any VPS
watcher
Hot-reload in development
cli
init, up, deploy, logs, state
cli -> schedulercli -> deployercli -> watcherscheduler -> runnerrunner -> staterunner -> loggerrunner -> retryrunner -> historystate -> history
FIG. 06 / START WITH ONE AGENT
BUILT BY © LEVEL09