We are going to build a spec-to-service agent that reads a plain-English API description and emits a deployable FastAPI project with tests and a Dockerfile. If you ship microservices often, this eliminates the repetitive scaffolding work so you can focus on business logic.
What you'll need
- Python 3.10 or newer
- The OpenAI SDK. Install it with
pip install openai - An Oxlo.ai API key from https://portal.oxlo.ai
Step 1: Bootstrap the environment and Oxlo.ai client
I always start by pinning the client configuration and the input spec. Create a new folder, then add a file named deploy_agent.py. We point the OpenAI SDK at Oxlo.ai so every request benefits from flat per-request pricing (see https://oxlo.ai/pricing), which keeps costs predictable even when we pass long specs.
import os
from pathlib import Path
from openai import OpenAI
# Oxlo.ai client setup
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=os.environ.get("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
)
OUTPUT_DIR = Path("./generated_service")
OUTPUT_DIR.mkdir(exist_ok=True)
SPEC = """
Build a FastAPI service for a task tracker with these endpoints:
- POST /tasks to create a task with title, description, and status.
- GET /tasks/{task_id} to retrieve a single task.
- GET /tasks to list all tasks with optional status filter.
Use an in-memory list for storage. Include Pydantic models and HTTPException handling.
"""
print("Client ready. Spec length:", len(SPEC))
Step 2: Define the system prompt
The system prompt governs how the model formats code. I keep it strict about output format so parsing stays simple and I do not have to clean up prose later.
SYSTEM_PROMPT = """You are a senior Python backend engineer.
Given a specification, output only valid Python code for a single FastAPI main.py file.
Do not include markdown fences, explanations, or ellipsis.
The code must be self-contained and runnable with uvicorn.
Include Pydantic models, router logic, and in-memory storage.
"""
print("Prompt loaded.")
Step 3: Generate the service layer
Now we call Oxlo.ai to generate the core application. I use DeepSeek V3.2 because it handles coding and reasoning well, and Oxlo.ai's request-based pricing means the long spec does not inflate the cost.
def generate_service(spec: str, system_prompt: str) -> str:
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
response = client.chat.completions.create(
model="deepseek-v3.2",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": spec},
],
)
return response.choices[0].message.content
service_code = generate_service(SPEC, SYSTEM_PROMPT)
service_code = service_code.replace("
```python", "").replace("```
", "").strip()
service_path = OUTPUT_DIR / "main.py"
service_path.write_text(service_code, encoding="utf-8")
print(f"Wrote service code to {service_path}")
Step 4: Generate tests and the Dockerfile
With the service in place, we generate a pytest suite and a Dockerfile. This second call uses a different system prompt and model to keep concerns separated. Because Oxlo.ai charges per request, splitting this into a second call still costs one flat fee.
TEST_SYSTEM_PROMPT = """You are a senior Python QA engineer.
Given a FastAPI service specification, output only valid Python test code using pytest and FastAPI's TestClient.
Do not include markdown fences or explanations.
Cover success paths and validation errors.
"""
DOCKER_SYSTEM_PROMPT = """You are a DevOps engineer.
Output only a valid Dockerfile for a Python 3.11 slim image that installs requirements and runs the FastAPI app with uvicorn.
Do not include markdown fences or explanations.
"""
def run_generation(system_prompt: str, user_content: str, model: str) -> str:
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
response = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_content},
],
)
return response.choices[0].message.content
test_code = run_generation(TEST_SYSTEM_PROMPT, SPEC, "llama-3.3-70b")
dockerfile = run_generation(DOCKER_SYSTEM_PROMPT, SPEC, "qwen-3-32b")
test_code = test_code.replace("
```python", "").replace("```
", "").strip()
dockerfile = dockerfile.replace("
```dockerfile", "").replace("```
", "").strip()
(OUTPUT_DIR / "test_main.py").write_text(test_code, encoding="utf-8")
(OUTPUT_DIR / "Dockerfile").write_text(dockerfile, encoding="utf-8")
print("Wrote test_main.py and Dockerfile.")
Step 5: Validate syntax and assemble
Before declaring success, we validate the generated code compiles. This catches most formatting issues from the model without needing to install dependencies.
import ast
def validate_python(path: Path) -> bool:
source = path.read_text(encoding="utf-8")
try:
ast.parse(source)
print(f"Syntax OK: {path.name}")
return True
except SyntaxError as e:
print(f"Syntax error in {path.name}: {e}")
return False
service_ok = validate_python(OUTPUT_DIR / "main.py")
tests_ok = validate_python(OUTPUT_DIR / "test_main.py")
reqs = ["fastapi", "uvicorn[standard]", "pydantic", "pytest", "httpx"]
(OUTPUT_DIR / "requirements.txt").write_text("\n".join(reqs), encoding="utf-8")
if service_ok and tests_ok:
print("All artifacts generated and validated.")
else:
print("Validation failed. Review the generated files.")
Run it
Execute the script from your terminal. Here is the complete flow and the expected output.
export OXLO_API_KEY="your-key-here"
python deploy_agent.py
Expected output:
Client ready. Spec length: 312
Prompt loaded.
Wrote service code to generated_service/main.py
Wrote test_main.py and Dockerfile.
Syntax OK: main.py
Syntax OK: test_main.py
All artifacts generated and validated.
You can now inspect generated_service/main.py, build the container with docker build -t myservice ./generated_service, or run the tests after installing requirements.
Wrap-up and next steps
This agent gives you a working scaffold in under a minute. Two concrete ways to extend it: add a third Oxlo.ai call that generates a GitHub Actions workflow for CI/CD, or wire the agent into a webhook so it rebuilds services automatically when your API specs change. Both are natural fits for Oxlo.ai's flat per-request pricing because agentic pipelines often involve long prompts and multiple round trips.
Top comments (0)