We are going to build a Spec-to-Code agent that turns a plain-English feature request into a multi-file Python project. It plans the architecture, generates each module, and runs a self-review loop before writing anything to disk. If you ship code that spans more than one file, this removes the busywork of bootstrapping structure and enforces consistency across modules.
What you'll need
- Python 3.10 or newer
- The OpenAI SDK:
pip install openai - An Oxlo.ai API key from https://portal.oxlo.ai
- An empty project directory
I host this on Oxlo.ai because its flat per-request pricing keeps costs predictable when I pass long system prompts and full file trees into the context window. You can see the exact plan details at https://oxlo.ai/pricing.
Step 1: Initialize the client
First, set up the OpenAI-compatible client pointing at Oxlo.ai. This single client will handle planning, generation, and review.
from openai import OpenAI
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key="YOUR_OXLO_API_KEY"
)
Step 2: Define the architecture planner
Before any code is written, the agent decides which files to create and how they interact. I use Kimi K2.6 on Oxlo.ai for this because it handles long-horizon agentic planning and reasoning well. Here is the system prompt I give it.
PLANNER_PROMPT = """You are a senior staff engineer. Given a user requirement, output a strict JSON object with no markdown formatting. The JSON must contain a single key "files" which is a list of objects. Each object must have "path" (relative file path) and "purpose" (one sentence describing what the file does). Design 3 to 6 files that together implement the requirement with clean separation of concerns."""
import json
def plan_architecture(spec: str) -> list[dict]:
response = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "system", "content": PLANNER_PROMPT},
{"role": "user", "content": spec},
],
)
raw = response.choices[0].message.content
# Strip accidental markdown fences
cleaned = raw.strip().removeprefix("
```json").removeprefix("```
").removesuffix("
```
").strip()
plan = json.loads(cleaned)
return plan["files"]
Step 3: Generate code for each module
With the file list ready, we generate implementation code. DeepSeek V3.2 on Oxlo.ai is my go-to for coding and reasoning, and it is available on the free tier so you can iterate without burning budget. I feed the entire architecture plan into every generation call so the model knows the intended imports and interfaces.
GENERATOR_PROMPT = """You are a production Python engineer. Implement the file described below so it integrates with the rest of the architecture. Output only valid Python code with no markdown fences. Include type hints, docstrings, and inline comments only where the logic is non-obvious."""
def generate_code(file_plan: dict, full_architecture: list[dict]) -> str:
context = json.dumps(full_architecture, indent=2)
user_msg = f"Architecture plan:\n{context}\n\nImplement this file: {file_plan['path']}\nPurpose: {file_plan['purpose']}"
response = client.chat.completions.create(
model="deepseek-v3.2",
messages=[
{"role": "system", "content": GENERATOR_PROMPT},
{"role": "user", "content": user_msg},
],
)
return response.choices[0].message.content.strip()
Step 4: Add a self-review loop
Generated code drifts. I run every file through Qwen 3 32B on Oxlo.ai to catch missing imports, interface mismatches, and style issues. Because Oxlo.ai uses request-based pricing instead of token-based billing, sending a two-thousand-line draft for review costs the same as a one-line prompt. That pricing model makes multi-step agentic loops practical.
REVIEWER_PROMPT = """You are a picky code reviewer. Review the provided Python file in the context of the overall architecture. Report only concrete problems: missing imports, incorrect type hints, broken interfaces, or untested edge cases. Keep your response under 200 words. If the file looks correct, reply with exactly the word PASS."""
def review_code(file_plan: dict, code: str, full_architecture: list[dict]) -> str:
context = json.dumps(full_architecture, indent=2)
user_msg = f"Architecture plan:\n{context}\n\nReview this file: {file_plan['path']}\n\n{code}"
response = client.chat.completions.create(
model="qwen-3-32b",
messages=[
{"role": "system", "content": REVIEWER_PROMPT},
{"role": "user", "content": user_msg},
],
)
return response.choices[0].message.content.strip()
Step 5: Orchestrate the pipeline and write to disk
Now wire everything together. The orchestrator takes a spec, runs the planner, generates each file, runs the review, and writes the final files into a timestamped output directory.
import datetime
from pathlib import Path
def build_project(spec: str, out_dir: str = "output") -> Path:
# Plan
files = plan_architecture(spec)
print(f"Planned {len(files)} files")
# Prepare output directory
ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
project_dir = Path(out_dir) / f"project_{ts}"
project_dir.mkdir(parents=True, exist_ok=True)
# Generate and review
for f in files:
print(f"Generating {f['path']} ...")
code = generate_code(f, files)
print(f"Reviewing {f['path']} ...")
review = review_code(f, code, files)
print(f" Review: {review[:120]}...")
file_path = project_dir / f["path"]
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(code, encoding="utf-8")
print(f" Wrote {file_path}")
return project_dir
if __name__ == "__main__":
spec = (
"Build a CLI task tracker that stores tasks in JSON. "
"Support commands: add, list, done, and delete. "
"Use a modular design with separate storage, CLI argument parsing, and business logic layers."
)
project_path = build_project(spec)
print(f"\nProject written to: {project_path}")
Run it
Save the script as build_agent.py, export your key, and execute it.
export OXLO_API_KEY="sk-oxlo.ai-..."
python build_agent.py
Typical output looks like this:
Planned 4 files
Generating cli.py ...
Reviewing cli.py ...
Review: PASS...
Wrote output/project_20250715_143022/cli.py
Generating storage.py ...
Reviewing storage.py ...
Review: Missing error handling for file not found. Add try/except block...
Wrote output/project_20250715_143022/storage.py
Generating tasks.py ...
Reviewing tasks.py ...
Review: PASS...
Wrote output/project_20250715_143022/tasks.py
Generating __init__.py ...
Reviewing __init__.py ...
Review: PASS...
Wrote output/project_20250715_143022/__init__.py
Project written to: output/project_20250715_143022
You can now cd into the generated directory and run python -m cli add "Buy milk" to test the result.
Wrap-up
This pipeline gives you a reproducible way to bootstrap multi-file projects from a single sentence. Two concrete next steps you can ship tomorrow: wire in an automated test runner that executes pytest on the generated code and feeds failures back to the generator for a fix loop, or add a retrieval step that indexes your internal library docs so the agent imports your real utils instead of reinventing them. Both workflows stay cheap on Oxlo.ai because long context rolls into the same flat per-request price.
Top comments (0)