[Hands-On] Build a Self-Evolving Agent

... PLUS: DeepSeek Open-Sourced its Agent Harness

In today’s newsletter:

  • [Hands-On] Build a Self-Evolving Agent

  • DeepSeek Open-Sourced its Agent Harness

Reading time: 5 minutes.

Most AI agents can complete a task, but they cannot learn from what happens afterwards.

You can correct an agent, reject its answer, or rewrite part of its output. The agent may acknowledge the correction in the current conversation. Start a new session, however, and the same mistake can return.

The problem is not always the model. The application often has nowhere to keep the lesson.

In this project, we add that missing memory to a code-review agent. The agent reviews code, waits for an engineer to accept, reject, or edit each comment, and stores what the engineer taught it in Actian VectorAI DB.

Before the next review, the agent retrieves relevant lessons and similar past reviews. The model stays the same, but the context supplied to it improves.

The same loop can work for writing, research, support, and data-analysis agents. Human feedback becomes useful long-term when the application turns it into searchable memory and retrieves it during a related task.

Corrections Need Somewhere to Go

A normal code-review agent follows a short path:

Code -> Review -> Comments

The agent may produce useful comments, but the workflow ends before the engineer responds. Nothing records which comments were correct, which warnings were unsupported, or which recommendations needed editing.

We added three feedback actions:

  • Accept. The concern and recommendation were useful.

  • Reject. The comment was incorrect or unsupported in the current context.

  • Edit. The concern was useful, but the explanation or recommendation needed correction.

Each action carries a different lesson. Accept should reinforce a rule. Reject should tell the agent what to avoid. Edit should preserve the useful concern while replacing the incorrect part.

The models for that feedback are small:

class CommentFeedback(BaseModel):
    comment_id: str
    action: Literal["accept", "reject", "edit"]
    edited_comment: str = ""
    note: str = ""

The optional note matters. A rejection tells the agent that a comment failed. A rejection with a reason tells the agent why it failed and when the lesson should apply.

ExpeL Provides the Learning Pattern

The project follows the pattern described in ExpeL. ExpeL extracts natural-language lessons from previous experience and recalls them during later tasks.

No model retraining is required. The language model weights remain unchanged.

Instead, the application changes the context supplied to the model. A useful lesson from one task becomes guidance for a related task later.

For code review, the loop looks like this:

  1. Retrieve lessons from earlier reviews.

  2. Review the current code with those lessons.

  3. Collect an engineer’s response to every comment.

  4. Turn the responses into reusable rules.

  5. Store the rules and the complete review.

The model provides general code knowledge. The feedback tells the application how one team wants that knowledge applied.

Actian Stores Rules and Their History

The agent needs two kinds of memory. We store them in two Actian VectorAI DB collections:

  • review_insights. Short rules created from feedback.

  • review_trajectories. Complete reviews with comments and engineer decisions.

The distinction keeps retrieval useful. Insights give the model direct guidance. Trajectories give the model examples from related work.

Both collections use embeddings from BAAI/bge-small-en-v1.5. When new code arrives, the application embeds the code and asks Actian for the closest insights and trajectories.

This means the next function does not need to use the same names as the first one.

The Graph Reads Before It Writes

The complete workflow has five nodes:

builder.add_node("retrieve", retrieve_node)
builder.add_node("review", review_node)
builder.add_node("human_feedback", feedback_node)
builder.add_node("reflect", reflect_node)
builder.add_node("persist", persist_node)

Retrieve runs before Review. Reflect and Persist run after Human Feedback.

That order is fixed in LangGraph because memory retrieval should not depend on whether the language model decides to call a tool. Every review needs to check for relevant experience.

The model is used where interpretation is needed. The Review node analyzes the code. The Reflect node reads the original comment and engineer response, then writes a reusable lesson.

Once the engineer submits feedback, LangGraph resumes the same review using its original thread ID. The Reflect node receives the generated comments and the engineer’s decisions together.

In plain terms, the agent cannot teach itself that its own answer was correct. The engineer supplies that judgment.

More Memory Does Not Always Mean Better Output

A growing insight count proves that the database is receiving records. It does not prove that the records are useful.

Repeated feedback can create duplicate rules. A rejected comment may apply to one repository but not another. A rule can also become outdated when a team changes its framework or coding standards.

A larger version of this system needs:

  • Scopes. Rules should identify the repository, language, framework, or team they belong to.

  • Rule maintenance. Engineers need a way to edit, replace, or remove old lessons.

  • Evaluation. The team should track repeated false positives, edited comments, rejection rates, and defects found.

This current implementation tracks accepted, rejected, and edited comments for each review.

Build the Full Project

The complete project includes the LangGraph workflow, Actian collections, local BGE embeddings, Ollama structured output, and a Streamlit feedback interface.

The same design applies anywhere an agent performs similar tasks and receives reviewable human feedback. The task can change. The loop remains the same.

If human corrections disappear after every session, the agent will keep starting from zero. Once those corrections become searchable memory, the next task begins with experience.

DeepSeek has open-sourced DeepSeek Harness, the runtime that turns a language model into a working agent. The project can edit files, run shell commands, manage sessions, use subagents, and launch a local Web UI with one command:

npx @deepseek-ai/dsh web

The interesting part isn't that another free coding agent exists. It's that DeepSeek made every layer of the agent replaceable, including the loop that decides how the agent works.

The Model Is Only One Part of the Agent

A model can generate code, but it cannot inspect a repository or run a test by itself. The harness gives the model a working environment by assembling tools, permissions, context, persistence, and the loop that connects one action to the next.

That surrounding system decides whether the agent can recover from errors, remember previous steps, ask for approval, manage long tasks, or safely execute code.

Commercial coding agents package those decisions into a finished product. You can often add tools or instructions, but the underlying runtime remains the vendor's design.

DeepSeek Harness takes a different approach. Models, tools, skills, session storage, sandboxes, scheduling, the interface, and the agent loop are all plugins.

Nothing Gets a Privileged Core

DeepSeek Harness is built on Cordis, a plugin runtime that contributes services, typed events, and reversible effects to a shared context.

There is no central implementation that every extension must work around. The running agent is a tree of plugins assembled from configuration, and a plugin can be mounted beside an existing component instead of patching the component itself.

That distinction changes what developers can replace:

  • Model adapters decide which provider and model handle a request.

  • Tool plugins define what the model can call and how those calls execute.

  • Session plugins control how events are stored, replayed, resumed, and forked.

  • Sandbox providers decide where file operations and processes run.

  • Agent-loop plugins control how prompts, model requests, tool calls, and stopping conditions fit together.

A normal plugin system lets you add capabilities around the agent. DeepSeek Harness lets you replace the machinery inside it.

Swap the Loop, Not Just the Model

Model portability has become a standard feature. A framework accepts an OpenAI-compatible endpoint, so developers can move from one provider to another without rewriting the application.

The agent's behavior is usually less portable. Switching frameworks can mean giving up session semantics, permission rules, context management, retry behavior, and the exact loop used to call tools.

DeepSeek separates those concerns through capability seams. A service defines a contract, a provider implements it, and the rest of the system consumes the contract without depending on one implementation.

The model layer follows the same pattern. DeepSeek Harness includes a direct DeepSeek adapter and a multi-provider adapter for Anthropic, OpenAI, custom gateways, and self-hosted endpoints. Changing the model doesn't require changing the agent loop, and changing the loop doesn't require rewriting the model adapter.

That is the real value of making everything a plugin. Developers can change one architectural decision without inheriting a new agent from scratch.

One Runtime Can Become Several Agents

DeepSeek Harness ships with profiles that compose the plugin tree differently.

  • Standard mode provides a full coding agent with file editing, shell access, search, planning, goals, skills, subagents, and workflows.

  • Code mode exposes tools through a TypeScript SDK, allowing the model to combine several operations into one generated program.

  • Minimal mode keeps only a shell and file editor, creating a smaller environment for evaluating models without a large harness influencing the result.

  • Creator mode lets the agent inspect the running plugin tree, test plugins in memory, and assemble new presets.

These aren't four separate agent implementations. They are four compositions of the same runtime.

That makes configuration part of the architecture rather than a list of settings around a fixed product. A team can start with the standard profile, replace the local sandbox with a remote provider, add an internal tool, or remove everything that doesn't belong in a benchmark.

The Repository Is Written for Agents Too

The repository includes more than source code and a short README. Its architecture documentation maps the services, events, session lifecycle, capability boundaries, and plugin composition model.

DeepSeek also ships an AGENTS.md that tells coding agents how to explore and modify the project. It describes the package layout, testing commands, architectural rules, and where new behavior should live.

That file matters in a codebase designed to be extended by agents. An open repository gives an agent access to the code, but a machine-readable engineering guide gives the agent a path through it.

The harness can therefore help an agent understand the same runtime the agent is modifying.

Open Source Does Not Mean Zero Cost

The harness itself is free to use, modify, and distribute under the MIT license. The models it calls still need compute, whether that comes from DeepSeek's API, another provider, or infrastructure running an open model locally.

The comparison with Claude Code needs the same distinction. Claude Code is included in plans starting at $20 per month, while Anthropic's highest individual tier, Max 20x, costs $200 per month. That subscription covers model access and a maintained product, not only the agent harness.

DeepSeek isn't giving away free inference. It is making the runtime around inference available as infrastructure developers can own.

Developer Preview Means the Interface Will Move

DeepSeek is explicit that the project is still in developer preview and compatibility-breaking changes will happen. Its session format carries no compatibility promise, and the repository currently favors correcting the architecture over preserving interfaces for early consumers.

That makes DeepSeek Harness more useful as a foundation to study and build on than as a drop-in replacement for every mature coding agent today.

But the release still changes what developers can expect from an open agent. Access to the model is no longer the only part that can be separated from the vendor. The tools, state, permissions, interface, and even the loop can belong to the developer too.

Models will keep changing. The runtime that turns them into agents no longer has to change with them.

That’s all for today. Thank you for reading today’s edition. See you in the next issue with more AI Engineering insights.

PS: We curate this AI Engineering content for free, and your support means everything. If you find value in what you read, consider sharing it with a friend or two.

Your feedback is valuable: If there’s a topic you’re stuck on or curious about, reply to this email. We’re building this for you, and your feedback helps shape what we send.

WORK WITH US

Looking to promote your company, product, or service to 200K+ AI developers? Get in touch today by replying to this email.