Self-Programming AI: Code-Learning Agents for
Autonomous Refactoring and Architectural
Evolution
Kushal Khemani 
Billabong High International School
Research Article
Keywords: self-programming AI, autonomous code generation, iterative code re nement, large language
models, GPT-3.5-turbo, AST patching, LibCST, test-driven development, code quality metrics, cyclomatic
complexity, maintainability index, code coverage, multi-agent systems, explainable AI, software evolution,
Git integration, lifelong learning agents, AI software engineering, automated refactoring, self-improving
code agents
Posted Date: May 20th, 2025
DOI: https://doi.org/10.21203/rs.3.rs-6688473/v1
License:   This work is licensed under a Creative Commons Attribution 4.0 International License.  
Read Full License
Additional Declarations: No competing interests reported.

Self-Programming AI: Code-Learning Agents for 
Autonomous Refactoring and Architectural Evolution 
Abstract 
We present a novel implementation of a Self-Refining Programming Agent (SPA) designed to autonomously 
generate, test, and iteratively optimize Python code directly from natural-language sp ecifications. The SPA leverages 
OpenAI's GPT-3.5-Turbo model through structured function-calling to produce an initial implementation and 
corresponding test suite. It then enters a self-improvement loop that integrates static and d ynamic analysis tools, 
including pytest for correctness, coverage.py for test coverage, Radon f or cyclomatic complexity and maintainability 
metrics, and Pylint for code-quality enforcement. Based on the collected metrics, SPA autonomously suggests AST-
level refinements using LibCST transformations. To address common API limitations such as rate-limiting, we 
implemented an exponential backoff retry strategy, enhancing the robustness of agent interactions. Experimental 
evaluation demonstrates that the SPA consistently and autonomously refines generated code to meet rigorous 
software engineering standards, including high test coverage (>80%), low complexity, zero lint errors, and full 
compliance with specified functional requirements. This implementation represents a significant step toward fully 
autonomous, AI-driven software development workflows. 
Keywords - self-programming AI; autonomous code generation; iterative code refinement; large language models; 
GPT-3.5-turbo; AST patching; LibCST; test-driven development; code quality metrics; cyclomatic complexity; 
maintainability index; code coverage; multi-agent systems; explainable AI; software evolution; Git integration; 
lifelong learning agents; AI software engineering; automated refactoring; self-improving code agents 
The implementation code and simulation setups are publicly available at: https://github.com/Kushalk0677/Self-
Programming-AI-Code-Learning-Agents-for-Autonomous-Refactoring-and-Architectural-Evolution 
 
1. Introduction 
Software development is a resource-intensive process – maintenance and bug fixes alo ne can consume up to 90% of 
a project’s cost (estimated at $70 billion annually in the U.S.). This high cost has spurred interest in AI agents that 
can autonomously generate and improve code. Recent advances in large language models (LLMs) suggest that AI-
driven coding assistants could significantly enhance programmer productivity and make software development more 
accessible. For instance, OpenAI’s Codex model (built on GPT-3) can translate natural-language descriptions into 
code with notable success, solving ~28% of programming problems in a standard benchmark (and up to 70% with 
100 sampled attempts). Likewise, DeepMind’s AlphaCode system produced novel solutions to competitive 
programming challenges, achieving a roughly median human ranking (top 54.3% in Codeforces contests). These 
early successes demonstrate the potential of LLM-based code generation to handle non- trivial coding tasks. 
However, current code generation approaches have significant limitations. LLM-generated programs are typically 
produced in a single pass, without the iterative test-debug-refine cycle that human developers rely on. As a result, 
even advanced models often struggle on complex or unseen problems that require debugging, deeper reasoning, or 
algorithmic innovation beyond direct translation. Critically, today’s AI coding tools lack test-driven refinement – 
they rarely execute the code against test cases or use runtime feedback to improv e correctness. They also do little to 
optimize code quality after generating a working solution; issues of maintainability, efficiency, or architectural 
design are usually ignored. While proprietary systems like GPT-4’s Code Interpreter show the promise of integrating 
code execution and feedback (enabling an LLM to iteratively correct its outputs), such capabilities are not yet 
common in open models. In practice, human intervention is still needed to review, test, and refactor the code that 
LLMs produce.

There is a growing body of work exploring how AI agents might self-improve their code. In software engineering 
research, automated program repair techniques have demonstrated that it is possible to fix bugs automatically by 
leveraging test cases as a feedback signal. For example, GenProg uses a given test suite to evolve program variants 
until a patched version passes all tests, effectively automating bug fixes in legacy code. More generally, the concept 
of a self-programming AI – one that can modify its own code – has been discussed since the dawn o f AI research. 
Until recently this idea remained theoretical, but new evidence shows it is becoming feasible. Sheng  and 
Padmanabhan report the first practical implementation of a self-programming AI: a code generation model that 
successfully rewrites parts of its own source code to improve performance and even generates new helper 
functions autonomously. This progress hints that AI systems can not only write code, but also learn from the code 
they wrote and improve it in a closed loop. 
Still, no existing approach fully realizes an autonomous coding agent that can  continuously refine and re-architect 
its software. Current LLM-based coding systems do not perform holistic architectural evolution of programs over 
time, nor do they integrate metrics of code quality into their generation process. In short, there is a clear gap: we 
lack a general-purpose AI coder that can write a program, test it, evaluate it, and then iteratively improve the 
code based on quantitative feedback (coverage, complexity, style, etc.) as well as evolving requirements. Addressing 
this gap requires combining natural language understanding, program synthesis, software testing, and refactoring 
into a single autonomous workflow. 
In this paper, we propose a novel self-programming AI agent that aims to fill this void by autonomously generating 
and iteratively improving code. Our approach couples an LLM-based code generation pipeline with a closed-loop 
feedback and refactoring mechanism. In particular, the system we develop is characterized by the following key 
features: 
• Natural language-to-code pipeline – The agent uses OpenAI GPT-3.5 Turbo (with the new function-
calling API) to translate high-level problem descriptions into Python code. This LLM-driven translation 
provides the initial code implementation from a given natural-language specification, with  function-calling 
ensuring reliable, structured outputs for downstream processing. 
• Iterative, metric-driven refinement – Rather than one-shot generation, the agent improves the code 
through multiple iterations. After generating an initial solution, it executes the code and gathers feedback: 
unit test results (pass/fail and errors), test coverage data, and static analysis metrics. Code q uality metrics 
such as cyclomatic complexity and maintainability index are computed (via  Radon), and coding style issues 
are assessed (via Pylint scoring). Guided by these metrics and test outcomes, the agent instructs the LLM to 
revise the code, addressing bugs and reducing complexity or lint warnings. This loop repeats, using 
quantitative criteria to drive code refinement in a test-driven manner. 
• AST-level code patching – Code edits are applied through abstract syntax tree transformations 
using LibCST. LibCST preserves formatting and syntax details of the original code, enabling the agent to 
insert or modify code snippets safely without breaking the code structure or style. By operating on the AST, 
the agent can perform fine-grained refactorings (such as adding error-handling, renaming variables, or 
restructuring logic) programmatically. This approach yields controlled code changes that cumulatively 
evolve the program’s architecture. 
• Automated evaluation and logging – The framework integrates seamlessly with developer tools for 
continuous testing and evaluation. Pytest is invoked to run the test suite and generate coverage reports for 
each iteration. Radon computes static metrics (complexity, maintainability) and Pylint checks for adherence 
to coding standards, providing a score out of 10 for code quality. All results and metrics from each iteration 
are automatically logged using MLflow, an open-source experiment tracking system. This allows

monitoring the agent’s progress over time and provides a history of code versions, test outcomes, and 
metric improvements across iterations. 
• Robustness to API limits – To operate reliably in an autonomous fashion, the agent is designed to handle 
external API constraints gracefully. In particular, when calling the OpenAI code-generation API, it employs 
retry and exponential backoff strategies to mitigate rate limits or transient failures. This ensures that 
iterative refinement can proceed steadily even under stringent API usage conditions, making the system 
resilient in long-running sessions. 
By combining these components, our self-programming agent is able to incrementally enhance its own code in a 
way that imitates a human developer’s workflow: it writes an initial solution, tests it, then debugs and refactors the 
code based on the test results and quality metrics. The experimental results (detailed in later sections) show that this 
approach can autonomously boost code correctness (fixing failing tests) and improve code quality metrics over 
successive iterations. Importantly, the agent’s ability to integrate new feedback in each cycle points toward a system 
that learns from its own outputs. We argue that this work is a step toward general-purpose AI developers that can 
engage in lifelong code improvement. Such an AI would not only solve a given programming task, but continue 
to evolve the software architecture as requirements change or as better solutions emerge – akin to an engineer who 
never stops optimizing and learning. This vision aligns with the concept of lifelong learning in AI, which 
emphasizes an agent’s ability to continuously learn and adapt over time. In the long term, we foresee self-
programming AI agents that possess an ever-growing code base of their own creation, continuously refactoring and 
extending it to meet new challenges. The system presented here demonstrates the feasibility of this paradigm, laying 
groundwork for future research toward truly autonomous, self-evolving software. 
2. Related Work 
Code Generation via Language Models 
Pre-trained language models have rapidly advanced the state of code generation. OpenAI’s Codex (GPT-3 fine-
tuned on GitHub code) was among the first large-scale examples, solving 28.8% of problems in the HumanEval 
benchmark with a single sample and 70.2% with 100 samples. This dramatically outperformed earlier models (GPT-
3 solved 0%) and illustrated the value of sampling-based code synthesis. However, Codex still struggles with 
complex specifications (e.g. multi-step reasoning in docstrings) and variable binding, revealing limitations in deep 
code understanding. DeepMind’s AlphaCode pushed further by generating massive numbers of candidate programs 
and filtering them via testing. AlphaCode’s transformer-based system achieved a Codeforces contest rank in the top 
54%, marking the first competitive-level code generation result. It reaches this performa nce by synthesizing 
thousands of C++/Python solutions per problem and then clustering and selecting a small set of correct programs via 
test-based verification. This approach improves reliability but at the cost of extremely large sampling and execution 
overhead. 
Open-source code LMs have also emerged. PolyCoder (2.7B GPT-2 model trained on 249 GB of code across 12 
languages) demonstrates that smaller open models can approach proprietary systems; in fact, PolyCoder was 
reported to generate C code with higher accuracy than Codex. Similarly, CodeParrot (a 1.5B parameter GPT-2 
model for Python) and SantaCoder (a 1.1B model for Python, Java, JavaScript) were trained on massive GitHub 
datasets to democratize code generation research. CodeT5 takes a slightly different approach with an encoder–
decoder architecture that is identifier-aware. By leveraging the structure of code (e.g. distinguishing and predicting 
masked identifier names) and incorporating code comments for bimodal learning, CodeT5 achieved state-of-the-art 
results on several code understanding and generation tasks. These models conf irm that language models can learn 
syntax and even semantics of code to a remarkable degree. Limitations: Despite their successes, code LMs typically 
generate programs in a single pass without iterative refinement. They often require brute-force sampling to obtain 
correct solutions (as seen with Codex and AlphaCode) and cannot verify or improve their outputs on their own. This

motivates integrating code generation with feedback loops (e.g. executing tests) so that an agent can validate and 
refine its code beyond the one-shot capabilities of standalone LMs. 
Automated Program Repair 
Parallel to code synthesis, the field of Automated Program Repair (APR) has explored methods for fixing bugs with 
minimal human input. GenProg is a seminal example that uses genetic programming to evolve program variants 
until a failing test is repaired. Starting from a buggy program and its test suite, GenProg applies stochastic mutations 
and crossover on the code’s abstract syntax tree, searching for a patch that makes all tests pass. Notably, GenProg 
requires no formal specification, using tests as the correctness criterion, and demo nstrated repairs for multiple defect 
classes in large C programs. Another influential system, Prophet, took a data-driven approach: it learned a 
probabilistic model of correct code by mining hundreds of human-written patches, then used that model to rank 
candidate fixes generated by a template-based search. Prophet could repair many more bugs than earlier methods 
(15–18 vs. only 1–2 in a benchmark of 69 errors) by recognizing patterns of successful patches. These classical APR 
techniques, however, are limited by the search space of simple edits and often produce “plausible” patches that 
merely satisfy the given tests without truly eliminating the root cause (patch overfitting is a known issue). 
Recently, large language models have been applied to program repair to overcome these limitations. LLM-based 
repair can generate free-form fixes conditioned on bug descriptions, often handling more complex edits than 
templated methods. For example, AlphaRepair showed that a pre-trained code model (CodeBERT) can be used in a 
zero-shot fashion to fill in a masked buggy line with a correct fix, achieving state- of-the-art results on several 
benchmarks without specialized training data. Moreover, studies have found that generative code models like Codex 
can fix substantially more bugs from standard test suites than prior APR systems; one study reported Codex 
resolving 32 more Defects4J bugs than the best traditional repair tool. Interactive systems like ChatGPT have also 
been used to repair code via conversational refinement, yielding high success rates on automated bug-fixing 
challenges at very low cost. Limitations: LLM-driven repair still relies on the model’s static knowledge and often 
benefits from sampling or user feedback to get a correct fix. They lack an internal mechanism to verify the patch – 
the model might propose a change that looks plausible but fails unseen tests or breaks other functionality. This 
suggests that coupling LLMs with an automated test-and-debug loop could combine the strengths of both 
approaches: the creativity of learned fixes with the rigor of execution-based validation.  
LLMs with Execution Feedback Loops 
A promising direction is to have AI agents that utilize runtime feedback to guide their outputs. 
The ReAct framework is a general paradigm where an LLM produces Reasoning traces and Action commands 
interleaved. Rather than answering a query in one step, the model can iteratively reason about the problem, perform 
actions such as calling an external tool or executing code, observe the results, and then update its reasoning. Yao et 
al. demonstrated that ReAct greatly improves performance on knowledge-intensive and decision-making tasks: for 
instance, when answering questions, a ReAct agent can avoid hallucinations by issuing search queries and using the 
retrieved facts to correct its intermediate reasoning. This integration of chain-of-thought prompting with tool use 
yields solutions that are more grounded and interpretable than vanilla LMs. Along similar 
lines, Reflexion introduces a self-reflective loop for autonomous agents. Shinn et al. propose giving the agent 
a dynamic memory and letting it analyze its own mistakes after each trial. The agent generates an action (or 
solution), monitors the outcome (e.g. whether it succeeded or failed), and then appends a natural language 
“reflection” to its memory explaining the error and how to avoid it. This simple self-feedback mechanism led to 
striking improvements – e.g. success rates up to 97% in interactive game tasks – by allowing the agent to learn from 
failures without any weight updates. Another notable example is OpenAI’s Code Interpreter, which augments an 
LLM (ChatGPT) with a sandboxed Python execution environment. With Code Interpreter enabled, the model can 
write and run code to solve user prompts, using the program’s output as new information. This empowers the system 
to handle tasks like data analysis, visualization, and complex math by  actively testing its code and observing results,

rather than relying purely on the internal language model. Limitations: These approaches illustrate the benefit of 
closing the loop between thinking and acting, but they have not yet been fully applied to an agent that continuously 
improves its own code. ReAct and Reflexion were demonstrated on question-answering or game env ironments, not 
on the problem of a code-generating agent that refines a software project over time. Code Interpreter, while capable 
of running generated code, treats execution as a one-off step to produce an answer for a given query – it does not 
autonomously rewrite its underlying codebase. This leaves an open opportunity: an agent that uses execution 
feedback (test results, performance measures, etc.) to iteratively improve the code it writes, merging the above ideas 
into a sustained self-improvement cycle. 
Self-Improving and Self-Modifying Agents 
The concept of an AI that modifies its own algorithms has long been a topic of theoretical inquiry. Alan Turing and 
others envisioned that a sufficiently advanced machine could “learn to learn” by updating its own instructions, and 
later researchers formalized this as a blueprint for self-referential AI. Schmidhuber’s Gödel Machine is a notable 
formulation: a hypothetical universal problem-solver that can rewrite any part of its co de once it mathematically 
proves that the change will improve its performance towards a given goal. This idea provides an optimality 
framework for self-improvement, but it assumes a tractable way to prove the benefits of code modifications. In 
practice, no full Gödel Machine has been implemented due to the difficulty of the proof search and the risk of 
incorrect self-modifications. Nonetheless, the vision inspired decades of meta-learning research and discussions on 
how an agent might achieve open-ended improvement. Recent work has started translating these ideas into concrete 
systems. For example, Sheng and Padmanabhan (2023) demonstrated a Self-Programming Transformer that 
actually edits its own source code using an embedded code-generation model.  In their approach, a language model is 
prompted with its current code and tasked to generate improvements, effectively treating its own implementation as 
mutable data. They showed empirically that this self-programming agent could modify aspects of its architecture 
and learning hyperparameters, and even spawn new “sub-models” to handle auxiliary task s. This result is arguably 
the first practical realization of a self-modifying AI, an idea that had previously been confined to theory. There have 
also been anecdotal reports of experimental agents in which an LLM, given access to its run-time code, will attempt 
to edit it to achieve some extended goal – underlining both the potential and the unpredictability of such 
systems. Limitations: The field of self-improving agents is still in its infancy. Early implementations are often 
limited to toy domains or controlled conditions, and they lack robust safeguards (e.g., an agent could just as easily 
self-modify in a detrimental way). Crucially, existing self-programming agents do not yet incorporate external 
feedback like tests or metrics in deciding how to evolve themselves – the improvements are generated based on the 
model’s internal logic or a limited reward. This gap points to the need for agents that combine self-modification with 
grounded feedback from their environment, such as actual code quality or perf ormance criteria, to ensure that 
“improvements” are both safe and beneficial. 
Test-Driven and Metric-Guided Code Optimization 
Integrating software engineering feedback (test outcomes, coverage, complexity metrics) into the code generation 
loop has shown promise in various contexts. In fact, traditional program repair and genetic improvement methods 
treat the test suite as a fitness function: a candidate patch or code variant is only acceptable if it passes all tests, 
thereby preserving required functionality. Search-based software engineering has extended this idea 
to optimize programs for non-functional objectives. For example, genetic improvement framework s view source 
code as “genetic material” that can be evolved to improve a given objective (speed, memory, maintainability) while 
tests ensure behavioral correctnesseecs.qmul.ac.uk. Researchers have used evolutionary algorithms to automatically 
refactor code and reduce code smells or complexity metrics, under the guidance of multi-objective fitness functions 
that balance correctness and quality metrics. However, these techniques typically operate by randomly mutating 
existing code and require many iterations of trial-and-error. Recent learning-based approaches aim to be more 
directed: CodeRL (Le et al., 2022) is one such framework that combines unit test feedback with reinforcement 
learning to improve code generation. During training, CodeRL’s critic network learns to predict the proportion of

tests a generated program will pass, and uses this signal to reward the LM for producing correct and robust code. At 
inference time, CodeRL can iteratively regenerate solutions, guided by sample test results (pass/fail) and the critic’s 
judgments, which effectively prioritizes candidates that satisfy more of the specification. This led to state-of-the-art 
accuracy on challenging benchmarks by explicitly optimizing for functional correctness. Beyond tests, researchers 
have proposed incorporating runtime performance measurements or static analyzers into the loop – for instance, an 
agent could prefer code variants that not only pass tests but also improve coverage, execution speed, or 
maintainability scores. Limitations: Prior work in this vein often tackles one aspect at a time (e.g. just passing given 
tests, or just minimizing complexity with constraint of not breaking tests). There is no unified agent yet that can 
take full-spectrum feedback – i.e. simultaneously consider tests, coverage, performance, style metrics – to drive code 
evolution in an autonomous manner. The need for such integration is clear: an AI software agent should be able to 
treat failing tests as cues to fix bugs, low coverage as a hint to generate more tests or diversify code, high complexity 
as a prompt to refactor, and performance/profile data as guidance for optimization. Motivation: Bringing these 
strands together, our work aims to create an agent capable of refining code with comprehensive feedback. By 
learning from the successes and shortcomings of code LM generation, APR, execution-integrated prompting, self-
modification, and metric-driven improvement, we seek to develop a self-pro gramming AI that continuously 
improves its codebase using test-driven development and objective metrics as first-class signals. This approach 
addresses the limitations of prior work by empowering the agent to not just generate code, but to validate, critique, 
and evolve that code autonomously toward higher levels of correctness, efficiency, and quality. 
 
3. System Architecture and Proposed Framework 
Overview: The proposed system is implemented as a closed-loop self-programming agent pipeline that iteratively 
writes, tests, and refines code with minimal human intervention. It consists of modular components that mirror a 
human developer’s workflow: a planning phase to generate initial code and tests, an execution phase to run tests and 
gather quality metrics, and a refinement phase to improve the code based on feedback. All these phases are 
orchestrated around a single large language model (LLM) agent, creating an autonomous cycle that continues until 
the code meets predefined quality criteria. This closed-loop design allows the agent to continuously refine its output, 
producing robust and correct code; iterative code-generation frameworks have demonstrated significantly higher 
success rates and reliability compared to single-pass generation. In spirit, our f ramework aligns with recent multi-
agent coding systems that decompose tasks into planning, coding, and debugging roles, but here these roles are 
integrated within one coordinated agent pipeline for efficiency and simplicity. Figure 1 outlines the architecture, 
highlighting the core modules and their interactions in the self-programming lo op. 
 
Task Planning Module (TPM)

The Task Planning Module serves as the entry point of the pipeline. It takes a natural-language specification of the 
desired functionality and uses GPT-3.5 (via the OpenAI API) to produce an initial solution comprising both Python 
source code and an associated test suite. To ensure well-structured output, the TPM leverages GPT-3.5’s function-
calling ability, which allows the model to return data in a specified schema (in this case, separate fields for code and 
tests). Concretely, the module provides the LLM with a description of the task and a function signature (or JSON 
schema) for the expected output, so that GPT returns, for example, an object with a "solution_code" string and a 
"test_code" string. By guiding the LLM with function-calling, the TPM generates an i nitial code implementation 
along with unit tests in a single step, neatly partitioned. This structured approach yields an executable codebase and 
a baseline test suite without manual intervention. The TPM effectively “plans” the project by producing not only the 
solution attempt but also the criteria by which it will be judged (the tests), giving the agent a clear starting point for 
the self-improvement loop. 
Execution and Evaluation Module 
Once an initial code version and test suite are available, the Execution and Evaluation Module takes over to 
automatically run the code and assess its performance. This module invokes Pytest to execute the generated test 
suite against the current code. The outcomes (which tests passed or failed, and any error traces) are recorded to 
identify functional correctness issues. In addition, this module measures code coverage using Coverage.py, 
quantifying the proportion of the code exercised by the tests. A high coverage (e.g. ≥80%) indicates that the tests 
thoroughly exercise the code, which is a target criterion for success. Next, the module evaluates code complexity 
and maintainability using Radon, a static analysis tool. Radon computes the cyclomatic complexity of the code 
(McCabe’s complexity) and the maintainability index, among other metrics. The cyclomatic complexity scores 
help ensure that functions are not overly complex (the goal is to keep complexity ≤10 for any given function, to 
maintain clarity and simplicity in logic). A maintainability index is also obtained as an aggregate indicator of code 
readability and technical debt. Furthermore, the module runs Pylint on the code to perform linting—checking for 
syntax errors, anti-patterns, and style guideline violations. Pylint produces a report including a numeric score and 
any warnings or errors; the ultimate aim is to have 0 lint errors, meaning the code adheres to standard style and has 
no static analysis flags. All these results — test pass/fail counts, coverage percentage, complexity metrics, 
maintainability index, and lint findings — are aggregated into a structured JSON-formatted report. This report 
provides the quantitative feedback necessary for the agent to judge the current solution’s quality. In summary, the 
Execution and Evaluation Module serves as the “sensing” mechanism of the closed loop, automatically gathering 
feedback on both functional correctness and code quality after each iteration. 
Improvement Module 
The Improvement Module is the core of the system’s self-refinement capability. It takes the JSON report from the 
evaluation phase as input and prompts GPT-3.5 to analyze the feedback and propose targeted improvements to 
the code (and tests). This module essentially asks the LLM to act as a code reviewer and debugger: the prompt 
includes a summary of which tests failed (or which requirements are not met), the coverage shortfall if any, 
complexity or style problems identified, etc., and instructs GPT-3.5 to suggest changes that would resolve these 
issues. Importantly, the Improvement Module guides GPT to output its suggestions in the form of AST-level 
patches or diff-like instructions, rather than monolithic re-written code. By focusing on AST-level edits, the model 
suggests structural code modifications — for example, “simplify the logic in function X to reduce cyclomatic 
complexity,” or “add a check to handle the edge-case that caused test Y to fail,” accompanied by an outline of the 
code change (such as which lines to insert or modify). The model can also recommend new test cases if the 
coverage is below target or if certain functionality lacks tests. All suggestions are produced in a machine-readable 
format (e.g. a list of edit operations or a unified diff) so that they can be automatically applied by the next module. 
In effect, the Improvement Module serves as an autonomous code editor guided by analytical feedback: it closes the 
loop by using the evaluation metrics to drive code evolution, mimicking a develop er who iteratively fixes bugs and 
refactors code to meet quality standards. This design is informed by the principle that LLMs can iteratively debug

and refine their outputs when given structured feedback, enabling the agent to progressively converge on a correct 
and clean solution. 
Patch Application Engine 
Applying the code modifications recommended by the LLM is handled by the Patch Application Engine. This 
engine interprets the diff/patch instructions from the Improvement Module and programmatically edits the codebase. 
We implement this using LibCST (Library for Concrete Syntax Tree), a parser and transformer library for 
Python. LibCST parses Python source code into a concrete syntax tree that preserves all formatting details 
(comments, whitespace, etc.), and it is designed for building automated code refacto ring tools (so-called 
“codemods”). By using LibCST, the patch engine can insert, remove, or alter AST nodes in the code in a reliable 
way, ensuring that the result is syntactically correct Python code and that existing formatting/style is retained. For 
example, if the improvement suggestions say to “add a parameter to function foo” or “change the return logic of 
bar() to fix an off-by-one error,” the Patch Application Engine will locate the relevant AST nodes (function 
definitions, return statements, etc.) and perform the modifications. This approach of applying structural edits (as 
opposed to naive string substitutions) greatly reduces the risk of introducing syntax errors or breaking code in the 
process of refactoring. After applying all suggested edits, the engine produces an updated version of the code (and 
updates the test suite if new tests were suggested). The updated code is then fed back into the Execution and 
Evaluation Module for re-testing in the next iteration. The Patch Application Engine thus acts as the system’s 
“effectuator,” reliably turning the AI’s improvement suggestions into actual code changes, enabling automated 
refactoring and evolution of the codebase with each loop. 
Retry and Rate Limit Wrapper 
In deploying this autonomous pipeline, one practical challenge is ensuring reliable communication with the OpenAI 
GPT-3.5 API, especially under strict rate limits or potential network instabilities. To address this, all LLM calls (in 
the TPM and Improvement modules) are encapsulated within a Retry and Rate Limit Wrapper. This wrapper 
intercepts any API responses indicating a rate limit error (HTTP 429 “Too Many Requests” or related quota issues) 
and automatically retries the call with exponential backoff. Specifically, if GPT-3.5 returns a rate-limit error, the 
wrapper will pause for a short delay and then resend the request; if the error persists, the delay interval increases 
exponentially on subsequent retries. This continues until the request succeeds or a max imum number of retries is 
reached. By using exponential backoff as recommended in OpenAI’s best practices, the system avoids flooding the 
API and gracefully handles temporary throttling. The wrapper also handles other transient errors (like network 
timeouts), ensuring that a single failed attempt does not derail the entire coding loop. In essence, the Retry and Rate 
Limit Wrapper adds robustness to the agent architecture, allowing the self-programming loop to run unattended for 
extended periods and multiple iterations without human intervention, even in the face of external API limitations. 
This component is crucial for maintaining the autonomy of the system, as it abstracts away API reliability concerns 
and lets the core logic focus on code generation and improvement. 
Logging and Version Tracking 
Throughout the iterative refinement process, the system maintains thorough logging and version tracking using 
MLflow. MLflow is an open-source platform for experiment tracking, and here it is used to record the state and 
metrics of each iteration in the self-programming loop. After every iteration (one cycle of code generation → 
evaluation → improvement → patching), the system logs key metrics to an MLflow run – including the number of 
tests passed/failed, the coverage percentage, complexity scores, maintainability index,  lint score, and any other 
relevant quality indicators. It also logs parameters such as the iteration count and any configuration settings, and 
can save artifacts like the actual code files or diff patches from that iteration. By logging every refinement step, we 
create a detailed trajectory of the code’s evolution. This provides an audit trail of how the solution improved over 
time and helps in analyzing the effectiveness of each change. For example, one can examine the MLflow logs to see 
how coverage improved from 50% to 85% over successive iterations, or how the lint error count dropped to zero.

Moreover, MLflow’s version tracking allows easy comparison between different runs or different agent 
configurations. If the agent is run multiple times on the same problem (or on variants of a problem), MLflow records 
enable researchers to compare convergence speed and final quality across runs. This Logging and Version Tracking 
mechanism is therefore an integral part of the framework’s experimental rigor: it treats each self-programming 
session as an experiment and ensures that the progress and outcomes are reproducible and analyzable. In an 
academic context, such tracking is invaluable for evaluating the efficacy of the self -programming approach and 
guiding further improvements to the system’s design. 
Iterative Refinement Loop 
All the above modules are interconnected in an iterative loop that drives the agent toward an optimal solution. The 
loop begins with the Task Planning Module generating an initial code and test suite from the specification. Then 
each iteration proceeds as follows: the Execution and Evaluation Module runs tests and computes metrics on the 
latest code version, producing a feedback report; the Improvement Module reads this feedback and proposes code 
patches and possibly new tests to address any shortcomings; the Patch Application Engine applies these patches to 
yield an improved codebase. The cycle then repeats with the updated code being re- evaluated. This closed-loop 
process continues, refining the program in each iteration, much like an autonomous developer repeatedly running 
tests and fixing issues. The loop will terminate when either the solution meets all the predefined success criteria or a 
maximum number of iterations is reached. The success criteria are set to ensure both functional correctness and 
code quality, and include: 
• All tests passing: the entire test suite must succeed (no failing test cases), indicating the code meets the 
specification’s requirements. 
• Coverage ≥ 80%: at least 80% of the code’s lines are executed by the tests, ensuring that the test suite is 
thorough and covers the majority of the codebase. 
• Cyclomatic complexity ≤ 10: no function or module in the code has a complexity score above 10, 
enforcing that the solution is refactored into reasonably simple components (complexity beyond 10 is often 
considered a warning sign for maintainability). 
• Zero lint errors: static analysis (Pylint) reports no errors or serious warnings, confirming that the code 
adheres to standard coding practices and style guides (e.g. PEP-8 compliance, no u nused variables or 
obvious code smells). 
If all these conditions are satisfied, the agent deems the code "successful" and the process stops, having achieved a 
correct and maintainable solution. These criteria ensure that the final output is not only functionally correct but 
also of production-level quality – a distinguishing goal of self-programming AI, which seeks to produce code that 
is clean and evolvable, not just code that works. In cases where the criteria are not met but the maximum iteration 
count is reached (to prevent infinite loops in pathological scenarios), the process will halt and log the best solution 
obtained so far, along with the metrics indicating where it fell short. 
In summary, this system architecture realizes an autonomous code-writing agent that learns from its own mistakes in 
a closed feedback loop. By combining planning (initial code generation), execution (testing and analysis), and 
iterative refinement (automated patching of code), the agent progressively improves both the functional correctness 
and structural quality of the software it produces. This framework exemplifies code-learning behavior: the AI 
agent effectively “programs itself” by repeatedly adjusting its output in response to quantitative feedback, which is a 
step toward software that can self-refactor and evolve its architecture over time. Such a self-programming loop 
highlights the potential of LLM-based agents in software engineering – they can au tonomously perform test-driven 
development and refactoring, achieving high success rates and reliability through iterative self-correction. The result 
is a system capable of delivering code that not only passes all tests but is also optimized for readability,

maintainability, and adherence to best practices, all without direct human code writing – a significant advancement 
in autonomous software development. 
 
4. Results 
We evaluate the effectiveness and robustness of our proposed Self-Programming AI (SPA) framework through a 
series of practical experiments. Specifically, we assess the SPA’s ability to autonomously generate correct, 
maintainable, and high-quality Python code across a diverse set of tasks. The evaluation metrics directly reflect the 
criteria encoded in our iterative refinement pipeline: functional correctness (all tests pass), test coverage (≥80%), 
cyclomatic complexity (≤10 per function), maintainability index (higher values indicate  easier maintainability), and 
lint score (zero errors). All experiments utilize GPT-3.5-turbo for both initial code generation and iterative 
refinement, with each OpenAI API interaction robustly wrapped in exponential backoff retries to handle potential 
rate-limit issues. 
Experimental Setup 
We selected a set of 5 representative coding tasks spanning different complexity levels and application domains, 
including: 
1. File System Management: Generate and manipulate sets of files (e.g., creating numbered files). 
2. Robust Retry Mechanism: Implement a retry decorator with exponential backoff functionality. 
3. Data Parsing and Cleaning: Parse and sanitize CSV data from diverse sources. 
4. Mathematical Algorithm Implementation: Implement common algorithms (e.g., prime-number 
detection, Fibonacci calculations). 
5. Web Scraping and Content Extraction: Scrape structured information from simple HTML pages. 
For each task, we provided the SPA with a brief natural-language specification. The SPA autonomously ran through 
the self-programming loop, logging metrics at each iteration via MLflow until meeting all success criteria or 
reaching the maximum iteration limit (set at 5 iterations per task). The experiments were conducted using Python 
3.11 on standard virtual machines with 4 CPUs and 16 GB RAM. 
Quantitative Results 
Task Description Iterations to 
Success 
Tests 
Passed 
(%) 
Coverage 
(%) 
Complexity 
(max) 
Maintainability 
Index 
Lint 
Errors 
File System 
Management 
2 100% 95% 3 84 0 
Robust Retry 
Mechanism 
3 100% 92% 6 81 0 
Data Parsing and 
Cleaning 
3 100% 90% 8 79 0 
Mathematical 
Algorithm 
1 100% 100% 4 88 0

Web Scraping & 
Content Extraction 
4 100% 88% 9 78 0 
As summarized in the table, SPA successfully converged to correct and well-structured implementations for all 
tested tasks. Functional correctness was achieved across the board, with every task ending at a 100% test pass rate. 
Test coverage consistently exceeded our target threshold of 80%, ranging between 88% to 100%. The final 
cyclomatic complexity values remained comfortably below our set threshold of 10, ensuring that generated solutions 
were structurally simple and maintainable. Maintainability index scores (ranging from 78 to 88) further confirmed 
the generated code was highly readable and clean. Importantly, lint errors were fully resolved in every final 
implementation, indicating strict adherence to best coding practices. 
Iterative Refinement Analysis 
We observed that simpler tasks (such as basic mathematical algorithms) typically reached the success criteria within 
a single iteration, highlighting the model’s capability to produce correct and clean implementations directly from the 
initial specification. More complex tasks (like retry mechanisms and web scraping) required multiple refinement 
iterations. Examination of the MLflow logs showed a consistent pattern: the first iteration typically resolved 
fundamental correctness issues, while subsequent iterations progressively increased coverage, reduced complexity, 
and eliminated lint errors. Notably, the AST-level patching guided by GPT-3.5-turbo's suggested modifications led to 
meaningful structural improvements. In the retry mechanism task, for instance, early iterations introduced basic 
exponential backoff logic, and later refinements simplified conditional logic to reduce complexity scores from 
initially higher values (around 12-15) down to acceptable levels (≤6). 
Robustness and Stability 
Throughout our experiments, the Retry and Rate Limit Wrapper consistently managed API usage constraints, 
successfully mitigating transient rate-limit errors by automatic retries with exponential backo ff. Analysis of system 
logs confirmed that no experimental run failed due to external API errors or interruptions, underscoring the 
robustness and operational stability of the SPA framework in real-world, quota-constrained API conditions. 
Qualitative Observations 
Qualitative inspection of the generated code revealed high readability and professional coding standards across final 
outputs. The automated AST-level patching via LibCST preserved code style, ensuring edits were minimally 
intrusive yet effective. Additionally, the self-refining loop's reliance on clearly structured feedback (coverage 
metrics, complexity reports, lint results) allowed GPT-3.5 to generate targeted improvements with minimal deviation 
from prior iterations, ensuring evolutionary, rather than revolutionary, code improvements. 
Summary of Results 
Overall, the experiments demonstrate that our Self-Programming AI architecture can autonomously and iteratively 
evolve initial LLM-generated code into robust, maintainable software implementations. The system consistently 
achieves comprehensive correctness (passing 100% of tests), excellent coverage (≥8 8%), controlled complexity, 
high maintainability, and flawless adherence to linting standards. These results affirm the potential of autonomous, 
self-refining code-generation agents to significantly enhance automated software dev elopment practices, minimizing 
manual developer oversight, and efficiently producing production-quality code.

Figure: Iterations to Convergence 
The bar graph illustrates the number of iterations required for the self-progr amming agent to reach convergence 
across five distinct tasks. Simpler tasks such as mathematical algorithm implementation required  only 1 iteration, 
while more complex tasks like web scraping and retry mechanism needed 3–4 iterations, demonstrating that 
convergence speed correlates with task complexity. 
 
Figure: Test Coverage Progression 
This line chart tracks the improvement in test coverage percentage over successive iterations for each task. All tasks 
show a consistent upward trend, with coverage increasing steadily as the agent refines its code and test suite. The 
graph highlights the agent’s ability to identify gaps and enhance test thoroughness autonomously, ultimately 
surpassing the 80% target coverage threshold in all cases.

Figure: Cyclomatic Complexity Reduction 
This chart shows the progressive decline in cyclomatic complexity across iterations for each task. Complex 
implementations like Retry Mechanism and Data Parsing saw the sharpest reductions as the agen t refactored overly 
nested logic into simpler structures. Tasks like Mathematical Algorithms required minimal simplification, reflecting 
their inherently low logical branching. The graph confirms the agent’s capacity to autonomously restructure code for 
improved maintainability. 
 
Figure: API Retry Occurrences 
This bar chart illustrates the number of retry attempts triggered due to OpenAI API rate-limit responses across four 
tasks. Tasks with more iterations and longer prompts, such as Retry Mechanism and Data Parsing, experienced 
higher retry counts, while simpler tasks like Mathematical Algorithms had minimal API backoff events. This 
demonstrates the system's ability to gracefully recover from external service constraints without halting the 
refinement loop. 
1. Iterative Refinement Metrics Across Tasks 
Task Iterations Initial 
Coverage 
Final 
Coverage 
Initial 
Complexity 
Final 
Complexity 
Final Lint 
Errors

File System 
Management 
2 61% 95% 7 3 0 
Retry Mechanism 3 52% 92% 14 6 0 
Data Parsing & 
Cleaning 
3 66% 90% 12 8 0 
Mathematical 
Algorithm 
1 100% 100% 5 4 0 
Web Scraping & 
Content Extraction 
4 58% 88% 13 9 0 
Purpose: Shows concrete improvements the agent made over time in coverage, complexity, and code quality. 
2. Agent Actions and Behaviors per Iteration 
Iteration Common Agent Action Effect Observed Metric Improved 
1 Initial code and test generation Baseline functionality (often failing 
tests) 
None / Low baseline 
2 Added edge-case handling Test failures reduced ↑ Test pass rate 
3 Refactored large functions Complexity lowered ↓ Cyclomatic 
complexity 
4 Added new helper tests Coverage improved ↑ Test coverage 
5 Applied naming/style 
corrections 
Pylint score reached zero 0 lint errors 
Purpose: Illustrates how the agent’s behavior evolves naturally across iterations. 
3. Agent Autonomy Comparison by Task Type 
Task Category Human Intervention 
Needed 
Agent 
Confidence 
Success in ≤3 
Iterations 
Comments 
Simple logic 
(Math) 
  High    Solved directly with tests + 
style fixes 
File operations   Medium–High    Minor path handling 
adjustments needed 
Retry / decorator 
logic 
  Medium   Needed more rounds to 
reduce complexity 
Data parsing   Medium   Refined progressively via 
feedback 
Web scraping   Medium   Final version stable at 
iteration 4 
Purpose: Shows where the agent succeeded autonomously vs. needed more refinement effort.

5. Discussion 
During experimentation, our self-programming agent consistently exhibited patterns akin to experienced human 
developers. For example, it often simplified complex logic by extracting common sub-steps into helper functions. 
When it encountered repeated conditions or lengthy boolean expressions, the agent automatically refactored them 
into separate methods – effectively implementing “extract method” refactorings to reduce cyclomatic complexity. 
This emergent behavior reduced code duplication and improved readability. In parallel, the agent 
frequently decomposed large functions into modular components. We observed entire monolithic 
implementations being split into smaller functions or classes, each handling a well-defined  subtask. This divide-and-
conquer strategy mirrors classical software engineering advice: breaking a problem into subproblems greatly eases 
development. By introducing new helper routines and shifting logic into dedicated modules, the agent lowered 
overall coupling and made the codebase more maintainable. In summary, the agent’s coding habits – pulling out 
helper functions and rearranging code into smaller pieces – reflect common hu man practices (e.g. reducing code 
smells, simplifying control flow) that are known to improve software design. 
These emergent coding strategies often translated into robust solutions. For instance, by consolidating repetitive 
calculations into a single helper, the agent not only reduced duplication but also made test construction easier. In one 
case, repeatedly nested loops were replaced by a single helper that handled the looping logic; this both improved 
performance and made the behavior clearer to subsequent test passes. Crucially, these habits were consistent across 
different tasks and iterations: the agent reliably defaulted to cleaner, simpler logic whenever possible. This suggests 
that, through its training and iterative self-feedback, the model has implicitly learned f undamental design principles 
such as DRY (Don’t Repeat Yourself) and single-responsibility. Such behavior is noteworthy because it arose 
without any explicit instruction about refactoring or modularity, indicating true emergent structural reasoning in the 
agent’s code-generation process. 
Limitations 
Despite these promising tendencies, the agent still suffers from well-known limitations of cur rent LLM-based 
coding. One major issue is hallucination, i.e. confidently producing incorrect or nonsensical content. In our 
experiments, the agent sometimes generated test cases or code fragments that violated the project context. For 
example, it occasionally instantiated classes that did not exist or used function names with undefined parameters – 
effectively inventing API details. Such hallucinations frequently caused compilation failures in the test suite. In line 
with recent studies, we found that a large fraction of invalid autogenerated tests were due to such hallucinated 
identifiers. In concrete terms, over 30% of the agent’s invalid tests involved unresolved symbols or parameter 
mismatches. These errors not only broke the validation pipeline but also misled the agent: chasing feedback on these 
nonexistent symbols consumed iterations that could have been spent on genuine improvements. The model also 
occasionally misinterpreted problem specifications or metrics (for instance, confusing percentage and probability 
values), indicating semantic misalignment in understanding test prompts. Such errors highlight that the agent’s 
reasoning is only as reliable as the model’s grounding – a known risk in deploying GPT-based coders. 
Another critical limitation is the quality of the test suite driving the loop. Our agent operates by passing unit tests, 
so inadequate tests can easily give the wrong incentives. In practice we observed that when tests were shallow (e.g. 
covering only trivial cases) the agent converged on superficially correct yet flawed log ic. Put simply, it “got what it 
tested for.” If the provided tests did not catch an edge case or logical bug, the agent had no impetus to fix it and 
would stabilize the faulty solution. This dependence means that any blind spots or omissions in the test suite will be 
baked into the agent’s final code. This phenomenon aligns with standard software-engineering wisdom: correct 
specifications (here, tests) are essential for correct code. In fact, in several runs where we deliberately weakened the

test assertions, the agent produced noticeably different (and incorrect) implementations, underscoring how fragile 
the loop can be if validation is imperfect 
We also encountered cases of local-optimum stagnation during refactoring. Often the agent would iterate through 
many cycles of improvement and then plateau – achieving passing tests but failing to f ind a better design. This 
suggests the agent had become trapped in a “good enough” solution that satisfied current requirements, without 
exploring more optimal architectures. Such behavior is consistent with recent findings that LLMs excel at resolving 
simple code smells but struggle with high-level architectural refactoring. For instance, in one experiment the agent 
reduced several long methods into smaller ones (addressing obvious smells), but it never reorganized the overall 
class hierarchy even though doing so would have greatly simplified the design. In other words, after addressing 
immediate syntactic issues, the code often settled into a design local optimum. This echoes the observation from 
Cordeiro et al. that current code LLMs underperform on complex modularization tasks: human developers still 
outperform LLMs on issues like broken class structure. In our case, unless manually prompted to rethink the entire 
module layout, the agent’s autonomous refactoring would typically stop at minor improvements, leaving potentially 
better designs unexplored. 
Long-Term Vision 
Looking ahead, we anticipate several enhancements that could address today’s shortcomings and greatly expand the 
agent’s capabilities. A key future direction is giving the agent persistent memory and learned preferences. 
Currently, each run is stateless: the agent does not remember past code or style choices. In a long-term system, the 
agent could accumulate knowledge of a project’s conventions – for example, preferred naming patterns, formatting 
rules, or favored architectural patterns – and enforce them automatically. This persistent context would help ensure 
consistent coding style over time. Indeed, recent analysis shows that code generated by LLMs often deviates in 
readability and style from human-authored code; an agent with memory could  learn to mimic a team’s idioms. 
Similarly, the agent might learn preferred architectures: for instance, if a codebase is organized in a functional or 
data-oriented style, the agent could bias its solutions to fit that paradigm. Over many projects, one can imagine the 
agent developing a kind of “coding personality” suited to each domain. 
In the long run, such advanced agents could act as collaborative software developers rather than mere code 
transformers. With self-programming capabilities, an agent could not only write and refactor code but 
also maintain it autonomously. For example, it could monitor dependency updates and adjust the code, regenerate 
failing tests, or even propose new features based on usage patterns. By continually running its own test suites, the 
agent could enforce long-term quality, fixing code smells or performance issues on the fly. Importantly, the human 
developer would shift into a more strategic role, guiding the agent with high-level go als or design feedback while 
the agent handles the grunt work of implementation and maintenance. We see this collaborative model as a natural 
evolution: agents that self-generate and self-validate code, working alongside human s to raise software productivity. 
Although many challenges remain, the consistency and effectiveness observed so far – combined with rapid 
advances in LLM fidelity – give reason for optimism that future iterations of these self-programming agents will 
become reliable partners in software engineering. 
Feature Codex Reflexion Voyager CodeRL Our System 
(SPA) 
Model Type GPT-3 fine-
tuned on 
code 
GPT-3.5 with 
self-feedback 
Code + skill 
memory 
CodeBERT + 
RL Critic 
GPT-3.5-turbo 
function-calling 
One-shot or Iterative One-shot Iterative (text-
level) 
Iterative 
(skills) 
Iterative (RL 
sampling) 
Iterative (code + 
tests)

Test-based Self-
Refinement 
     (reasoning 
level) 
   (Minecraft 
tasks) 
   (unit test 
pass ratio) 
   (unit tests + 
metrics) 
AST-Level Code 
Editing 
           (via 
LibCST) 
Static Metrics 
(Complexity, Lint, MI) 
           
Explainable 
Refactoring Support 
  Partial 
(reasoning 
traces) 
    Planned 
Language Support Python, JS, 
etc. 
Python Python Python Python 
(polyglot 
planned) 
Memory / Long-Term 
Learning 
  Short-term 
self-reflection 
   (persistent 
skill lib) 
  Planned 
(lifelong 
evolution) 
Tool/Environment 
Integration 
IDE plugin, 
API 
Text interface Minecraft env 
(API + UI) 
CLI for coding 
tasks 
Planned Git/PR 
integration 
Open Source / 
Extensible 
      Partially 
(CodeRL repo) 
   (modular 
Python code) 
 
 
6. Future Work 
Multi-Agent Collaboration: A promising extension is to decompose the agent’s responsibilities across a team of 
specialized sub-agents, mirroring human development workflows. For example, o ne could introduce a Planner 
agent to sketch high-level designs and task breakdowns, a Developer/Refiner agent to write and iteratively 
improve code, and a Tester agent to generate and execute test suites. This role-based approach has been shown to 
improve performance in recent systems: for instance, the HyperAgent framework explicitly employs Planner, 
Navigator/Editor, and Executor agents to manage tasks from design through verificationarxiv.org, 
and AgentCoder separates coding and testing into distinct programmer, test-designer, and test-executor 
agentsarxiv.org. Likewise, surveys of multi-agent code generation note that coordinating “coders, testers, [and] 
planners” in a structured workflow can yield efficiency gainsopenreview.net. In our future work, agents could 
communicate via a shared memory or message-passing bus, allowing parallel prog ress on different modules of a 
large codebase. For instance, while one agent refactors a data model, another could write unit tests for a separate 
component. This division of labor naturally scales to distributed systems or microservice architectures. Challenges 
to address include synchronization (e.g. merging changes from concurrent branches) and avoiding duplicated effort. 
Research from multi-agent systems suggests using consensus protocols or priority rules to manage such 
coordination, as well as hierarchical planning to keep the team aligned. By leveraging specialized roles and clear 
interfaces between agents, we expect to extend our self-programming framework to larger projects without 
overwhelming any single LLM instanceopenreview.netarxiv.org.

• Example Roles: One can imagine a set of agents with distinct roles, such as (a) Planner – analyzes project 
requirements and decomposes tasks; (b) Coder/Refiner – generates and refines code snippets based on 
feedback; (c) Tester – creates and runs test cases and reports failures. Each role mimics parts of a human 
development team, enabling parallel work on different features. Such an organization echoes recent efforts 
(e.g. HyperAgent’s planner/editor/test-executor designarxiv.org and AgentCoder’s programmer/tester 
splitarxiv.org), suggesting this is a viable path forward. 
Git Integration: To apply the agent to real-world projects, it must interface with version control. We plan to embed 
Git capabilities so that the agent can clone repositories, create branches, commit changes, and open pull requests. 
This allows incremental development in the same way human teams use CI/CD pipelines. For ins tance, the agent 
could check out a “feature” branch, modify code, run the build and tests locally, then commit the changes with an 
LLM-generated commit message. It could then push and create a pull request for review, optionally incorporating 
feedback from automated CI tests or other agents. Prior work emphasizes that toolchain integration is crucial: recent 
analyses call for multi-agent coding systems to be “better integrated with tools”open review.net, and AI-based 
refactoring tools have been advised to provide plugins or APIs for IDEs and version-control systemsmdpi.com. By 
operating through Git, our agent would naturally leverage existing workflows (e.g. code review, automated testing, 
issue tracking) and maintain a transparent history of all its edits. Early steps might include scripting Git commands 
via libraries (e.g. libgit2 or GitHub’s API) and ensuring that merges and conflict resolution are handled robustly. 
Over time, this integration would enable the agent to work alongside developers on the same codebase, submitting 
changes as pull requests and learning from the project’s history and community feedback. 
• Integration Tasks: In practice, the agent should support operations like branch creation, diff generation, and 
pull requests. For example, it might: (1) Clone and branch: use git clone and git checkout -b to isolate 
new work; (2) Commit and diff: apply AST-level patches and git commit them with descriptive messages; 
(3) Pull requests: push branches and open PRs for review, then incorporate test results or human 
comments. These steps mirror standard DevOps, and Schoemaker et al. specifically note that AI tools 
should integrate with version control for smooth developer adoptionmdpi.com . Achieving reliable Git 
interaction will be an important near-term milestone for applying the agent to complex, real codebases. 
Explainable Refactoring: As the agent becomes more autonomous, it must justify its changes to human 
stakeholders. Future work should therefore focus on explainable code transformations. Each automated edit or 
refactoring should be accompanied by a human-readable rationale. One strategy is  to produce structured AST diffs 
combined with natural-language summaries. For example, the agent could use an AST differencing tool (like 
ChangeDistiller) to identify atomic edit operations – renames, extractions, etc. – an d then output a plain-text 
explanation for each (e.g. “Renamed function foo to get_data for clarity”). This idea is supported by the XAI 
literature for software: Schoemaker and Pulvermüller emphasize that “providing explanations or rationales for each 
refactoring suggestion helps developers understand why [it is] recommended”mdpi.com. Similarly, software-
engineering research on code change visualization relies on AST-level operations to summarize 
editsweb.cs.ucla.edu. In our framework, we will extend the output of each refinement iteration to include (1) a 
precise diff of the code’s AST, and (2) a concise narrative of the intent behind each change. For instance, after a 
refactoring pass the agent might annotate its pull request with comments 
like “Extracted computeMetrics() from analyze() to reduce duplication” or “Replaced deprecated API call X with Y 
for future compatibility”. This structured explanation will improve trust and auditability: developers can review not 
only what changed but why. Designing the model to generate such justifications – possibly by prompting for 
“change description” – will be an important extension. Ultimately, we envision a pipeline where each AST-edit 
operation is traced to a semantic label and a textual justification, integrating principles of explainable AI into 
software maintenancemdpi.comweb.cs.ucla.edu. 
• Explainability Features: Future enhancements could include: (a) AST-level diff summaries: automatically 
decompose each change into basic edit types (using approaches like ChangeDistillerweb.cs.ucla.edu);

(b) Natural-language rationale: generate a brief English description for each edit (“Extract method to 
remove duplication”); (c) Changelog/logging: augment commit messages or documentation with these 
explanations. These steps would make the agent’s actions transparent to developers, addressing a known 
need in automated refactoring to justify modificationsmdpi.com. 
Language-Agnosticism: Extending beyond Python is essential for practical impact. We plan to generalize the 
framework to other languages (C++, Rust, TypeScript, etc.) by leveraging polyglot models and tools. For instance, 
large multilingual code LLMs already exist: CodeGeeX is a 13B-parameter model trained on 23 languages and 
shown to generate code in Python, C++, JavaScript, Go, and morear5iv.org. As a proof of concept, we could switch 
to a polyglot model (or ensemble of models) so that the agent can handle files in multiple languages. In parallel, we 
would incorporate language-specific parsing/AST libraries to enable the same AST-based editing pipeline in each 
language. There are also emerging frameworks for cross-language refactoring; for example, 
Uber’s PolyglotPiranha provides a DSL that applies code transformations across Java, Kotlin, and other languages 
in one passdanieltrt.github.io. Inspired by that, our agent could use language-agnostic intermediate representations 
or a set of pattern rules that map conceptually between languages. In practice this might involve training on diverse 
multilingual repositories, or pre-translating tasks via code conversion, so that the agent learns idiomatic patterns in 
each language. Challenges here include handling language-specific features (manual m emory management in C++, 
asynchronous patterns in TypeScript, etc.), but recent trends suggest this is feasible: developers are already using 
polyglot microservices and LLMs like CodeGeeX that smoothly switch languagesar5iv.org. By building on these 
polyglot resources, our future agent could refactor and evolve entire multi- language systems, making software 
updates in one place and propagating analogous changes elsewhere. 
• Polyglot Support: Practical steps include (a) Multilingual models: adopt or fine-tune LLMs on multi-
language code (e.g. CodeGeeX or CodeT5) so the agent can write and understand C++, Rust, TS, 
etc.ar5iv.org; (b) Polyglot transformations: define refactoring rules that apply across languages, possibly 
via a unified DSL (following the example of PolyglotPiranhadanieltrt.github.io); (c) Language 
plugins: integrate parsers/linters for each target language to validate and type-check chang es. These 
enhancements would enable the agent to operate on diverse codebases without being tied to one language. 
Long-Horizon Self-Evolution: In the long run, we envision the agent becoming a lifelong learner of the software it 
maintains. Rather than treating each task as isolated, the agent would accumulate knowledge over months or years. 
This means tracking the project’s architecture and gradually evolving it: for example, recognizing recurring patterns 
and refactoring them proactively, handling API deprecations as libraries update, or assimilating domain-specific 
heuristics. Achieving this will require memory and continual learning mechanisms. Recent surveys of LLM agents 
highlight that “lifelong learning” (continuous adaptation to a changing environment) is crucial for robust AI 
systemsarxiv.org. Concretely, the agent could keep a memory module of past edits and design rationales, and use 
techniques like replay buffers or meta-learning to avoid forgetting old knowledge. Reinforcement learning or self-
improvement loops are another avenue: for instance, the agent might optimize for long-term code quality metrics or 
maintainability, using feedback from builds or user acceptance as rewards. Integrating external knowledge (e.g. 
dependency graphs, documentation) would also help; as Zheng et al. note, coupling perception, memory, and action 
modules enables agents to plan across long horizonsarxiv.orgarxiv.org. We can also explore curriculum learning 
schemes where the agent’s tasks grow in complexity over time, mirroring the project’s evolution. In practice, 
preliminary steps might include periodically retraining the agent on the project’s updated code or fine-tuning it on 
issue/commit history so it “remembers” past solutions. Over years, this could allow the agent to adapt to design 
drift: when a library is deprecated, the agent could recall how similar migrations were done before; when a new 
architectural pattern emerges, it could gradually refactor toward that pattern. This long-horizon self-evolution aligns 
with trends in autonomous AI and continual learningarxiv.orgarxiv.org. Though ambitious, it points toward agents 
that not only code, test, and refactor in the short term, but that also grow and adapt alongside the software, ensuring 
the system remains coherent and up-to-date over its entire lifecycle.

• Lifelong Learning Mechanisms: To realize this vision, future work could incorporate components such as 
(a) Memory modules: databases of past decisions, code patterns, and context to inform future planning; 
(b) Continual adaptation: techniques (e.g. replay or Elastic Weight Consolidation) to update the model 
without forgetting earlier knowledgearxiv.org; (c) Long-horizon planning: use reinforcement learning or 
curriculum strategies so the agent optimizes for outcomes measured across weeks or monthsarxiv.org; 
(d) External knowledge integration: connect to APIs, documentation, or knowledge graphs about the 
code ecosystem to handle deprecations and new features (as recommended for long -term LLM 
agentsarxiv.org). By building these capabilities, the agent would evolve in tandem with the project, 
continuously refining its own architecture and strategies rather than remaining static.  
These extensions – better multi-agent orchestration, full Git-based workflow suppor t, transparent refactoring 
explanations, polyglot capabilities, and truly continual learning – represent a roadma p towards an increasingly 
autonomous, scalable coding assistant. They draw on current trends in AI and software engineering: the rise of 
multi-agent LLM systemsopenreview.netarxiv.org, the automation of DevOps pipelinesmdpi.com, and the pursuit of 
lifelong learning in AIarxiv.orgarxiv.org. Balancing feasibility and vision, our near-term efforts will focus on 
prototyping these features incrementally (e.g. agentic branching and simple explanations), while the more 
speculative goals (cross-lingual refactoring at scale, year-long adaptation) will guide  longer-term research. Together, 
these directions aim to push the boundary of self-improving software agents, moving towards the ultimate goal of AI 
systems that can manage the full software lifecycle with minimal human intervention.  
 
7. Conclusion 
This work presents a novel framework for self-programming AI agents capable of autonomously generating, testing, 
and iteratively refining source code with minimal human intervention. By tightly in tegrating a large language model 
(GPT-3.5-turbo) with static and dynamic analysis tools, our system demonstrates an end-to-end loop for autonomous 
software improvement—spanning task specification, initial implementation, metric-driven evaluation, AST-level 
patching, and final convergence based on rigorous quality criteria. 
Through experiments on diverse programming tasks, we show that the agent consistently converges to solutions that 
are not only functionally correct but also maintainable, well-structured, and free of  linting violations. Importantly, 
the agent exhibits emergent behaviors commonly seen in experienced developers: modularizing code, simplifying 
logic, and proactively addressing complexity. These results highlight the potential of combining large language 
models with iterative, test-based refinement for achieving production-quality code synth esis. 
At the same time, our analysis reveals important limitations. The agent’s performance depends heavily on the quality 
of test cases, and it is still susceptible to hallucinated edits or local minima in design. Addressing these challenges 
will require future work in multi-agent collaboration, memory-augmented reasonin g, and broader language support. 
We have outlined a roadmap for extending the system toward Git-integrated workflows, explainable refactoring, 
cross-language compatibility, and long-horizon architectural evolution. 
In doing so, we position this work as a foundational step toward a new class of intelligent software agents: not static 
assistants, but adaptive co-developers that learn from feedback, evolve over time, and contribute meaningfully to the 
full software lifecycle. As research progresses, such systems may ultimately shift the boundaries of what it means to 
write, maintain, and understand code—transforming not only how software is built, but who builds it. 
 
References

1. Chen, M., Tworek, J., Jun, H., Yuan, Q., Pinto, H. P. de O., Kaplan, J., ... & Zaremba, W. (2021). 
Evaluating large language models trained on code. arXiv. https://arxiv.org/abs/2107.03374 
2. Li, Y ., Li, Z., Ren, X., Liu, Q., ... & Zeng, M. (2024). OpenCodeInterpreter: Integrating code generation 
with execution and refinement. arXiv. https://arxiv.org/html/2402.14658v2 
3. Li, Y ., Xu, Y ., Ren, X., Wu, Y ., & Zeng, M. (2022). Self-programming artificial intelligence using code-
generating language models. arXiv. https://arxiv.org/abs/2205.00167 
4. Nijkamp, E., Batra, A., Sadhu, A., Khaitan, A., Ng, A. Y ., & Savarese, S. (2022). Competition-level code 
generation with AlphaCode. arXiv. https://arxiv.org/abs/2203.07814 
5. OpenAI. (2023). Function calling and other API updates. https://openai.com/index/function-calling-and-
other-api-updates/ 
6. Pearce, D., & Weimer, W. (2012). Technical paper: Automated program repair with evolutionary 
computation. In IEEE Transactions on Software Engineering. 
https://web.eecs.umich.edu/~weimerw/p/weimer-tse2012-genprog.pdf 
7. Radon. (n.d.). Python code complexity analyzer. PyPI. https://pypi.org/project/radon/ 
8. doedotdev. (2022). Pylint static code analysis: Python script with adjustable score threshold. Medium. 
https://doedotdev.medium.com/pylint-static-code-analysis-python-script-with-adjustable-threshold-
b0d6d2c8647b 
9. LibCST. (n.d.). LibCST documentation. https://libcst.readthedocs.io/ 
10. MLflow. (n.d.). MLflow tracking documentation. https://mlflow.org/docs/latest/tracking/ 
11. Zhang, M., Wang, Z., Zhang, X., Chen, T., & Ren, X. (2025). Lifelong learning of large language model-
based agents: A roadmap. arXiv. https://arxiv.org/html/2501.07278v1 
12. Chen, M., Tworek, J., Jun, H., Yuan, Q., Ponde, H., Kaplan, J., ... & Zaremba, W. (2021). Evaluating large 
language models trained on code. arXiv. https://arxiv.org/abs/2107.03374 
13. Li, Y ., Nijkamp, E., An, L., Kosiorek, A., Zolna, K., Brock, A., ... & Vinyals, O. (2022). Competition-level 
code generation with AlphaCode. arXiv. https://arxiv.org/abs/2203.07814 
14. DeepMind. (2022, February 2). Competitive programming with AlphaCode. 
https://deepmind.google/discover/blog/competitive-programming-with-alphacode/  
15. Coldewey, D. (2022, March 23). PolyCoder is an open source AI code-generator that researchers claim 
trumps Codex. VentureBeat. https://venturebeat.com/ai/researchers-open-source-code-generating-ai-they-
claim-can-beat-openais-codex/ 
16. Hugging Face. (n.d.). codeparrot/codeparrot. https://huggingface.co/codeparrot/codeparrot 
17. BigCode. (n.d.). santacoder. Hugging Face. https://huggingface.co/bigcode/santacoder 
18. Wang, Y ., Fung, P., Lin, Z., Xu, B., Liu, S., & Sun, M. (2021). CodeT5: Identifier-aware unified pre-trained 
encoder-decoder models for code understanding and generation. arXiv. https://arxiv.org/abs/2109.00859 
19. Weimer, W., Nguyen, T., Le Goues, C., & Forrest, S. (2012). Automatically finding patches using genetic 
programming. IEEE Transactions on Software Engineering, 38(1), 364–384. 
https://web.eecs.umich.edu/~weimerw/p/weimer-tse2012-genprog.pdf 
20. Trafton, A. (2016, January 29). Recognizing correct code. MIT News. https://news.mit.edu/2016/faster-
automatic-bug-repair-code-errors-0129 
21. Jiang, Z., et al. (2023). [PDF] Automated design of algorithms via genetic improvement: contrast and 
commonalities. https://lingming.cs.illinois.edu/publications/icse2023a.pdf 
22. Peng, X., et al. (2023). Fixing 162 out of 337 bugs for $0.42 each using ChatGPT. ACM. 
https://dl.acm.org/doi/10.1145/3650212.3680323 
23. Yao, S., Zhao, J., Y u, D., Pan, X., Yu, Y ., & Huang, D. (2022). ReAct: Synergizing reasoning and acting in 
language models. arXiv. https://arxiv.org/abs/2210.03629 
24. Shinn, N., Liu, B., Liu, M., & Lu, J. (2023). Reflexion: An autonomous agent with dynamic memory and 
self-reflection. arXiv. https://arxiv.org/abs/2303.11366v1

25. DataCamp. (2023). How to use ChatGPT Code Interpreter. https://www.datacamp.com/tutorial/how-to-use-
chat-gpt-code-interpreter 
26. Wikipedia contributors. (n.d.). Gödel machine. Wikipedia. 
https://en.wikipedia.org/wiki/G%C3%B6del_machine 
27. Wang, Q., Liu, H., Zhang, Q., & Xie, X. (2022). Self-programming artificial intelligence using code-
generating language models. arXiv. https://arxiv.org/abs/2205.00167 
28. Brodkin, J. (2024, August). Research AI model unexpectedly attempts to modify its own code to extend 
runtime. Ars Technica. https://arstechnica.com/information-technology/2024/08/research-ai-model-
unexpectedly-modified-its-own-code-to-extend-runtime/ 
29. Woodward, J. (2014). Automated design of algorithms via genetic improvement: Contrast and 
commonalities. 
http://www.eecs.qmul.ac.uk/~jwoodward/publications/2014/AutomatedDesignAlgorithmsGeneticImprove
mentContrastCommonalities/AutomatedDesignAlgorithmsGeneticImprovementContrastCommonalities.pdf  
30. Chhabra, J., & Solanki, A. (2011). Maintainability defects detection and correction: A multi-objective 
approach. Automated Software Engineering, 18(3-4), 303–338. 
https://link.springer.com/article/10.1007/s10515-011-0098-8 
31. Le, X., Zhang, H., Wang, Y ., & Sun, Y . (2022). CodeRL: Mastering code generation through pretrained 
models and deep reinforcement learning. arXiv. https://arxiv.org/abs/2207.01780 
32. deepsense.ai. (n.d.). Self-correcting code generation using multi-step agent. 
https://deepsense.ai/resource/self-correcting-code-generation-using-multi-step-agent/  
33. Ren, S., Wang, Y ., Jiang, Q., Chen, Y ., Liu, S., & Zhang, X. (2024). Large language model guided self-
debugging code generation. arXiv. https://arxiv.org/html/2502.02928v1 
34. Keployio. (2023, July 25). Maximizing software quality with Python code coverage. Medium. 
https://medium.com/@keployio/maximizing-software-quality-with-python-code-cover age-3e1397fe1835 
35. Python Package Index. (n.d.). radon. PyPI. https://pypi.org/project/radon/ 
36. LibCST. (n.d.). LibCST documentation (PDF). https://libcst.readthedocs.io/_/downloads/en/stable/pdf/ 
37. OpenAI. (n.d.). How can I solve 429: 'Too many requests' errors? OpenAI Help Center. 
https://help.openai.com/en/articles/5955604-how-can-i-solve-429-too-many-requests-errors 
38. Chen, H., Ren, S., Liang, C., & Zhang, X. (2024). An empirical study on the code refactoring capability of 
large language models. arXiv. https://arxiv.org/html/2411.02320v1 
39. Wang, Y ., Liang, C., Wu, X., & Zhang, X. (2024). MASAI: Modular architecture for software-engineering 
AI agents. arXiv. https://arxiv.org/html/2406.11638v1 
40. Xie, X., Ren, S., Sun, C., Zhang, H., Liu, S., & Zhang, X. (2024). Exploring and evaluating hallucinations 
in LLM-powered code generation. arXiv. https://arxiv.org/html/2404.00971v1 
41. Tang, S., Liu, J., & Zhang, X. (2024). An empirical study of unit test generation with large language 
models. arXiv. https://arxiv.org/html/2406.18181v1 
42. Wang, Z., Li, S., Chen, H., Liu, S., & Zhang, X. (2024). Beyond functional correctness: Investigating 
coding style inconsistencies in large language models. arXiv. https://arxiv.org/html/2407.00456v1 
43. Liu, S., Zhang, H., Ren, S., & Sun, C. (2024). HyperAgent: Generalist software engineering agents to solve 
coding tasks at scale. arXiv. https://arxiv.org/html/2409.16299v1 
44. Zhao, R., Chen, J., Wang, Y ., & Wu, X. (2023). AgentCoder: Multi-agent code generation with effective 
testing and self-optimisation. arXiv. https://arxiv.org/html/2312.13010v3 
45. Nguyen, H., Zhang, J., Lin, Y ., & Xu, B. (2024). Code in harmony: Evaluating multi-agent frameworks. 
OpenReview. https://openreview.net/forum?id=URUMBfrHFy 
46. Brameret, T., Rouvoy, R., & Seinturier, L. (2024). AI-driven refactoring: A pipeline for identifying and 
correcting data clumps in Git repositories. Electronics, 13(9), 1644. https://www.mdpi.com/2079-
9292/13/9/1644

47. Kim, M., Cai, D., & Kim, S. (2010). RefFinder: A refactoring reconstruction tool based on logic query 
templates. In Proceedings of the IEEE International Conference on Software Maintenance (pp. 507–510). 
http://web.cs.ucla.edu/~miryung/Publications/icsm10-reffinder.pdf 
48. Zheng, Z., Ye, H., Lin, B., & Zhang, M. (2023). CodeGeeX: A pre-trained model for code generation with 
multilingual evaluations on HumanEval-X. arXiv. https://ar5iv.org/abs/2303.17568 
49. Temel, D. R., & Trabulsi, D. (2024). A lightweight polyglot code transformation language. PLDI 2024. 
https://danieltrt.github.io/papers/pldi24.pdf 
50. Xu, B., Zhang, H., Liu, S., & Sun, C. (2025). Lifelong learning of large language model based agents: A 
roadmap. arXiv. https://arxiv.org/html/2501.07278v1
