The old ListSessions call capped at 200, and 476 agent tasks were missing from our conversation archive.

What the scraper did

The scraper pulls the agent service’s sessions into raw JSON, and a parser turns them into per-thread markdown. The documented refresh step was the scraper with --files --skip-existing, followed by the parser. Discovery went through the internal ListSessions endpoint with a JWT.

A row in our API doc covered what to do about the scraper. It said the scraper stays on the internal JWT for now, because the archive parser depends on internal response shapes. The port to task.list and task.listMessages was to happen “when the JWT next breaks.”

That trigger was a broken JWT. The 200 cap was what had dropped the 476 tasks.

What replaced it

Discovery is now the official task.list. It is paginated, uses the API key, and is free. Bodies still ride the internal JWT getSessionV2. Porting them to task.listMessages would retire the JWT refresh step.

Alongside the discovery change, the scraper picked up these behaviors:

  • Incremental fetch. It refetches a task when its updated_at changes. The command is now scrape_manus.py --files with no --skip-existing, and it fetches new and changed tasks only.
  • Shape check and quarantine. Responses are shape-checked before anything is written, and bad ones are quarantined.
  • Auth failures. A 401 or 403 halts the run with one nudge. The exit code is 2.
  • Upstream failures. A 5xx is skipped or aborts the run. Exit 3 means upstream is down.
  • Bounded run and status file. The run is bounded, and counts land in a status file.
  • Nightly push. The nightly job pushes the single-writer archive repo.

The change touched 10 files, with 1193 insertions and 170 deletions. The scraper alone accounts for 761 changed lines. The new hardening test file adds 367 lines, and the refresh-history test file gains 48.

The webhook item

The same doc had a deferred item for webhooks: a task_stopped event feeding our secretary inbox. It needed a public HTTPS endpoint first. We closed it as superseded. The nightly task.list poll keeps the archive current for free and needs no public endpoint.

The doc row for the scraper used to say it stays on the JWT until the JWT breaks. It now says discovery is task.list, paginated, because the internal ListSessions capped at 200 and had dropped 476 tasks.