@athree/create-project
v1.2.1
Published
Create a new A3 automation project
Keywords
Readme
A3 Project Template
Create and scaffold A3 automation workflows.
Note: This template requires the
nextbranch of@athree/runner. Last updated: 2026-01-27. This will change as this branch changes or is merged.
Create a New Project
npx @athree/create-project a3-project-starter
cd a3-project-starter
npm i && npm run compileNaming convention: Projects should be named a3-project-{name} (e.g., a3-project-hotel-rates).
Note: You must run
npm run compilefor the project to appear in your local athree runner.
Or clone manually:
cp -r a3-project-template a3-project-starter
cd a3-project-starter
npm i && npm run compileAdding Project to Runner
Use the Add Project button in the A3 runner UI to add your project directory. The runner will automatically detect workflows in compiled projects.
Environment Setup
Configure your environment variables before running workflows:
cp .env.example .env
# Edit .env and add your API keysRequired variables:
- At least one LLM API key:
GOOGLEAI_API_KEY,OPENAI_API_KEY, orANTHROPIC_API_KEY
Optional variables:
CHROME_HEADLESS— Run browser in headless mode (default:true)CHROME_KEEP_OPEN— Keep browser open between runs (default:true)
Project Structure
├── datasets/ # Input YAML files (one per service)
├── services/ # Output directory (gitignored)
│ └── {service-id}/
│ ├── screenshot.png # Page screenshot
│ └── result.json # Workflow result
├── src/
│ ├── instructions/ # LLM instructions (markdown files)
│ ├── schema/ # Zod schemas (Dataset, Result)
│ └── workflows/ # Workflow classesIncluded Workflows
SimpleScreenshot
A minimal workflow demonstrating basic browser automation:
- Navigates to a URL
- Waits for page load
- Takes a full-page screenshot
Useful as a starting point or for testing browser connectivity.
SimpleGenericWebAgent
Demonstrates the GenericWebAgent pattern:
- Navigates to a URL
- Creates a
GenericWebAgentviaAgentsService - Runs the agent with a simple text objective
This is the simplest way to use LLM-powered web automation - no stages, no schemas, just a one-shot LLM call with browser tools.
SimpleLearningAgentExtract
Demonstrates the learning agent pattern with stages:
- Loads instructions from a markdown file
- Sets up automation context with input/output schemas
- Uses
AutomationRunner.learn()to execute with LLM guidance - The LLM creates reusable stages to navigate and extract data
Use this pattern for complex, multi-step automations that benefit from reusable stages.
Getting Started
- Set up environment variables (see Environment Setup)
- Run
npm run compileto build the project - Update the dataset in the workflow (or load from
datasets/) - Define instructions in
src/instructions/for LLM-powered workflows - Update schemas in
src/schema/to match your data
Key Services
ChatService— Send messages to the UIBrowserService— Access the browser page for screenshots, navigationAgentsService— Create LLM agents (createGenericWebAgent(),createPageExtractor())AutomationRunner— Run automations withrun()(existing stages) orlearn()(LLM-guided)AutomationContext— Manage automation state, inputs, outputs, and schemas
GenericWebAgent Pattern
For simple one-shot LLM tasks, use GenericWebAgent:
import { AgentsService, BrowserService, workflow } from '@athree/runner';
import { dep } from 'mesh-ioc';
@workflow({ title: 'My Workflow' })
export class MyWorkflow {
@dep() private browserService!: BrowserService;
@dep() private agentsService!: AgentsService;
async run() {
const page = await this.browserService.getPage();
await page.goto('https://example.com');
const agent = this.agentsService.createGenericWebAgent();
agent.addUserContext({ currentUrl: page.url() });
await agent.run('Extract the main heading and description from this page.');
}
}Learning Agent Pattern
For complex multi-step automations with reusable stages, use the learning agent:
import { AutomationRunner, AutomationContext, workflow } from '@athree/runner';
import { dep } from 'mesh-ioc';
import { z } from 'zod';
@workflow({ title: 'My Workflow' })
export class MyWorkflow {
@dep() private automationRunner!: AutomationRunner;
@dep() private automation!: AutomationContext;
async run() {
const result = await this.automationRunner.learn({
automationId: 'my-automation',
instructions, // Loaded from .md file
inputs: { url }, // Input data
inputsSchema, // Zod schema for inputs
outputsSchema, // Zod schema for expected outputs
learningModel: 'gemini-2.5-flash', // Optional: specify LLM model
});
const outputs = this.automation.outputs;
}
}Instructions Files
Instructions tell the LLM how to handle different page states. Place them in src/instructions/:
# Goal
Extract product details from the page.
# Output Fields
- `ctx.outputs.title` - Product title
- `ctx.outputs.price` - Product price
- `ctx.outputs.status` - "success" or "failure"
# Instructions
## Product page
1. Extract the title from h1
2. Extract the price
3. Set status to "success"Tips
- Define clear output fields in your instructions
- Use Zod schemas to validate inputs and outputs
- The LLM creates reusable stages that can be re-run without LLM
- Save results to the
services/folder
