Documentation snapshot. Run commands in the separate NorthCUA Harness repository.

A real local batch, then resume

This tutorial uses the existing BatchRunner, controller, SQLite state, device transport and evaluator. Each attempt starts a new local browser worker and browser context. The local-process provider is for trusted small Web batches on macOS/Linux. It is not an OS sandbox: it shares the host filesystem, user and network. Desktop runs separately, one task per display.

Install using first run. Activate the same environment in all terminals. No hosted-model key, cloud account or remote path is required below.

Start the fixture and controller

Terminal A (keep open):

northcua demo serve --directory logs/batch-tutorial --response-delay 1

Wait for ready: true. Terminal B (keep open):

northcua controller serve --app-config logs/batch-tutorial/app.batch.yaml \
  --host 127.0.0.1 --port 8765 --executor-mode in_process \
  --runner-workers 2 --worker-queue-max 4 \
  --db-path logs/batch-tutorial/controller.sqlite \
  --blob-dir logs/batch-tutorial/blobs \
  --artifact-root-dir logs/batch-tutorial/controller-artifacts \
  --insecure-dev-no-auth

The generated batch.yaml already has three tasks, their fixture URLs and the absolute controller DB path. Wait for the controller to start before running it. For another port, pass --controller-port to demo serve and the same --port to the controller. Only loopback connections may use the no-auth option.

Validate, plan, execute

Terminal C:

northcua batch validate --manifest logs/batch-tutorial/batch.yaml
northcua batch run --manifest logs/batch-tutorial/batch.yaml \
  --dry-run --output-dir logs/batch-tutorial/plan
northcua batch run --manifest logs/batch-tutorial/batch.yaml \
  --output-dir logs/batch-tutorial/batches
northcua batch status --batch-id local-web --output-dir logs/batch-tutorial/batches
northcua batch report --batch-id local-web --output-dir logs/batch-tutorial/batches

Use a separate output root for a dry run. A successful run has three succeeded tasks, each with one attempt, and three real page-action receipts in events.jsonl. Each actor writes a note and clicks the page; each evaluator must observe its own receipt in the original browser. Inspect individual task errors and cleanup errors even when the runner command itself returns normally.

Persistent state and reports are under batches/local-web/: manifest.json, run_config.json, batch_state.sqlite, batch_summary.json, telemetry and sandbox-logs/. Controller task artifacts are in controller-artifacts/. Do not edit SQLite directly or delete evidence to make a failed run appear green.

Read each controller session's result.json → evaluation_report.overall_verdict and evaluations/web_round_evaluator/round_0001/final_report.json for the live evaluator verdict. The batch summary's evaluation_status / evaluation_attempts projection can remain empty / zero for this runtime path; it is not the outcome check. Keep actor status, evaluator verdict and cleanup confirmation separate.

Resume without repeating successful tasks

Keep the same controller and fixture alive:

northcua batch resume --batch-id local-web --output-dir logs/batch-tutorial/batches

After a completed batch this should preserve three successes and their attempt counts. It must not produce another round of page clicks. Check batch status and the count of web_action events before and after.

For an actual drain/recovery exercise, create a fresh fixture directory, set --response-delay 3, and use --concurrency 1 on the first batch run. While the first task is running, in terminal D:

northcua batch drain --batch-id local-web --output-dir logs/batch-tutorial/batches

Drain lets admitted work finish and leaves queued work for batch resume. The drained runner exits 1 when queued work remains: the batch is deliberately incomplete, not a failed drain operation. Confirm task states before resuming. Wait for the original runner to exit before resuming. Resume uses the saved manifest and reconciles known controller tasks; do not change its task list or reuse its batch ID for a different experiment. pause and cancel have different semantics; see batch operations.

Prefer drain to abruptly killing the runner. If the runner dies, a local supervisor stops its workers and browsers; incomplete attempts may need a retry. This does not imply that arbitrary external website actions can be safely replayed. Completed tasks are preserved by the existing reconciliation path.

Switch to your real model and tasks

Keep the local-process manifest structure. Start the controller with the model configuration from first run instead of app.batch.yaml; change task URLs, queries and budgets. Set sandbox.metadata.controller_db to that controller's absolute DB path. The demo service is only needed if you still use its fixture pages.

The normal model template disables evaluation by default. To retain live outcome checks, set both evaluation.enabled: true and evaluation.tools.allow_client_live_probe: true in the controller's app YAML. The evaluator uses the configured model too; provision an appropriate task budget and inspect its report separately from actor completion.

Setting Starting value Meaning
defaults.concurrency 2 Active tasks; start with 1 for a new endpoint
defaults.max_retries 1 One extra whole-task attempt after a retryable failure
defaults.timeout_seconds 120 Controller-task wait limit
sandbox.resources.timeout_seconds 300 Local worker lifetime, renewed by the lease mechanism
tasks[].max_steps 6 for this demo Actor decision budget; use a suitable budget for real work

The local provider accepts only Web/browser, fresh per-task allocations. It rejects guest shell commands, uploads, post-run hooks, prepared queues and CPU/memory/disk isolation requests. It uses the running Python installation; it does not install packages or build templates. Use the documented E2B path when you need separately provisioned environments.

Shut down

Wait for batch completion or drain it. Stop the controller, then the fixture service with Ctrl-C. Each released local allocation has a cleanup receipt under the OS temporary directory northcua-local-<uid>/local-<uuid>/finished.json; diagnostic files may remain there, but worker and browser processes must end. The receipt must include cleanup_confirmed: true; a supervisor exit without that confirmation is a cleanup error, not success. Detached browser descendants are tracked by process identity and an inherited allocation marker. Cleanup scans again during shutdown to find children whose parent has already exited. Unexpected worker exits and unreadable newly appeared processes leave cleanup unconfirmed. This applies to the installed worker and Playwright, which inherit the marker; arbitrary daemon commands are unsupported. The provider never kills a process based only on a PID read from old state. See troubleshooting if cleanup was not confirmed.

← Back to the guide

Licenses & creditsApache-2.0 · Harness code

中文