From a recording to a reusable flow

This is how log learns to do something on a website once and then repeat it on any account. You do the task step by step with log inspect, which records everything; log turns that recording into a flow, a state machine, a command and an MCP tool. Read this if you want to automate a new task, or understand where the saved flows come from.

It works on every platform with a browser path (Facebook, Reddit). Every run passes the same gates as any other: proxy, device, locale, self-check, active hours, launch budget and a raw recording of the network (HAR).

The pipeline

StageCommandWhat it produces
1. Looklog inspect start --account <a> --url <url>, then log inspect do <action>One visible browser kept open. Every step is recorded in order: an accessibility snapshot with element refs, a screenshot, the step's own HAR, and rea's reading of that HAR.
2. Readlog facebook capture --docsdocs/platforms/<platform>/<domain>/<request>.md: every request the site's pages made, what it sends and reads, which step fires it, timings, errors, and rea's evidence from the site's own code.
3. Maplog inspect map [<run>] [--all]The recording as states and transitions (flow.md, machine.json). --all combines every run.
4. Flowlog flow fromInspect <run> --name <n> --rename text1=firstName …src/browser/flow/definitions/<n>.json: each step's element by role and name, the request that confirms each step, and the parameters. Plus its doc in docs/platforms/facebook/flows/<n>.md.
5. MachinecreateFlowMachine(definition)An XState machine: one state per step, and failed on the first step that fails.
6. Runlog flow run <n> --account <a> --set k=v … [--live]A dry run lists the filled-in steps. --live runs the machine through an inspect session, so the run is recorded and mapped again.
7. MCPthe log MCP serverEvery saved flow becomes its own tool (for example flowProfileSetup), with parameters by name. The live version needs confirmLive.

Inspect actions

ActionChanges anything on the site? (needs --live)What it does
goto <url>, snapshot, back, wait [s]noMove around or look.
click <ref>, type <ref> <text>, press <key>, upload <ref> <file>yesOne action on the element the snapshot gave that ref.
solveyesReads the site's text captcha, sends it to an image solver, then types and sends the answer (solve.json).
signIn, codeyesTypes the email, password and authenticator code from the run's private login file.
clickRole, fillRole, uploadRole, waitRoleyesThe flow runner's steps: an element found by role and accessible name, plus expect (the request that confirms it worked).
stopnoClose and save the session.

Details:

  • A step settles when the network has been quiet for 1.5 s (up to 15 s, longer while an expect is pending).
  • Typed values are hidden in snapshots.
  • A HAR over rea's 32 MB limit gets a copy without static file bodies for rea; the raw HAR is kept.
  • --now skips only the 10-minute gap between launches.

The mouse

Every session moves the cursor with python/human/humanMouse.py, which is fitted to a recording of a real person's mouse made with python/human/recordMouse.py. What it reproduces:

  • one smooth speed curve per move, peaking early and settling slowly;
  • overshooting and coming back about half the time;
  • loose loops around whatever is being looked at;
  • short pauses, and staying still about 25% of the time.

Every step writes mouse.json (its moves) and mouseSamples.json (every point, in the recorder's format), so the same analyser can compare the two:

python python/human/recordMouse.py 60                      # record your own mouse for 60 s, then analyse it
python python/human/recordMouse.py --analyze <run>/steps/02_wait60s/mouseSamples.json

Camoufox's own humanize setting stays on, but is capped at 20 ms per hop in these sessions (launch_kwargs(…, own_trajectory=True)). Its default cost about 100 ms per 5 px hop, which made earlier movement crawl.

How a flow step runs

A flow never depends on a page's exact wording or on a person stepping in (rule 79). Each control is one scored match by role and name inside the dialog the step names, never a guess (controlAmbiguous, controlMissing, controlDisabled); every step waits for the call it must cause and checks its answer before the next one fires (rule 73); and before the first click, fill, upload or location the known overlays are pressed away with Escape, each checked, or the flow stops with overlayNotCleared. Each of these is a requirement in the flows spec.

Saved flows

Every flow below is in src/browser/flow/definitions/, has its doc in docs/platforms/facebook/flows/, and is an MCP tool (flow<Name>, a dry run) with its live twin (flow<Name>Live, needs confirmLive). log flow list prints them.

FlowStepsWhat it does
deletePost4Deletes the newest post on the account's own profile
facebookLanguageEnglish4Switches the account's Facebook language to English (US)
groupHeaderMenus11Opens and closes the group header's menus, picking nothing
groupMembers20Opens a group's People tab and scrolls it, read-only
groupPostComments5Opens a post's comments on Open questions, sorts them and scrolls, read-only
groupPostDialog3Opens a post in its dialog with Leave a comment and closes it, typing nothing
groupTabs9Opens each tab of a group and comes back to Discussion, read-only
marketplaceListingDelete6Deletes one Marketplace listing from Selling and answers the survey
marketplaceListingPublish15Publishes one Marketplace listing in the account's open browser
messengerPinCreate4Creates the Messenger PIN from Twenty (rule 67)
postComment3Comments on the newest post on the account's own profile
profilePhotoPost3Posts a photo on the account's own profile
profilePost4Posts text on the account's own profile
profileSetup13Sets the profile picture, cover photo and name (rule 28)
warmupCreateAccessCheck6Warm-up stage 3
warmupFeedBrowse6Warm-up stage 1
warmupMarketplaceBrowse4Warm-up stage 2
warmupMessagesVisit7Warm-up stage 5
warmupSellingVisit4Warm-up stage 4

profileSetup was recorded on one account and then ran 13 out of 13 steps on another.

What early recordings showed

  • A first sign-in on a new account can land on "We suspect automated behaviour" (/checkpoint/601051028565049/). Pressing Dismiss sends FBScrapingWarningMutation and lands signed in.
  • A locked account went through these screens in order (recorded before a checkpointed account was deactivated instead of pressed through, rule 82; see the page states spec): "Confirm that you're human to use your account" [Continue] → useUFACSubmitActionMutation (5 s) → a text captcha → solver (1.5 s) → [Continue] → useUFACSubmitActionMutation (3 s) → "Confirm your identity with a video selfie". Only a person can clear the last screen. A second visit picks up at the step it was left on.
  • Changing exit IPs stood out. One account signed in from three exit IPs in 90 minutes over 15 launches; accounts whose exit IP stayed fixed fared differently.
  • Connect read the page too soon. It read 1 s after pressing Enter, saw the login form still there, and tried again, although the first Enter had worked. It must wait for the page to change.
  • The listing's location isn't set by any request in a run. It arrives in the create page itself (sell_location), so a wrong Marketplace location is an account setting.

Where things are

PathWhat
python/session/inspectSession.pyThe inspect session
src/browser/inspect/Talking to it: commands, replies, rendering
src/rea/inspectMap/Recording → states and transitions
src/browser/flow/Recording → definition, machine, docs; definitions/
src/cli/inspect/, src/cli/flow/The commands
src/mcp/server/helpers/toolsFromFlows.tsFlows as MCP tools
src/rea/facebookClient/The per-request docs build
skills/inspect, skills/flow, skills/profileSetup, skills/reaCaptureHow-to routines
~/.logCli/runs/{inspect,flow}/<time>_<account>/Recordings (local, never committed)

The rules behind this are in AGENTS.md.