Define the workflow.
Set the objective, write mission.md, and wire tools, schemas, and agents in defineWorkflow() — the contract the agent learns against.
A3 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.
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.
Set the objective, write mission.md, and wire tools, schemas, and agents in defineWorkflow() — the contract the agent learns against.
The agent visits sites, writes per-page stages as Playwright scripts, and captures findings in playbook.md for drift and edge cases.
Stages and playbooks live as git-friendly files. The runner replays them with no LLM at runtime — locally or on Automation Cloud.
a3 run · cloudSelect a use case to preview how A3 applies the same three-step model in practice. Then look below to see fully worked Workflow → Learning → Runner examples update instantly for that scenario.
mission.md with the objective and success criteria.defineWorkflow().# 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.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 the Product tour while implementing workflows and stages.