AI-Powered Workflow Generation System
Agent School dynamically creates workflows using LLMs. Instead of hardcoding scrapers and automation, describe what you want and get working code instantly.
Traditional approach: Write code for every data source
def fetch_luma_events(): ...
def fetch_eventbrite_events(): ...
def fetch_twitter_data(): ...
# Manually maintain hundreds of scrapersAgent School approach: Describe once, generate forever
$ python main.py
You: "Find hip-hop parties in SF within 5 miles"
Agent School: [Generates code, executes, returns results]Agent School uses a clean three-layer design:
Pure Python code with NO LLM calls
- Input: Structured parameters
{"location": "SF", "radius": 5} - Output: Structured data
[{"title": "...", "date": "..."}] - Method: API calls OR browser automation
- Lives in:
workflows/deterministic/
Example:
# workflows/deterministic/luma_scraper/workflow.py
def fetch_luma_events(location: str, radius: int, keywords: list) -> list[dict]:
# Pure Playwright automation code
# Runs the same every time
return eventsMulti-step workflows that combine LLM + deterministic code
- Step 1: Parse natural language → structured params (LLM)
- Step 2: Call deterministic workflow (Pure code)
- Step 3: Rank/filter results (LLM)
- Step 4: Format response (LLM)
- Lives in:
workflows/agent_plans/
Example:
{
"name": "personalized_event_finder",
"steps": [
{
"id": 1,
"type": "llm",
"action": "parse_preferences",
"prompt": "Extract location, keywords, size preference from: {user_input}",
"output_var": "params"
},
{
"id": 2,
"type": "deterministic",
"workflow": "luma_scraper",
"input_from": "params",
"output_var": "raw_events"
},
{
"id": 3,
"type": "llm",
"action": "rank_events",
"prompt": "Rank these events by user preferences: {params}",
"input_from": ["raw_events", "params"],
"output_var": "ranked_events"
}
]
}Natural language interface
- Analyzes user intent
- Routes to appropriate agent plan
- Guides users through creation
- Acts as conversational mentor
# Clone repository
git clone <repo-url>
cd agent-school
# Install dependencies (requires UV)
uv sync
# Copy environment template
cp .env.example .env
# Add your API keys to .env
# Need at least one: OPENAI_API_KEY or ANTHROPIC_API_KEYJust run and chat!
# Interactive mode
python main.py
# Or single query
python main.py chat "find tech events in San Francisco"Example conversation:
You: Find hip-hop parties in SF within 5 miles
Agent School: I don't have a workflow for Luma yet. Let's create one!
What platform: lu.ma
What should it do: Extract events from Luma
Create this workflow? Yes
[Generates deterministic workflow...]
Success! Workflow created: lu_ma_scraper
Method: browser (Luma API is paid)
You: Now find hip-hop parties in SF
Agent School: [Executes workflow and returns results]
Here are 3 hip-hop parties in SF:
1. Bass Night at The Midway - Jan 15
2. Hip-Hop Open Mic at Cafe Du Nord - Jan 17
...
# Create deterministic workflow
python main.py create-workflow lu.ma --desc "Scrape Luma events"
# Create agent plan
python main.py create-plan personalized_finder \
--uses luma_scraper \
--goal "Find personalized events"
# List all workflows
python main.py list-all
# View system info
python main.py infoagent-school/
├── agent_school/
│ ├── core/ # Three-layer system
│ │ ├── deterministic_generator.py # Layer 1: Pure code generator
│ │ ├── agent_planner.py # Layer 2: LLM orchestration
│ │ ├── router.py # Layer 3: Intent routing
│ │ ├── executor.py # Executes agent plans
│ │ ├── registry.py # Workflow discovery
│ │ └── validator.py # Schema validation
│ │
│ ├── utils/ # Utilities
│ │ ├── logger.py
│ │ ├── code_validator.py
│ │ └── browser_helper.py
│ │
│ ├── config.py # Configuration
│ └── optimized_prompts.py # LLM prompts
│
├── workflows/ # Generated workflows
│ ├── deterministic/ # Layer 1 storage
│ │ └── luma_scraper/
│ │ ├── workflow.py
│ │ ├── input_schema.json
│ │ ├── output_schema.json
│ │ └── metadata.json
│ │
│ ├── agent_plans/ # Layer 2 storage
│ │ └── personalized_event_finder/
│ │ ├── plan.json
│ │ └── metadata.json
│ │
│ └── registry.json # Auto-generated index
│
├── main.py # Natural language CLI
├── tests/ # Test suite
└── README.md
from agent_school.core import DeterministicGenerator
generator = DeterministicGenerator()
# LLM analyzes lu.ma and decides: API or browser?
# Result: API is paid → Use Playwright
workflow = generator.generate_workflow(
name="luma_scraper",
description="Extract events from Luma",
target_platform="lu.ma"
)
# Generated code is pure Python, no LLM calls
# Saved to: workflows/deterministic/luma_scraper/workflow.pyfrom agent_school.core import AgentPlanner
planner = AgentPlanner()
plan = planner.create_plan(
name="personalized_event_finder",
description="Find events matching user preferences",
goal="Return top 5 personalized events",
uses_workflows=["luma_scraper"],
example_inputs=[
"Find small startup events in SF",
"Hip-hop parties within 10 miles"
]
)
# Plan defines LLM + deterministic workflow orchestration
# Saved to: workflows/agent_plans/personalized_event_finder/plan.jsonfrom agent_school.core import Router
router = Router()
# Natural language input
response = router.route("Find tech events in SF within 5 miles")
# Router:
# 1. Detects intent: find_events
# 2. Finds matching plan: personalized_event_finder
# 3. Executes plan with Executor
# 4. Returns formatted resultsAll settings in .env:
# Required: At least one LLM API key
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
# Optional
LUMA_API_KEY=... # If you have paid Luma API access
# Settings
DEFAULT_LLM_PROVIDER=anthropic
CACHE_DIR=./workflows
DEBUG=false# Run fast tests (no LLM calls)
uv run pytest tests/
# Run all tests including LLM generation tests
uv run pytest tests/ --run-llm-tests
# Run specific test file
uv run pytest tests/test_config.py -vTest Results:
- 21/22 tests passing
- Config validation: PASS
- Registry operations: PASS
- Code validation: PASS
- Schema extraction: PASS
"Find YC co-founder events in SF this weekend"
"Get tech news from multiple sources and summarize"
"Track competitor pricing on 5 e-commerce sites"
"Find tweets about our product from last week"
- Natural language interface
- Conversational mentor guides you
- No commands to memorize
- Just describe what you want
- Three-layer clean architecture
- Schema validation at every boundary
- Comprehensive test coverage
- Technical CLI commands available
- MCP integration ready
- Dynamic tool generation
- MCP-compatible schemas
- Deterministic execution
- Composable workflows
Generated code goes through validation:
- Syntax checking
- Security analysis (no eval/exec without warning)
- Import whitelist
- Safe execution environment
For production:
- Run workflows in containers
- Implement rate limiting
- Add authentication
- Monitor executions
Modify agent_school/optimized_prompts.py to customize how code is generated:
WORKFLOW_SYSTEM_PROMPT = """
Your custom instructions here...
"""# The system learns new platforms automatically
generator = DeterministicGenerator()
generator.generate_workflow(
name="custom_scraper",
target_platform="example.com", # Any platform!
description="Extract data from example.com"
)
# LLM figures out how to scrape itplanner = AgentPlanner()
# Multi-source aggregation
plan = planner.create_plan(
name="multi_source_events",
uses_workflows=["luma_scraper", "eventbrite_scraper", "meetup_scraper"],
goal="Aggregate events from multiple sources"
)- Dynamic data source discovery (LLM searches for APIs/platforms)
- Visual workflow editor
- Hosted MCP server
- Workflow marketplace
- A/B testing for generated code
- Performance monitoring
- Cost tracking per workflow
- Multi-modal support (images, videos)
See examples/ directory for:
- Creating Luma event scraper
- Building personalized event finder
- Multi-source data aggregation
- Custom platform integration
python main.py # Interactive chat mode
python main.py chat "your query" # Single querypython main.py create-workflow <platform>
python main.py create-plan <name> --uses <workflows>
python main.py list-all
python main.py infoWorkflows must:
- Accept structured input (typed parameters)
- Return structured output (list of dicts)
- Have no LLM calls inside
- Be deterministic (same input → same output)
- Include error handling
Plans must:
- Define clear steps (llm or deterministic)
- Specify data flow (input_from, output_var)
- Reference existing workflows
- Include example inputs
Input schemas:
{
"location": "str",
"radius": "int",
"keywords": "list",
"optional_param": "str"
}Output schemas:
{
"type": "list",
"items": {
"title": "str",
"date": "str",
"location": "str",
"url": "str"
}
}Contributions welcome! Areas to improve:
- Add more platform integrations
- Improve code generation quality
- Add workflow templates
- Enhance natural language understanding
- Build web interface
[Add license]
[Add contact]
Built with: Anthropic Claude, OpenAI GPT, LangChain, LangGraph, Playwright, UV
Agent School v0.1.0 - Empowering LLMs to create their own tools