An agent-based educational content workflow that generates a grade-appropriate lesson, evaluates it against a curriculum-quality rubric, and performs one feedback-driven revision when needed.
Built as an AI Developer Assessment, the project demonstrates structured LLM outputs, bounded multi-agent orchestration, validation, provider isolation, and a transparent Streamlit user experience.
- Two focused AI agents with explicit Generator and Reviewer responsibilities.
- Strict Pydantic contracts for every request and response.
- Gemini JSON Schema output instead of fragile text parsing.
- Review criteria covering age appropriateness, conceptual correctness, and clarity.
- Exactly one refinement pass, preventing unbounded agent loops and API usage.
- A visible execution trace containing the draft, review decision, feedback, and conditional revision.
- Actionable handling for authentication, model access, quota, timeout, and connection failures.
- Automated coverage for both orchestration branches and the initial UI interaction.
Grade + topic
|
v
Generator Agent
|
v
Structured explanation + 4 MCQs
|
v
Reviewer Agent
|
+-------------------+
| |
pass fail
| |
v v
Final draft Generator revises once
|
v
Refined output
The Reviewer receives both the generated content and the original grade/topic context. This makes the age-appropriateness decision meaningful without changing the Generator's required output schema.
ContentRequest, EducationalContent, MCQ, and ReviewResult are strict,
immutable Pydantic models. Gemini receives their JSON Schema and the application
validates every response before it enters the pipeline.
The agents depend on a small StructuredModel protocol rather than the Gemini SDK
directly. Provider-specific networking, retry policy, structured-output handling,
and errors remain isolated in education_agents/llm.py.
The orchestration contains one conditional refinement call instead of an open-ended loop. A passing review stops immediately; a failing review sends the original request, draft, and actionable feedback back to the Generator exactly once.
The Streamlit interface exposes every required stage, answer keys, raw JSON, and a downloadable pipeline result. It never stores the API key or provider response data in project files.
| Requirement | Implementation |
|---|---|
| Generator and Reviewer agents | GeneratorAgent, ReviewerAgent |
| Structured grade/topic input | ContentRequest |
| Structured explanation and MCQs | EducationalContent, MCQ |
| Grade-appropriate, correct content | Generator prompt contract |
| Pass/fail and actionable feedback | ReviewResult |
| Age, correctness, and clarity review | Reviewer rubric |
| One feedback-driven refinement | run_pipeline |
| Visible UI execution flow | app.py |
- Python 3.11+
- Google Gemini API through
google-genai - Pydantic 2
- Streamlit
- Pytest
- Ruff
education_agents/
├── agents.py # Generator and Reviewer responsibilities
├── llm.py # Gemini structured-output adapter and provider errors
├── models.py # Strict input, output, and pipeline contracts
├── pipeline.py # Generate → review → optional single refinement
└── prompts.py # Generation, review, and refinement prompt contracts
tests/
├── test_app.py # Streamlit startup and credential validation
└── test_pipeline.py # Pass and fail/refinement orchestration paths
app.py # Streamlit application
run.ps1 # Windows launcher pinned to the project environment
pyproject.toml # Dependencies and validation configuration
Requirements:
- Python 3.11 or newer
- A Gemini API key from Google AI Studio
From PowerShell:
python -m venv .venv
.venv\Scripts\python.exe -m pip install -e ".[dev]"
Copy-Item .env.example .envSet the real key in .env:
GEMINI_API_KEY=<your-gemini-api-key>
GEMINI_MODEL=gemini-2.5-flashLaunch with the project-local interpreter:
.\run.ps1Open http://localhost:8501, select a grade and topic, and choose
Run agent pipeline.
run.ps1 prevents a global Python or Anaconda installation from accidentally
starting the application without its declared dependencies.
.venv\Scripts\ruff.exe check .
.venv\Scripts\ruff.exe format --check .
.venv\Scripts\python.exe -m pytest
.venv\Scripts\python.exe -m pip checkThe pipeline tests use a deterministic provider boundary and therefore consume no API quota. They verify that a passing review stops after two model calls and that a failing review performs exactly one feedback-driven regeneration.
- Process environment variables take precedence over
.env. .env, virtual environments, caches, and build artifacts are ignored by Git.- API keys are never printed, committed, or written by the application.
- Free-tier prompts and responses may be used by Google to improve its products; do not submit private or sensitive content.
- Provider errors are categorized and displayed without exposing credentials or raw response bodies.
- Wrong Python environment: run
.\run.ps1. - Invalid API key: replace
GEMINI_API_KEYand restart the application. - HTTP 429 /
RESOURCE_EXHAUSTED: wait for the applicable Gemini quota window to reset. - Model unavailable: confirm that the configured project can access the model.
- Connection failure: check the internet connection, VPN, proxy, and firewall.
Ankit Kumar