Give it any task in plain English. It writes the code, generates its own test cases, executes and validates everything, and self-corrects until all tests pass β no manual testing required.
Traditional AI code generation: LLM writes code β you test it β you debug it β repeat manually.
CodeFix AI: LLM writes code β agent tests it β agent debugs it β agent rewrites β repeats automatically.
You type: "Write a function that finds all duplicates in a list"
Agent does: generates tests β writes code β runs tests β fixes errors β passes β
You get: working, tested Python code
graph TD
A([User: Task Description]) --> B
B["π§ͺ generate_tests\nAuto-write pytest cases from task"]
B --> C
C["βοΈ generate_code\nLLM writes Python solution"]
C --> D
D["β‘ execute_code\nRun code directly β catch crashes"]
D -->|Execution crashed| E
D -->|Ran successfully| F
F["π¬ run_tests\nRun pytest with generated test cases"]
F -->|All tests PASS| G
F -->|Tests FAIL + retries left| E
F -->|Tests FAIL + max attempts| G
E["π analyze_error\nStructured diagnosis: root cause + fix plan"]
E --> C
G(["β
END: Return final code + metrics"])
style A fill:#1e1e3a,color:#e2e8f0,stroke:#6d28d9
style B fill:#1e1e3a,color:#818cf8,stroke:#818cf8
style C fill:#1e1e3a,color:#a78bfa,stroke:#a78bfa
style D fill:#1e1e3a,color:#fbbf24,stroke:#fbbf24
style E fill:#1e1e3a,color:#f87171,stroke:#f87171
style F fill:#1e1e3a,color:#2dd4bf,stroke:#2dd4bf
style G fill:#1e1e3a,color:#34d399,stroke:#34d399
sequenceDiagram
participant U as User
participant ST as Streamlit UI
participant LG as LangGraph
participant LLM as Groq LLM
participant PY as Python Subprocess
U->>ST: Task description
ST->>LG: stream(initial_state)
LG->>LLM: Generate test cases for task
LLM-->>LG: pytest test functions
LG-->>ST: Test cases ready
loop Until tests pass or max_attempts reached
LG->>LLM: Generate or fix code
LLM-->>LG: Python code
LG-->>ST: Code generated
LG->>PY: python solution.py
PY-->>LG: stdout/stderr
LG-->>ST: Execution result
alt Execution crashed
LG->>LLM: Analyze crash
LLM-->>LG: Root cause + fix plan
LG-->>ST: Error analysis shown
else Executed OK
LG->>PY: pytest test_solution.py
PY-->>LG: test results
LG-->>ST: Test results shown
alt All tests pass
LG-->>ST: Complete
else Tests fail
LG->>LLM: Analyze failures
LLM-->>LG: Root cause + fix plan
LG-->>ST: Error analysis shown
end
end
end
ST-->>U: Final code + metrics
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β USER (Browser) β
β Task input Β· Live output Β· Final code β
βββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββ
β HTTP
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β STREAMLIT (app.py) β
β session_state persistence Β· live render_all() β
βββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββ
β Python call
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGGRAPH STATEGRAPH (graph/pipeline.py) β
β β
β generate_tests β generate_code β execute_code β
β β² β β
β β crashβok β
β analyze_error ββββββ β
β β² run_tests β
β βββββββββ failβpass β
β βΌ β
β END β
ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββ
β API calls (3 nodes)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β GROQ API β Llama-3.3-70B β
β test_generator Β· code_generator Β· error_analyzer β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β subprocess
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LOCAL PYTHON SUBPROCESS (isolated) β
β execute_code Β· run_tests Β· tempfile sandbox β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
codefix-ai/
β
βββ agents/
β βββ state.py β AgentState TypedDict β shared schema
β βββ test_generator.py β Node β : auto-generates pytest cases from task
β βββ code_generator.py β Node β‘: writes/rewrites code (3 prompt strategies)
β βββ code_executor.py β Node β’: direct python run β catches crashes early
β βββ test_runner.py β Node β£: pytest in isolated subprocess
β βββ error_analyzer.py β Node β€: structured root cause diagnosis
β βββ __init__.py
β
βββ graph/
β βββ pipeline.py β LangGraph StateGraph + conditional retry edges
β βββ __init__.py
β
βββ .streamlit/
β βββ config.toml β Dark violet theme
β
βββ app.py β Streamlit UI (entry point)
βββ .env.example
βββ requirements.txt
βββ README.md
| Agent | Input | Output | Uses LLM? |
|---|---|---|---|
test_generator |
task |
generated_tests |
β |
code_generator |
task + error_analysis |
code |
β |
code_executor |
code |
execution_status, execution_output |
β |
test_runner |
code + generated_tests |
test_output, status |
β |
error_analyzer |
code + error_log |
error_analysis |
β |
3 LLM calls per retry cycle. Code execution and testing run locally β no API cost.
git clone https://github.com/kunwardhruv/codefix-ai
cd codefix-ai
pip install -r requirements.txt
# Get free API key at console.groq.com
copy .env.example .env
# Add: GROQ_API_KEY=gsk_...
streamlit run app.pyPalindrome Check
Write a function is_palindrome(s) that returns True if the string is a palindrome.
Ignore spaces, punctuation, and case.
"A man a plan a canal Panama" β True
FizzBuzz
Write a function fizzbuzz(n) that returns a list of strings 1 to n.
Multiples of 3 β "Fizz", 5 β "Buzz", both β "FizzBuzz", else number as string.
Anagram Groups
Write a function group_anagrams(words) that groups anagrams together.
["eat","tea","tan","ate","nat","bat"] β [["eat","tea","ate"],["tan","nat"],["bat"]]
Longest Substring Without Repeating
Write a function longest_unique_substring(s) that returns the length of the longest
substring without repeating characters. "abcabcbb" β 3
Flatten Nested List
Write a function flatten(lst) that flattens any depth of nested lists.
[1, [2, [3, [4]], 5]] β [1, 2, 3, 4, 5]
LRU Cache
Write a class LRUCache(capacity) with get(key) and put(key, value) methods.
Evict least recently used when over capacity. Standard library only.
Valid Sudoku
Write a function is_valid_sudoku(board) that takes a 9x9 grid (list of lists, "." for empty)
and returns True if no row, column, or 3x3 box has duplicate digits.
Word Ladder
Write a function word_ladder(begin_word, end_word, word_list) that returns the minimum
number of single-letter transformations to reach end_word. Return 0 if impossible.
Roman Numeral Round Trip
Write int_to_roman(num) and roman_to_int(s).
Must be perfect inverses: roman_to_int(int_to_roman(n)) == n for all n in 1-3999.
Expression Evaluator (no eval)
Write evaluate(expression) for math strings with +, -, *, / and parentheses.
No eval() allowed. "(1+2)*(3+4)" β 21. Handle operator precedence.
Why generate tests before code? Test-first forces the LLM to reason about what the code must do before how β higher first-attempt pass rate.
Why subprocess instead of exec()?
exec() runs untrusted LLM code in-process. A bad generation can crash the entire agent. Subprocess gives full isolation + 15s timeout.
Why a dedicated error_analyzer node? Raw traceback β code_generator = blind retry. Structured diagnosis (root cause + specific lines + fix plan) β targeted rewrite = fewer retries.
Why temperature=0? Code needs determinism. Randomness hurts correctness here.
Why session_state for results? Streamlit re-runs the whole script on every click. Without session_state, clicking any expander clears all output.
Dhruv Singh β AI/ML Engineer
- Portfolio: portfolio-singh-mu-53.vercel.app
- LinkedIn: linkedin.com/in/dhruv-singh-24nov2004
- GitHub: github.com/kunwardhruv
- Email: kunwarrdhruv@gmail.com