Set the objective and mission.
You start by defining the objective, then writing a clear mission file that describes what success looks like.
mission.mdA3 is a stage-based automation framework. You define the workflow and any agents; A3 learns and writes typed stage modules plus a durable playbook, and the runner replays them with no LLM in the loop.
npm i @athree/runner @athree/cli
A3 separates the parts of automation that benefit from intelligence from the parts that don't. You define the workflow and agents once. Stages are then learned and captured as code. A runner replays them — fast, typed, and free of model spend.
You start by defining the objective, then writing a clear mission file that describes what success looks like.
mission.mdYou define the tools, schemas, and configuration in the workflow so the agent has strict contracts while learning.
defineWorkflow()The agent visits each target website and creates per-page stages as readable Playwright scripts.
LearningThe agent writes findings to playbook.md, making edge-case fixes and future site changes easy to handle.
Stages, playbooks, and config live as directly editable files inside your git repo.
git-friendlyAutomations run at scale on UBIO Automation Cloud with no LLM required at runtime.
a3 run / cloudSelect a use case to preview how A3 applies the same six-step model in practice. Then look below to see fully worked Step 1-6 examples update instantly for that scenario.
mission.md.# Mission — scrape rates Given a hotel id, stay dates, and guest count, drive the property’s booking flow on the live site. Prefer the public consumer path unless `playbook.md` already documents otherwise. ## What to capture - Every bookable room with nightly rates (fees/taxes when the UI shows them). - Normalise to the workflow’s `Rate` schema — don’t invent inventory the page never offered.
import { defineWorkflow } from '@athree/runner'; import { ScrapeRatesInputSchema } from './schema/ScrapeRatesInput.js'; import { ScrapeRatesOutputSchema } from './schema/ScrapeRatesOutput.js'; import { TestAgent } from './TestAgent.js'; export default defineWorkflow({ title: 'Scrape Rates', description: 'Scrape rates from a website', inputsSchema: ScrapeRatesInputSchema, outputsSchema: ScrapeRatesOutputSchema, rootDir: 'src', sitesDir: import.meta.dirname + '/sites', agents: [TestAgent], projectLocations: [ { dir: import.meta.dirname + '/objectives', writable: true, patterns: ['*.md'] }, { dir: import.meta.dirname + '/schema', writable: false }, ], });
sites/<hostname>/.playbook.md, including drift and edge-case notes in the changelog.import { defineStage } from '@athree/runner'; export default defineStage({ title: 'Extract Rooms and Rates', description: 'Pulls rooms+rates from API or DOM', success: true, match: async (ctx) => { const url = new URL(ctx.page.url()); return url.pathname.startsWith('/'); }, run: async (ctx) => { const resp = ctx.networkResources.find( r => r.request.url.includes('getProductAvailability') ); const data = JSON.parse(resp.response.responseBody); ctx.outputs.hotelId = ctx.inputs.search.hotelId; ctx.outputs.results = [{ search: ctx.inputs.search, rooms: extract(data) }]; }, });
# Synxis property — public rates ## Objective Scrape nightly room rates from the consumer booking path. ## Entry points - Deep link with property id + stay dates, or hotel home → check availability. ## Flow states 1. `cookie-banner` (dismiss) 2. `rate-shopping` (rates visible) ## Known risks - Inventory JSON from `getProductAvailability`; vendor changes the shape occasionally. ## Changelog ### 2026-04-12 - Rates list moved to `[data-test="room-list"]`; `extract-rates` `match()` updated. Mobile lazy-loads guest row — `main.stage.ts` waits on `networkidle`. ### 2026-01-28 - Currency toggle removed; property currency only. “Member rate” badge ignored for the public `Rate` schema.
my-automation-project/ ├── package.json └── src/ └── workflows/scrape-rates/ ├── scrape-rates.workflow.ts ├── TestAgent.ts ├── objectives/ │ └── mission.md ├── schema/ │ ├── ScrapeRatesInput.ts │ ├── ScrapeRatesOutput.ts │ └── Rate.ts ├── skills/ │ └── create-site/SKILL.md └── sites/ ├── default/ │ └── main.stage.ts # global fallback ├── be-synxis-com/ │ ├── main.stage.ts │ ├── extract-rates.stage.ts │ ├── inputs.yaml │ └── playbook.md └── asp-hotel-story-ne-jp/ ├── main.stage.ts ├── inputs.yaml └── playbook.md
version: '1'
workflow: src/workflows/scrape-rates/scrape-rates.workflow.ts
runtime:
provider: ubio-automation-cloud
mode: deterministic
llmInLoop: false
concurrency: 60
retries:
maxAttempts: 2
backoffMs: 1500
targets:
- site: be-synxis-com
inputs: src/workflows/scrape-rates/sites/be-synxis-com/inputs.yaml
- site: asp-hotel-story-ne-jp
inputs: src/workflows/scrape-rates/sites/asp-hotel-story-ne-jp/inputs.yaml
outputs:
artifactDir: ./.runs/scrape-rates
uploadPlaybooks: true
Begin with the quickstart in Docs, learn the architecture in Concepts, and use API reference pages while implementing workflows and stages.