An AI-powered website builder that uses multi-agent orchestration to generate complete, production-ready websites from a single text prompt. Nine specialized agents — four core and five specialists — collaborate to plan, design, build, and review your site.
PyPI Package: pypi.org/project/agentsite
Most AI website builders give you a single LLM call that dumps out a generic template. The result is usually a wall of code with no real structure, inconsistent styling, and no quality checks. You end up spending more time fixing the output than you saved by generating it.
AgentSite takes a different approach: nine specialized AI agents collaborate in a pipeline, each handling what they're best at. A PM agent plans the site structure and selects the build strategy. A Designer agent defines the visual system. In monolithic mode, a single Developer agent writes all the code; in specialist mode, dedicated Markup, Style, Script, and Image agents work in parallel for faster builds. A Reviewer agent evaluates quality and can send work back for revision — just like a real team would.
The entire pipeline is model-agnostic. You can use OpenAI, Claude, Google, Groq, Ollama, LM Studio, or any provider supported by Prompture. Swap models without changing anything else.
You get two ways to work: a full Web UI with live preview, chat input, and real-time progress tracking — or a CLI for generating sites directly from the terminal. Both produce the same output: clean, semantic HTML with proper accessibility baked in.
Under the hood, the pipeline enforces quality gates. The Reviewer agent scores every page against criteria like accessibility, semantic markup, and visual consistency. If the score is too low, the Developer gets feedback and iterates — up to two revision loops — before the site is finalized.
- Quick Start
- How It Works
- Features
- CLI Reference
- Web UI
- Embeddable Component
- Configuration
- Project Structure
- Tech Stack
- Development
- Troubleshooting
- Contributing
# 1. Install from PyPI
pip install agentsite
# 2. Set up your API keys
cp .env.copy .env
# Edit .env with your provider keys (OPENAI_API_KEY, CLAUDE_API_KEY, etc.)
# 3. Generate a website
agentsite generate "A portfolio website for a photographer"That's it! A complete multi-page website will be generated in your output directory.
Prefer a UI? Launch the web interface instead:
agentsite serve
# Open http://127.0.0.1:6391AgentSite supports two build modes, chosen automatically by the PM agent based on site complexity:
Monolithic mode — a single Developer agent handles all code:
Prompt --> PM --> Designer --> Developer <--> Reviewer --> Website
Specialist mode — dedicated agents work in parallel for faster builds:
Prompt --> PM --> Designer --> Image -----> Reviewer --> Website
Markup --/
Style --/
Script -/
| Agent | Role | Output |
|---|---|---|
| PM | Analyzes the prompt, plans site structure, selects build strategy and agents | SitePlan |
| Designer | Defines colors, typography, spacing, and the visual system | StyleSpec |
| Developer | Writes semantic HTML, CSS, and vanilla JS for each page (monolithic mode) | PageOutput |
| Reviewer | Evaluates quality, accessibility, and correctness (score >= 7 = approved) | ReviewFeedback |
| Agent | Role | Output |
|---|---|---|
| Markup | Writes HTML/JSX markup with semantic structure and ARIA labels | MarkupOutput |
| Style | Writes CSS or SCSS stylesheets with custom properties and responsive design | StyleOutput |
| Script | Writes vanilla JavaScript for interactivity and animations | ScriptOutput |
| Image | Generates images and manages the asset library | ImageOutput |
The Reviewer can trigger revision loops, sending feedback back to the Developer or specialists until quality meets the approval threshold. This runs up to two iterations per page.
Nine agents with distinct personas coordinate through Prompture groups. Four core agents handle planning, design, development, and QA. Five specialist agents (Markup, Style, SCSS, Script, Image) can run in parallel for faster builds. Each agent has a focused role and structured output — no single monolithic prompt trying to do everything.
WebSocket-based live updates during generation. Watch each agent work in real time through the Web UI with per-agent status, token usage, and timing.
Use any model from any provider: OpenAI, Claude, Google, Groq, Grok, Ollama, LM Studio, OpenRouter, and more. Switch models per-generation without changing configuration.
Agents enforce WCAG AA contrast, semantic HTML, ARIA labels, and keyboard navigation. Accessibility is built into the generation pipeline, not bolted on after.
Download generated sites as ZIP archives or browse them directly through the built-in preview server.
Before the PM agent runs, the frontend shows a 30-second discovery form (ported from open-design) — what surface, who it's for, brand context, tone, scale, constraints. If the user picks "Pick a direction for me", a follow-up direction picker shows 5 OKLch palettes (editorial-monocle, modern-minimal, human-approachable, tech-utility, brutalist-experimental). Choosing a direction skips the Designer agent entirely and synthesizes the StyleSpec deterministically from the chosen palette.
Eight bundled skills (saas-landing, pricing-page, dashboard, docs-page, blog-post, portfolio, mobile-app, coming-soon) live under agentsite/skills/<id>/SKILL.md. The PM agent receives a ranked top-5 list per brief (via lightweight token-overlap retrieval over the catalog) instead of a hardcoded full inventory; it picks skill_id per page and the Developer's prompt inherits that skill's instructions.
Four bundled design systems (linear, vercel, stripe, notion) under agentsite/design_systems/<id>/{DESIGN.md, tokens.css}. Setting style_spec.inherits_from = "linear" makes the Designer agent extend those tokens instead of inventing new ones. Users can save their own systems via the API; they persist in SQLite alongside the bundled ones.
Behind AGENTSITE_USE_CRITIQUE_PANEL=1: a panel of four single-dimension reviewers (visual_fidelity, accessibility, content_quality, code_health) scores each generation; a judge agent aggregates into a ReviewVerdict. An only-up quality_ratchet.json per project enforces "every dimension must equal or exceed its current floor" — regressions are rejected, accepted runs raise the floor. Surfaced in the Analytics dashboard.
The Developer must call read_guide('design-system.md') and read_guide('architecture.md') before its first write_file. Returns an actionable error otherwise; self-disarms after the first satisfied write so subsequent writes are unblocked.
While generation is running, the chat input flips to "Steer" mode. Steer messages flow through the WebSocket into a per-project mailbox; the pipeline drains the mailbox just before the build phase and injects accumulated tweaks into the developer prompt via {user_steer}.
write_file of any *.html publishes a preview_update WS event with the rendered HTML and a content hash. The preview iframe switches to srcDoc mode and remounts on every hash change so you see the page evolve as the agent writes it — no server round trip.
Three-tab uploader on the project Brand page. URL extraction fetches HTML + linked CSS over an SSRF-guarded httpx client and derives a populated StyleSpec (hex palette classified by luminance + chroma into bg / surface / fg / accent slots; font sniff from a curated family list). Image extraction uses Pillow quantization; PDF extraction prefers Prompture's ingestion pipeline with a raw-bytes fallback.
Heuristic extraction after every successful generation captures durable facts from the discovery brief, in-flight steer messages, and the critique verdict ("you prefer serif headers", "no emoji in body copy", "weakest dimension last run: accessibility"). Saved to project_memories, deduplicated, and prepended to the PM prompt on the next run.
settings.agent_routing maps each agent key to a strategy hint (fast, cost_optimized, balanced, quality_first) or an explicit model id; routing_model_pools holds the candidate pool per strategy. Critique-panel reviewers default to cheap models and the judge to quality-first so enabling the panel doesn't balloon the per-run cost.
Every agent's text output is run through RefusalDetector (prefers Prompture's when installed, regex fallback otherwise). Refusals are stamped onto the AgentRun record and surfaced live via the refusal_detected WS event. The Analytics dashboard shows refusal rate by agent alongside cost-by-routing and per-project quality ratchet trends.
Pixel-accurate SVG chrome (iPhone 15 Pro, Pixel, iPad Pro, MacBook) under frontend/public/frames/. The DeviceSwitcher in the page builder swaps the synthetic browser chrome for real device chrome around the preview iframe.
Six starter templates on the dashboard (saas-landing-b2b, portfolio-designer, docs-quickstart, dashboard-ops, pricing-saas, coming-soon) each link a skill_id + direction_id + concrete prompt; clicking prefills the create-project modal.
All non-default capabilities live behind a setting in agentsite/config.py (prefix env vars with AGENTSITE_):
| Flag | Default | Effect |
|---|---|---|
preflight_enabled |
True |
Developer must call read_guide() for required guides before any write_file. |
preflight_required_guides |
["design-system.md", "architecture.md"] |
Which guides satisfy the pre-flight gate. |
use_critique_panel |
False |
Run the 4-dim critique panel + judge + ratchet after every successful generation. Pair with agent_routing to keep cost flat. |
use_deep_agent_developer |
False |
Wrap the Developer in AsyncDeepAgent with planning on, enabling the TodoStream UI. Falls back to the tool-calling Developer when the installed Prompture predates AsyncDeepAgent. |
agent_routing |
{accessibility: cost_optimized, …} |
Per-agent routing strategy or explicit model id. |
routing_model_pools |
{fast: [], cost_optimized: [], …} |
Strategy → candidate model id pool (first wins). |
Per-project knobs live on the Project.style_spec:
style_spec.inherits_from— id of a bundled or user-saved design system. The Designer extends those tokens instead of inventing.style_spec.direction_id— bound to the chosenDesignDirectionfrom the picker; deterministically synthesized.
Per-generation overrides live on the POST /api/projects/{id}/pages/{slug}/generate request body:
discovery_brief— answers fromGET /api/discovery/form.direction_id— short-circuits the Designer.inherits_from— sets the design system for this run.agent_models,provider_keys,max_cost,budget_policy— fine-grain budget + model overrides per agent.
agentsite generate <prompt> # Generate a website from a text prompt
-m, --model <provider/model> # LLM model to use (default: openai/gpt-4o)
-o, --output <dir> # Output directory
-n, --name <name> # Project name
agentsite serve # Start the web UI server
--host <host> # Server host (default: 127.0.0.1)
--port <port> # Server port (default: 6391)
--reload # Enable auto-reload for development
agentsite models # List available LLM modelsLaunch the browser-based interface for a full visual experience:
agentsite serveThe Web UI includes:
- Dashboard — manage projects, create new sites
- Page Builder — chat-based generation with live preview
- Agent Monitoring — see each agent's status, metrics, and activity
- Analytics — token usage, cost breakdown, and generation history
For development, run the backend and frontend separately with hot-reload:
# Terminal 1: Backend
agentsite serve --reload
# Terminal 2: Frontend (Vite dev server)
cd frontend && npm run devUse AgentSite as a library inside any Python application — no server, database, or frontend required. Two async functions expose the full pipeline:
import asyncio
import os
from pathlib import Path
from agentsite import generate_website, regenerate_page, GenerationConfig
async def main():
# Generate a site from a prompt
result = await generate_website(
"A dark portfolio site with projects and contact page",
output_dir=Path("./websites"),
config=GenerationConfig(
model="openai/gpt-4o",
provider_keys={"openai": os.environ["OPENAI_API_KEY"]},
max_cost=0.50,
),
on_event=lambda e: print(f"{e.agent}: {e.type}"),
)
for path, html in result.files_content.items():
print(f"{path}: {len(html)} bytes")
# Iterate on the same project with new feedback
v2 = await regenerate_page(
"Make the hero section taller and add a testimonials page",
output_dir=Path("./websites"),
project_id=result.project_id,
config=GenerationConfig(model="openai/gpt-4o"),
)
if __name__ == "__main__":
asyncio.run(main())| Function | Description |
|---|---|
generate_website(prompt, *, output_dir, config, on_event, project_name, slug) |
One-shot generation. Creates a project, runs the full pipeline, writes files to output_dir. |
regenerate_page(prompt, *, output_dir, project_id, slug, version, config, on_event) |
Iterate on an existing project. Auto-detects next version number and preserves the StyleSpec from prior runs. |
load_project(output_dir, project_id) |
Restore a project's full state from disk — metadata, conversation history, site plan, and latest page files. Returns None if not found. |
| Field | Type | Default | Description |
|---|---|---|---|
model |
str |
"openai/gpt-4o" |
LLM model to use |
max_cost |
float | None |
None |
Budget cap in USD |
budget_policy |
str | None |
None |
Budget enforcement policy |
provider_keys |
dict[str, str] | None |
None |
API keys per provider |
agent_configs |
dict[str, AgentConfig] | None |
None |
Per-agent overrides |
style_spec |
StyleSpec | None |
None |
Pre-defined design tokens |
logo_url |
str |
"" |
Logo URL for the site |
icon_url |
str |
"" |
Favicon URL |
max_review_iterations |
int | None |
None |
Maximum review/fix cycles per page. None uses the pipeline default. |
review_threshold |
int | None |
None |
Minimum review score to accept a page. None uses the pipeline default. |
cancel_event |
asyncio.Event | None |
None |
Cooperative cancellation flag. Set the event to abort generation between phases. |
conversation_context |
str |
"" |
Extra context prepended to the prompt (e.g., prior conversation history). |
| Field | Type | Description |
|---|---|---|
project_id |
str |
Unique project identifier |
files |
list[str] |
List of generated file paths |
files_content |
dict[str, str] |
File path → content mapping |
output_dir |
Path |
Directory where files were written |
usage |
dict |
Aggregate token/cost usage |
agent_runs |
list[dict] |
Per-agent run data |
style_spec |
StyleSpec | None |
Parsed design spec (auto-saved for reuse) |
success |
bool |
Whether generation completed |
error |
str | None |
Error message if failed |
| Field | Type | Description |
|---|---|---|
project_id |
str |
Unique project identifier |
name |
str |
Project name |
model |
str |
LLM model used |
style_spec |
StyleSpec | None |
Design tokens from the Designer agent |
site_plan_raw |
str |
Raw site plan JSON |
pages |
list[PageState] |
Latest version of each page with files |
messages |
list[ConversationMessage] |
Full conversation history |
| Field | Type | Description |
|---|---|---|
role |
str |
"user" or "assistant" |
content |
str |
Human-readable message text |
timestamp |
str |
ISO 8601 UTC timestamp |
meta |
dict |
Structured data (slug, version, files, action, etc.) |
Prompts and agent responses are auto-persisted to messages.json on disk. Use load_project to restore the full conversation thread days later:
from pathlib import Path
from agentsite import generate_website, load_project, GenerationConfig
# Day 1: generate a site
result = await generate_website(
"A dark portfolio site",
output_dir=Path("./websites"),
config=GenerationConfig(model="openai/gpt-4o"),
)
project_id = result.project_id # save this
# Day 4: restore everything and continue
state = load_project(Path("./websites"), project_id)
print(state.messages) # full conversation history
print(state.pages) # latest files per page
print(state.style_spec) # design tokens ready to reuse- No database — files and metadata live on disk via
ProjectManager - No server — direct async function calls, runs in-process
- StyleSpec auto-persisted — after generation, the designer's output is saved to
project.jsonsoregenerate_pagepicks up the brand - Error recovery — budget exceeded and pipeline failures still return partial files if any were written
- Conversation auto-persisted — user prompts and agent responses are saved to
messages.jsonfor session restoration viaload_project - Sync/async callbacks —
on_eventaccepts either sync or async functions
| Variable | Description | Default |
|---|---|---|
AGENTSITE_DEFAULT_MODEL |
LLM model for all agents | openai/gpt-4o |
AGENTSITE_DATA_DIR |
Project storage directory | ~/.agentsite |
AGENTSITE_HOST |
Server bind address | 127.0.0.1 |
AGENTSITE_PORT |
Server port | 6391 |
Provider API keys (OPENAI_API_KEY, CLAUDE_API_KEY, GOOGLE_API_KEY, etc.) are inherited from Prompture's configuration.
agentsite/
agents/ # Agent factories, Prompture personas, orchestration
personas.py # All agent persona definitions (core + specialists)
orchestrator.py # Pipeline wiring, dynamic mode selection, parallel groups
registry.py # Centralized agent registry with auto-discovery
specialists/ # Specialist agents (markup, style, script, image)
api/ # FastAPI application
routes/ # REST endpoints (projects, generate, models, assets, preview)
websocket.py # WebSocket manager for real-time progress
engine/ # Core generation logic
pipeline.py # Orchestrates agents, handles file output and events
component.py # Embeddable API (generate_website, regenerate_page)
storage/ # Persistence layer
database.py # Async SQLite via aiosqlite
repository.py # CRUD operations for projects and generations
cli.py # Click CLI entry point
config.py # Pydantic-settings (env vars, defaults)
models.py # Domain models (SitePlan, StyleSpec, PageOutput, etc.)
frontend/ # React 19 + Vite 6 + Tailwind CSS 4 SPA
tests/ # pytest test suite
| Layer | Technology |
|---|---|
| Agent orchestration | Prompture |
| API server | FastAPI + Uvicorn |
| Database | SQLite via aiosqlite |
| CLI | Click |
| Config | Pydantic Settings |
| Frontend | React 19 + Vite 6 + Tailwind CSS 4 |
| Linting | Ruff |
# Install with dev + test extras
pip install -e ".[dev]"
# Run tests
pytest
# Lint
ruff check .
# Format
ruff format .
# Build frontend
cd frontend && npm install && npm run buildGeneration fails immediately?
- Check that your
.envhas valid API keys for the provider you're using - Run
agentsite modelsto verify your provider is reachable
Empty or broken output?
- Try a different model — some smaller models struggle with structured output
- Check the Reviewer feedback in the Web UI for specific issues
Frontend not loading?
- Make sure you've built the frontend:
cd frontend && npm run build - For development, run
npm run devseparately on port 5173
WebSocket disconnects?
- The generation is still running server-side — refresh the page to reconnect
- Check the terminal output for any backend errors
Contributions welcome! Here's how:
- Report bugs — GitHub Issues
- Improve docs — PRs for documentation improvements
- Submit PRs — Bug fixes and features
- Add providers — Extend LLM provider support via Prompture
This project is licensed under the MIT License. See the LICENSE file for full details.
- PyPI Package — pypi.org/project/agentsite
- Issues — GitHub Issues
- Prompture — pypi.org/project/prompture
Built by Juan Denis