No Plugins Needed, I Built a Fully Automated Coding Loop in OpenCode

Using DeepSeek-V4 for low-cost Loop Engineering

Share
No Plugins Needed, I Built a Fully Automated Coding Loop in OpenCode.
No Plugins Needed, I Built a Fully Automated Coding Loop in OpenCode. Image by gpt-image-2

Today I want to talk about how I built an agentic coding loop inside OpenCode. People call this Loop Engineering.

To show you how well this coding loop holds up, I used DeepSeek-V4-Pro and DeepSeek-V4-Flash for every example in this article. It turns out that with the right design, DeepSeek models can pull off high-quality coding loops at a very low cost.

All the source code in this article is available at the end of the post. Let's get into it.


Introduction

If you've been following the AI agent space recently, you've probably heard the term Loop Engineering. Claude Code and OpenClaw both mention it.

But nobody really explains what it means.

Until Andrew Ng posted a clear breakdown of what Loop Engineering actually is. That post gave me the direction I needed to build it inside OpenCode.


What Andrew Ng Says About the Coding Loop

Andrew Ng's explanation centers around this diagram:

3 key product development loops.
3 key product development loops. Image by Andrew Ng

Three loops, simply put:

  • The first loop is the code agent's implementation loop. You give the agent a product spec and a measurable target. The agent starts building features on its own, runs tests, and keeps iterating until every requirement in the spec is met.
  • The second loop is the engineer feedback loop. Here the engineer acts as QA for their own product. They test what the coding agent built, and check if it matches their vision. If something is off, they write a new spec and kick off another round in the first loop.
  • The third loop is the external feedback loop. Once the engineer is happy with the product, it goes to the open-source community or gets handed to a product team. Real user feedback comes in. The engineer collects that feedback regularly, feeds it back into the engineer feedback loop, and from there back into the code implementation loop.

All three loops keep running. With AI in the mix, they push the product forward until it gets to where it needs to be.


My Take on the Coding Loop

The way I see it, these three loops map to two commands in Claude or Codex: /goal and /loop.

/goal covers the first and second loops. Once a user writes a product requirements doc or a spec, they pass the task to the agent through the /goal command. The agent iterates on its own, runs its own tests, and opens a Pull Request.

Then the engineer reviews the code and tests it manually. If everything looks good, they merge the PR and ship.

Next comes the external feedback loop. You can use the /loop command to set up scheduled tasks that pull issues from GitHub or Jira on a timer. The agent turns those issues into requirement docs, and /goal takes it from there.

Use /goal to create a new task, and use /loop to schedule it to run on a timer.
Use /goal to create a new task, and use /loop to schedule it to run on a timer. Image by Author

There is a gap in the traditional understanding here. When a user calls /goal, they just pass in what they want done. How it gets done, and what the exit condition is, often gets left up to a strong reasoning model like Claude Opus or GPT 5.5 to figure out.

But in a proper coding loop, you need to give the agent a product spec and a measurable completion target so it knows when to exit. Something like this:

/goal Use the spec I wrote to build this chess game. 
Use Playwright MCP for end-to-end testing. 
Verify the game supports castling, pawn promotion, checkmate, stalemate, and rating calculation. 
Fix any bugs found during testing and re-run. Loop no more than 20 times.

That is a solid starting instruction for a coding loop. It needs a goal, a verification method, and a max iteration count. And you have to write something like that every single time, either right after the /goal command or inside the spec itself.

In my OpenCode version, I am not going that route. I just want to tell /goal what I want. The agent handles everything else.

The rest of this article shows you how I built that enhanced /goal loop. (The /loop command is a separate topic I will cover in a future post.)


See the Final Result First

Before getting into the implementation, let me show you what the /goal command actually does in a few scenarios, from simple to complex.

1. Write a Fibonacci script

This test checks whether the agent picks the best algorithm. The prompt is:

/goal Write a Fibonacci calculation script with the best possible performance.
What's pretty cool is that DeepSeek went with a fast doubling algorithm, and it's incredibly performant.
What's pretty cool is that DeepSeek went with a fast doubling algorithm, and it's incredibly performant. Image by Author

2. Build a Tower of Hanoi web game

Everyone knows this game. You could honestly just prompt an LLM directly and get it built. But that predictability is exactly what makes it useful for testing whether each step of the coding loop is working correctly.

The prompt is:

/goal Build a playable Tower of Hanoi web game.
The Towers of Hanoi game built using the /goal command comes with a built-in AI solver.
The Towers of Hanoi game built using the /goal command comes with a built-in AI solver. Image by Author

3. Build a chess web game

Maybe you are not impressed by the Tower of Hanoi example, since a regular prompt to any frontier model can do the same thing without a coding loop. Fair. The chess game experiment is something you should actually try for yourself.

The prompt is:

/goal Build a playable chess web game. 
Include easy, medium, and hard difficulty levels. 
No online multiplayer needed. 
Use a Python backend as the AI engine.
A full-stack chess game with both frontend and backend, built using the /goal command.
A full-stack chess game with both frontend and backend, built using the /goal command. Image by Author

In this experiment, OpenCode first does a quick requirements check with the user after receiving the task.

It offers suggestions along the way so you can just click next. Once the full requirements list is confirmed, it enters autonomous mode.

The /goal command breaks down your goal into a list of requirements and then implements them one by one.
The /goal command breaks down your goal into a list of requirements and then implements them one by one. Image by Author

It handles architecture design, builds each feature module, runs unit tests, edge case tests, and end-to-end tests. It only hands the result back to the user when everything passes.

Pretty cool, right? Want to know how it works? Let's go.


Building the Coding Loop

Overall design

OpenCode updates very fast. Almost every release breaks something or introduces small bugs. So I am not building yet another OpenCode plugin, since a plugin can easily break after an update.

The good news is that OpenCode lets you define commands and agents using plain Markdown files. Write a few lines of prompts, save the file as Markdown, and drop it in the right directory. That mechanism is the foundation for building a powerful coding loop on the cheap.

Let me walk you through the interaction flow of the whole loop.

When a user runs /goal <some task> to start a new coding task, OpenCode sends that task to an agent I call the orchestrator. In this setup, that agent is goal-orch.

The orchestrator's job is to talk to the user and review completed work. When it receives a task, it does not start coding right away. It first has a short conversation with the user to clarify the details, then breaks the task down into a list of atomic requirements.

This is different from OpenCode's built-in Plan agent. The /goal orchestrator does not ask open-ended questions. It takes its best guess at what the user wants and asks the user to confirm whether those sub-requirements are correct.

This works much better when the user is not a software engineer. It is like a capable assistant breaking down tasks for their manager without making the manager feel lost.

Once the requirements list is confirmed, the orchestrator saves it as a reqs-manifest.md file. This file tracks requirement status and serves as the acceptance record throughout the loop.

After that, the orchestrator enters autonomous mode. It starts an internal loop that calls a worker agent called goal-worker and sends each requirement to it.

goal-worker handles code implementation. Before writing any code, it does architecture planning first. If there are technology choices involved, it raises questions. It does not ask the user though. It asks goal-orch. Once goal-orch answers, goal-worker continues.

After the architecture plan is done, goal-worker enters the loop and starts implementing each requirement.

Each requirement includes feature code, edge case handling, and unit test code. When all of that is done, goal-worker sends an implementation report back to goal-orch.

The orchestrator checks the report against the requirement description, confirms completion, and updates the status in the requirements list.

Inside the loop, goal-orch also builds a DAG from the full requirements list to map out dependencies. Requirements with no dependencies between them get executed in parallel with multiple goal-worker instances, which speeds things up significantly.

Once all requirements are done, goal-orch runs acceptance tests against the list, checks unit test coverage, and for tasks involving frontend work, it launches end-to-end tests using browser use to confirm everything works.

When everything passes, the orchestrator writes an implementation report and notifies the user that the task is complete. Then it waits for the next task.

The execution sequence looks like this:

The sequence diagram for how the /goal command runs.
The sequence diagram for how the /goal command runs. Image by Author

Now, let me walk through how each piece is built.

Implementing the /goal command

Since we want /goal to be the entry point for the coding loop, just like in Claude Code, which is the first thing to build in OpenCode.

Thankfully, creating a command in OpenCode is pretty simple. Just drop a Markdown command definition file into the .opencode/commands/ directory.

Two things to keep in mind when writing the Markdown command file:

  1. In the frontmatter, configure a separate agent through the agent parameter. Without a dedicated agent, OpenCode sends the command straight to the default agent. The default agent has no Loop Engineering prompts, so the command fails. For /goal, I set up an orchestrator agent named goal-orch, which I will cover next.
  2. In the body of the command, use the $ARGUMENTS placeholder to represent the task the user passes when calling the command. When the command sends the message to the orchestrator, this placeholder gets replaced with whatever the user typed, and the full assembled message goes to the orchestrator.

Implementing the goal-orch agent

Now let's build the goal-orch agent, which acts as the orchestrator. It handles user communication, requirements clarification, kicks off the development loop, and calls goal-worker, and verifies that work is complete.

Since we have built OpenCode agents multiple times in previous articles, I will not go into every detail here. Just a few things worth noting:

  1. Model choice. goal-orch handles workflow orchestration overall, so it needs strong reasoning. I am a fan of the DeepSeek-V4 series, so I went with deepseek-v4-pro.
  2. System prompt. The prompt needs to cover both workflow orchestration and the agent's own tasks, so it is on the longer side. But that is fine. When you use /goal to send a task, the goal-orch system prompt automatically replaces OpenCode's default prompt, so there is no need to worry about excessive token usage.
  3. goal-orch must be a primary agent. OpenCode has two agent types: primary agents and subagents. The key difference is that primary agents can call subagents to delegate work, but subagents cannot. Since goal-orch needs to call goal-worker inside the loop, so it has to be a primary agent. The only downside is that it shows up in the agent list at the bottom of the OpenCode interface, but you get used to it.
  4. The interaction mechanism between primary and subagents. During the loop, when goal-worker hits a tricky problem or needs to make a technology choice, it does not ask the user. It returns the question to goal-orch through a session return. This requires goal-orch to answer the question and then continue the previous sub-session. OpenCode uses a task tool to send messages to subagents. This tool accepts a task_id parameter. The first call to the task tool opens a new subagent session, and the return value includes a task_id. After goal-orch answers goal-worker's question, it passes the answer and the previous task_id back into the task tool. This resumes the task in the original sub-session and preserves context.
  5. Put simply, it works like a foreman and a worker. The foreman sends the worker off to do a job. The worker gives the foreman a reference number. If the worker hits a problem, they come back and ask the foreman. The foreman solves the problem, takes the reference number and the answer back to the worker, and the worker picks up exactly where they left off. No starting over.
OpenCode uses task_id to keep track of the context in sub-sessions.
OpenCode uses task_id to keep track of the context in sub-sessions. Image by Author
  1. Parallel task execution. Even though we are building a fully automatic coding loop, the orchestrator can still run multiple goal-worker instances in parallel for requirements that have no dependencies on each other. This speeds up the overall task significantly. After goal-orch confirms the requirements list with the user, it does not jump straight into the coding loop. It first maps out the dependency relationships between requirements into a DAG. When it finds requirements with no dependencies between them, it kicks off parallel execution to finish the task faster.
The requirements are recalculated into a DAG based on their dependencies, and then executed concurrently.
The requirements are recalculated into a DAG based on their dependencies, and then executed concurrently. Image by Author
  1. Every completed task gets documented. A coding loop handles a large volume of requirements at once, and this process can run for hours. As the task keeps going, the context grows longer and the agent's ability to follow the prompt gets weaker. At that point, we cannot rely on session messages alone to track the status of each requirement. The orchestrator will start missing key steps in the workflow. So when designing goal-orch, I included a requirement in the prompt: subagents must not only update the requirement status in reqs-manifest.md after each step, they also generate a documentation note for each completed requirement. That way, once the coding loop ends, goal-orch can review those documents to see which tasks finished cleanly and which ones hit blockers that need human attention.
  2. End-to-end testing with browser use. Since we are going fully automatic, why not go all the way? When goal-orch detects that the task involves a frontend page, it calls the agent-browser skill or @playwright-mcp during the final review phase to run end-to-end tests, and captures screenshots as proof that the feature works. Since I am using deepseek-v4 models, I also call the @observer agent for image reading when needed. I covered the @observer agent implementation in a previous article.

That covers the notable design decisions behind goal-orch. I am not going to paste the full prompt here since prompts are easy to generate with an LLM once you understand the principles. Grab the full source code at the end of the article.

Now let's look at goal-worker.

Implementing the goal-worker agent

Compared to goal-orch, goal-worker is much simpler by design. It just does the work. The simpler its instructions, the better it performs. That said, I did set a few expectations for it in this coding loop:

  1. Model choice. For tasks that do not need deep reasoning, deepseek-v4-flash honestly outperforms pro. From my experience, in situations involving function calling and skill loading, flash is more accurate than pro and costs much less. So for goal-worker, which is all about execution, deepseek-v4-flash is the right call.
  2. Ask before acting. Even though it is a subagent, I gave goal-worker the ability to ask questions. Whether it is before starting or in the middle of a task, whenever it hits a technical question, goal-worker stops and asks goal-orch for input. This makes full use of the stronger reasoning model higher up in the chain.
  3. Plan first, then act. Just like the outer loop driven by goal-orchgoal-worker follows the same rule: plan before doing. Before implementing any new requirement, goal-worker writes out a plan that covers the tech stack, what it intends to change, and how it will handle unit tests and edge cases. That plan goes to goal-orch for review. Only after goal-orch signs off does goal-worker start coding. This mechanism maximizes the chance of a successful implementation.
  4. Use modern package managers. This is not strictly required, but in practice I noticed that DeepSeek tends to default to traditional tools like pip and npm for global dependency installs. As a developer, that is something I can not live with. So I explicitly require goal-worker to use modern package managers like uv and pnpm. This also keeps your environment clean when the coding loop is building something for you.

That is the full implementation plan for my OpenCode coding loop. I did not paste source code into the article body since all of it is at the end. Go grab it there.

I also tried to explain the thinking behind this coding loop and how to build it clearly enough that you could just drop this article into OpenCode and have it reconstruct a working /goal command for you. From there, tweak it however you want and build your own version of Loop Engineering. In the age of AI, what is really impossible anymore?

Before wrapping up, let me quickly cover how to actually use this coding loop.


How to Use This Coding Loop

First, go to the end of this article and open the GitHub link I shared. Then come back here and keep reading.

The source code for the coding loop lives in its own git repo. The only directory you need to care about is .opencode/. To use this coding loop across all your OpenCode projects, copy the agents and commands directories from that folder into ~/.config/opencode/, then restart OpenCode.

If you only want to try it in one specific project, just copy the .opencode/ directory into your project root and restart OpenCode.

If you just want to take it for a quick spin, clone the repo locally, create a new branch, and run opencode from that branch to start the environment.

After that, type the /goal command in OpenCode with whatever task you want the coding loop to handle. For example, if you want to build the typing practice game Andrew Ng mentioned in his post, just enter this:

/goal I want to build a typing practice web app for kids. 
At the bottom of the screen are 9 keys representing the positions of 10 fingers, with the thumbs sharing a wider spacebar key that takes up two slots. 
Above those 9 keys is a gradient-transparent rectangle. 
Letters fall down from the top toward that rectangle, aligned to their matching key positions. 
Press the right key as the letter enters the zone and it counts as a hit, triggering a hit effect. 
Consecutive correct hits build up increasingly dramatic effects. 
The falling speed gradually increases. 
At the top of the screen is a scoreboard that adds 1 point for each hit, with a pop animation. 
The whole thing should feel exciting and dopamine-triggering, with plenty of visual encouragement.
A typing mini-game created with /goal command.
A typing mini-game created with /goal command. Image by Author

You can be as detailed or as vague as you want. Either way, once you hit enter, the coding loop starts running. goal-orch will open a conversation with you to clarify the requirements.

You can fill in more details as the conversation develops, or just choose recommend for everything and go make yourself a coffee while it does the work.


Conclusion

That is the story of how I built this coding loop inside OpenCode. Before I wrap up, let me answer a few questions you might have.

1. Can open-source models support this coding loop?

Yes, I think so. In this article, I used deepseek-v4-pro for goal-orch and deepseek-v4-flash for goal-worker, and both worked well. With the strict constraints of the loop workflow in place, they can handle most of your tasks automatically.

Also, DeepSeek is releasing the official version of DeepSeek-V4 in mid-July. It will almost certainly come with post-training improvements, and I expect even better results from it.

2. What results should I expect?

The coding loop will spend hours working through your task, but do not set your expectations too high for what a single /goal run can produce. That is true even with the most powerful Claude or GPT models.

As Andrew Ng said, the code implementation loop is just the first of three loops. You need to step into the second loop, the engineer feedback loop. Try out what /goal produced, find all the bugs and things that do not match your vision, organize those into a new spec, and kick off another coding loop. Keep iterating. That is how the product gets better over time.

3. Can the coding loop replace SDD frameworks like OpenSpec?

No. They serve different scenarios.

The coding loop is great for product managers or team leads who want to quickly spin up a minimum viable product from market insights or their own ideas. It prioritizes speed and automation. It is for people who want to hand things off and let the agent run on its own.

But if your product is going to production, if you have high standards for code quality and implementation details, if you have a detailed product spec, and you are an experienced software engineer who knows exactly what the product should look like, then OpenSpec or another SDD plugin is the right tool. Start from a solid foundation and build your full product step by step.

I will keep updating this article as I use the loop more, and the Q&A section at the end will keep growing. If you have any questions, leave a comment, and I will get back to you as soon as I can.

Thanks for reading and subscribing. Next time you are sitting there sipping coffee while OpenCode codes away on its own, if this article comes to mind, please share it with a friend.



Further Reading

How I built a coding workflow in OpenCode, Oh-My-OpenCode-Slim, and OpenSpec that rivals Claude Code:

How I Use OpenCode, Oh-My-OpenCode-Slim, and OpenSpec to Build My Own AI Coding Environment
Ride the wave of AI coding, don’t get swept away by it

How I added a reflection agent to the OpenSpec workflow and got DeepSeek-V4 to match or beat Claude Opus:

Reflection SDD: Use a Reflection Harness to Level Up Your OpenSpec Workflow
Stop letting bad spec files tank your code quality

Still can't get your DeepSeek-V4 or GLM-5.2 to read images? Try my method:

DeepSeek-V4 Can’t Read Images? I Made It Read
Don’t wait for a multimodal model, you can use it now

You can grab the source code for this article right here:

GitHub - qtalen/super-goal: Without any plugins, implementing loop engineering right inside OpenCode
Without any plugins, implementing loop engineering right inside OpenCode - qtalen/super-goal