{"slug": "don-t-let-codex-roam-free-6-guardrails-i-use-for-ai-assisted-coding", "title": "Don't Let Codex Roam Free: 6 Guardrails I Use for AI-Assisted Coding", "summary": "A developer who is self-teaching web development with Python and Flask shares six guardrails for using OpenAI's Codex in VS Code for AI-assisted coding. The developer emphasizes limiting task scope, writing tests before code changes, isolating test environments, and stopping Codex from fixing unrelated issues to maintain traceability. The approach includes using pytest to create an 'incident-prevention log' and separating test databases from production.", "body_md": "[https://github.com/tosane932/sales_data_app](https://github.com/tosane932/sales_data_app)\n\nThis article was originally published in Japanese on Qiita and has been translated and adapted for DEV Community.\n\nI currently work as a truck driver while teaching myself web application development using Python and Flask.\n\nRecently, I've been using Codex in VS Code while working on my personal application, including:\n\nWhen I read about AI-assisted coding, I often come across warnings like:\n\nIf you leave everything to AI, things can go badly wrong.\n\nI think that's true.\n\nBut after using Codex for a while, I started to feel that there is a big difference between:\n\n**letting AI roam free**\n\nand:\n\n**defining its working area before assigning the task.**\n\nIn this article, when I say \"guardrails,\" I mean deciding not only\n\nwhat Codex should do, but alsowhat it must not do and where it should stop.\n\nI'm still a beginner in programming, but these are the six guardrails I've started using when working with Codex.\n\nThe first thing I do is limit the scope of the task.\n\nIn other words:\n\n**What exactly are we changing this time?**\n\nFor example:\n\nI try to keep each task focused on one small theme.\n\nI also tell Codex:\n\nIf you find another problem outside the current scope, do not fix it automatically. Report it instead.\n\nThere is nothing wrong with Codex discovering another issue while investigating.\n\nBut if it keeps expanding the task and fixing additional problems along the way, I can eventually end up wondering:\n\n**What exactly changed?**\n\nSo I try to separate:\n\n**discovering a problem**\n\nfrom:\n\n**fixing a problem.**\n\nRecently, I've increasingly asked Codex to write pytest tests before modifying the production code.\n\nMy basic workflow is:\n\nFor example, when I strengthened input validation for my product master, I added 17 invalid-input cases.\n\nBefore the fix:\n\n```\n17 failed\n```\n\nAfter the fix:\n\n```\n17 passed\n```\n\nBy confirming that the test fails first, I can verify more than just:\n\n\"It seems safer now.\"I can confirm that the problem actually existed, that the test reproduced it, and that the change closed the gap.\n\nRecently, I've stopped thinking of pytest as just a way to confirm that the application works.\n\nInstead, I think of it more like an:\n\n**incident-prevention log.**\n\nOnce I discover a dangerous condition, I record it as a test so the application cannot silently return to that state later.\n\nDuring testing, I generally avoid connecting Codex-driven tests directly to:\n\nFor ordinary pytest runs, I separate the test database from the normal database and use a disposable in-memory SQLite database:\n\n```\nsqlite:///:memory:\n```\n\nFor regular tests, this gives me a fast and disposable environment.\n\nHowever, I do **not** assume SQLite can fully reproduce PostgreSQL-specific behavior.\n\nWhen I need to verify PostgreSQL-specific behavior or migrations, I create a separate isolated PostgreSQL environment.\n\nI separate things such as:\n\nfrom the normal environment.\n\nMy thinking is not:\n\n\"It's only a test, so it's probably fine.\"Instead:\n\n\"Test in a place where failure cannot easily spread into the normal environment.\"\n\nThe goal is not simply to avoid using the production or normal database.\n\nThe real goal is:\n\n**to reduce the impact if something goes wrong.**\n\nWhile Codex is investigating one issue, it sometimes discovers another unrelated problem.\n\nIn the past, I might have said:\n\nGo ahead and fix that too.\n\nNow I usually stop there.\n\nI increasingly tell Codex:\n\nIf you discover an unexpected problem, do not expand the current scope. Stop and report it.\n\nFor example:\n\n```\nCurrent task:\nValidate the sales POST endpoint\n        ↓\nCodex discovers another database issue\n        ↓\nDo not fix it immediately\n        ↓\nReport it as an unresolved issue\n        ↓\nCreate a separate task for it later\n```\n\nThis prevents a single change from becoming unnecessarily large.\n\nFor me:\n\n**being able to trace what changed is more important than fixing every discovered problem immediately.**\n\nEven after the code changes are complete and the tests pass, I don't immediately let Codex commit or push.\n\nFirst, I have it check things like:\n\n```\npytest -v\ngit diff --check\ngit status --short\ngit diff --stat\ngit diff\n```\n\nThen I review the results and check:\n\nOnly after that do I give permission:\n\n**\"Everything looks good up to this point. You can commit.\"**\n\nCodex can write code for me, but I don't want it to automatically pass through the final Git gate.\n\nAfter the commit, I also ask it to report:\n\n`git status`\n\nRecently, I've also started thinking that relying only on a written instruction like:\n\n**\"Do not push.\"**\n\nis not strong enough.\n\nIf I forget to include that instruction even once, the AI may interpret pushing as allowed.\n\nSo ideally, I want two layers of protection:\n\n```\nRestrict the action in the prompt\n+\nRestrict the actual permissions\n```\n\nIf I also want to account for human mistakes, simply saying:\n\n\"Don't do this.\"is weaker than creating an environment where the action is difficult or impossible without explicit permission.\n\nAfter pytest passes locally, the relevant pushes and Pull Requests trigger another pytest run through GitHub Actions.\n\nIn my current setup, GitHub Actions runs when:\n\n`main`\n\n`main`\n\nis createdIn another article, I compared this process to truck inspections.\n\nFor me, the analogy looks like this:\n\nThe task isn't finished just because Codex says:\n\nThe fix is complete!\n\nInstead, I try to make every change pass through several checkpoints:\n\n```\nCodex\n  ↓\npytest\n  ↓\ngit diff\n  ↓\ncommit\n  ↓\npush\n  ↓\nGitHub Actions\n```\n\nI don't use the AI's own response as the final source of truth.\n\nInstead:\n\n**I use other mechanisms to verify the work performed by the AI.**\n\nImagine giving Codex a prompt like:\n\nMake this application secure.\n\nThat's all.\n\nNow the AI has to guess many things:\n\nThat's a lot of decisions.\n\nWhat worries me isn't Codex itself.\n\nWhat worries me more is:\n\n**the human defining nothing and then delegating not only the work, but also all of the decisions to the AI.**\n\nDelegating work to AIanddumping everything on AImay look similar, but I think they are very different.\n\nWhen I thought about it, this approach felt surprisingly similar to my main job as a truck driver.\n\nNormally, you wouldn't tell a new driver:\n\nJust deliver this cargo somehow.\n\nYou would confirm things such as:\n\nAnd when something unusual occurs, there are situations where the right action is not to make an arbitrary decision and continue.\n\nSometimes the correct action is:\n\n**stop and confirm.**\n\nWhile working with Codex, I started thinking:\n\nThis is actually similar to assigning work to someone in the real world.\n\nI'm still relatively new to programming.\n\nThat means I cannot always evaluate 100% of Codex's output by myself.\n\nAnd that's exactly why I don't want to completely trust the AI and give it unlimited freedom.\n\nInstead, I try to create an environment where:\n\n**even if something goes wrong, the damage is less likely to spread.**\n\nThe same idea applies to the pytest improvements I've been working on.\n\nMy goal is not:\n\nBe careful not to cause the same bug again.\n\nMy goal is:\n\n**If the application ever returns to the same dangerous state, pytest should stop it.**\n\nI think the same way about Codex.\n\nI don't let Codex roam free.\n\n- Define the scope\n- Create failing tests first\n- Keep it away from normal databases and production\n- Make it stop when something unexpected appears\n- Review changes before commit and push\n- Inspect the result again with pytest and CI\nI create those guardrails first, and then I let the AI work inside them.\n\nAnd ideally, I don't want those guardrails to exist only in the prompt.\n\n**Where possible, I also want to enforce them through actual permissions and environment restrictions.**\n\nThat's something I plan to pay more attention to going forward.\n\n**Letting Codex roam free still scares me.\nBut with clear guardrails, I've found it can be extremely useful.**\n\nThat's what I've learned through my recent personal development work.", "url": "https://wpnews.pro/news/don-t-let-codex-roam-free-6-guardrails-i-use-for-ai-assisted-coding", "canonical_source": "https://dev.to/tosane932/dont-let-codex-roam-free-6-guardrails-i-use-for-ai-assisted-coding-4bj4", "published_at": "2026-08-21 08:01:14+00:00", "updated_at": "2026-08-21 08:14:33.092271+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "artificial-intelligence"], "entities": ["Codex", "VS Code", "Python", "Flask", "pytest", "SQLite", "PostgreSQL", "OpenAI"], "alternates": {"html": "https://wpnews.pro/news/don-t-let-codex-roam-free-6-guardrails-i-use-for-ai-assisted-coding", "markdown": "https://wpnews.pro/news/don-t-let-codex-roam-free-6-guardrails-i-use-for-ai-assisted-coding.md", "text": "https://wpnews.pro/news/don-t-let-codex-roam-free-6-guardrails-i-use-for-ai-assisted-coding.txt", "jsonld": "https://wpnews.pro/news/don-t-let-codex-roam-free-6-guardrails-i-use-for-ai-assisted-coding.jsonld"}}