Seven Projects, One Workflow: How I Split My Agents into Core and Adapter
I develop seven projects on four stacks on my own, all with the same agent workflow. How that came about, why I had to split the workflow into core and adapter to make it work, and what six weeks of session data show about my share of the work.
10/18/2026
•17 min readNote on the Content
This series describes my insights from using AI in the software development process. These are personal experiences and conclusions from which I derived measures that worked for my projects. The series does not claim to be a comprehensive guide or universally valid — it is meant as inspiration for your own projects.
I currently develop seven projects on my own: four private ones (three Flutter apps and a Nuxt application) and three for my employer (a Nuxt application with a FastAPI backend, a FastAPI service and a VS Code plugin written in React). All of them run on the same agent workflow. This blog and the landing pages of Atomin, Hamini and Mealkat were built with it and are online. The Atomin and Hamini apps are live and have customers, and I am preparing Mealkat for its release. I consider the quality high, even though bugs still slip through; the section "Where I Still Step In" shows where.
This workflow is the only way I can move several projects forward in parallel without burning out. It grew out of an experiment that has been with me since the agentic coding series: finding out how far agents can be pushed and how much autonomy I can give them step by step. Today I usually describe a feature in three to five sentences, and the pipeline takes it all the way to the PR.
This post tells how the workflow went from one project to seven and what I had to change about it along the way. It is the first of three parts. Part 2 and Part 3 show how I then measured and reduced token consumption.
One Workflow, One Repository
In the agentic coding series I described how a single prompt turned into a team of specialised agents: business analyst, solution architect, developer and test agent, handing their work to each other through documents such as the implementation plan. That worked, in exactly one repository: the Mealkat Flutter app.
Then I wanted to take the team into a second project. The plan was
unremarkable: copy .claude/, start Claude Code, keep working.
The solution architect lectured about directories that did not exist in the new project. The developer agent insisted on a codegen step the new stack does not know. The test agent demanded a framework that was not installed. And an agent I had adopted from another setup had never been runnable in any of my projects. It carried assumptions from a different stack, and nobody had noticed, because it never produced a hard error. It simply answered plausibly.
This is the failure mode that has occupied me most ever since: an agent that finds no specification does not stop. It improvises. And improvised output looks like correct output. A study shows the same pattern: without explicit prompting, agents given incomplete specifications rarely ask and carry on without the missing information. Most models are poor at recognising whether a specification is complete (Vijayvargiya et al., ICLR 2026).
The obvious reaction would have been to rewrite the agents for every project. That is what I did first. After the third project I was maintaining three agent sets that slowly drifted apart, and for seven projects it would have been seven.
Line by Line: Stack or Process?
I went through every agent file line by line and asked two questions:
- Would this line be just as true in a FastAPI service?
- If not: is it knowledge about the stack or knowledge about the process?
By far the largest part of an agent file is process knowledge: in which order do I work, what do I read first, to whom do I hand the result, when do I escalate. That holds regardless of whether Dart, Python or TypeScript sits underneath.
Little of it is bound to the stack, but that little is scattered everywhere: a command here, a directory path there, a naming convention in a subordinate clause. That is why the file could not be moved despite its small stack share. The stack knowledge was stirred into the process knowledge.
Three Layers
This exercise produced a separation that today defines what a workflow update may touch and what it may not:
| Layer | What lives there | When porting |
|---|---|---|
| A — core | agents, skills, workflow index, guards, templates | copy unchanged |
| B — adapter | gate commands, stack conventions, test strategy, architecture rules | rewrite per stack (estimated at about one day) |
| C — content | UCs, concepts, plans, findings, agent memory | emerge in the target project |
The most important property lies in the direction of the arrow: the
dependency points one way, the core reads the adapter. A core agent references
project-context.md or the coding-guidelines skill, and it does not care
whether that says Flutter, Nuxt or FastAPI. The name stays stable, the content
changes. This turns a convention into an interface that makes the move possible.
At my employer the separation has a second effect. The core contains the
standards agents work by: sequence, approvals and guards, meaning hook scripts
that block forbidden actions, such as a commit to main or a write by a role
that may only read. A security department can
review and harden these files without knowing every project. Project-specific
rules live in the adapter and do not touch the core. So when someone says "but
we have a very special setup", the answer is: then we write an adapter for it,
and the core stays as it is.
The Rule That Keeps the Core Clean
A single rule keeps the layers from merging again:
An agent only enters the core if it would run unchanged in the target stack.
It is the direct lesson from the adopted agent that never ran. Everything else belongs in the adapter or in an optional module. That is how my UI module came about: three agents that presuppose a design system and a component catalogue. They have no business in a FastAPI service, so they remain an add-on outside the core.
The rule often decides against the short path. When an agent could do some small thing better in the current project because I hand it a path, that is tempting. The price is that on the next move, this agent is once again the one improvising plausibly.
What the Adapter Contains
The adapter consists of five documents and a script. They answer the questions an agent would otherwise guess:
| Adapter component | Answers |
|---|---|
project-context.md | Which stack, which layers, which hard rules, which reference module? |
coding-guidelines | What does code look like here — conventions, canonical patterns, anti-patterns? |
quality-gates | What has to be green, what is deliberately weakened, and until when? |
testing-strategy | Which test levels exist, with what tooling, and how are they run? |
styling-guidelines | UI only: design tokens, component catalogue, forbidden patterns. |
scripts/quality-gates.sh | The actual commands — the real swap point per stack. |
Since the rebuild I describe in Part 2, only
project-context.md is always in context as a rule. The other four documents are
skills that only the agents who need them preload.
The gates script is the most important adapter. The five documents describe something, the script executes it. Because the local session, the git hook and CI call it identically, a gate cannot be defined green locally and red in CI.
The reference module is a mandatory field. The adapter names a module that embodies the architecture rules, and the agents read it before they build. That is the difference between "follow clean architecture" and "this is what it looks like here". Anthropic recommends the same thing, pointing Claude at existing patterns in the code (Claude Code Best Practices). In a fresh project that is easy. In a grown codebase the answer is often: there is none. Then I name the least bad module and list its deviations. That is transparent, but it is no substitute for a clean example.
Even so, the structure helps in brownfield projects in particular. The adapter writes down what a grown codebase otherwise keeps only in the team's heads: architecture rules, known legacy debt, the least bad example. The pipeline makes sure an agent researches, plans and gets reviewed before it writes code. An exploratory survey of 52 developers, most of them working on existing systems, points the same way: most found AI of little help there when used ad hoc, and considerably more helpful with a fixed sequence of research, plan, review and human approval (Sharma 2025). That is not proof: the numbers are self-assessments without a control group, and the study looked at chat tools, not agents that change code themselves.
The Second Dividing Line: Who Needs the Knowledge, and When?
The three layers determine which knowledge belongs where. How it reaches the agent depends on the mechanism. Claude Code offers several, and they differ mainly in when they load into context and who gets to see them.
| Mechanism | Loads … | What I use it for |
|---|---|---|
Rule (without paths:) | at startup, in the main session and in almost all subagents | only what everyone needs: project-context.md and a short index "situation → skill" |
| Skill | at startup only name and description, the content only when invoked. Preloaded in a subagent via skills:: in full and immediately, but only there | role knowledge and procedures: coding guidelines for the developer, styling rules for the UI agents |
| Subagent | with its own context window and its own tools; only the result comes back | the pipeline roles, reviewers without write access |
| Hook, script, CI | not at all, runs outside the context | everything that must be guaranteed to happen: gates, locks, checks |
When each of them loads is documented for Rules, Skills and Subagents.
For every piece of knowledge I ask three questions: Who needs it? When do they need it? Does it have to be guaranteed? If it does, it belongs in a script.
The separation has a direct effect on the quality of the results:
- Every agent starts with a fresh, lean context. According to Anthropic, performance drops the fuller the context gets; Claude then forgets earlier instructions or makes more mistakes (Best Practices). A study with 15 models measured the effect: when the requirements arrive spread across several messages, performance drops by 39% on average. When the same information is bundled into one fresh instruction, the models reach 95% of their best score (Laban et al. 2025). A subagent that starts with the approved concept works in the second situation. Styling rules would only be noise in the business analyst's context.
- Roles have boundaries. A reviewer without write access reports every error it finds, because it cannot fix it itself. The documentation explicitly names restricting tools per subagent as one purpose of subagents (Subagents).
- Hooks always run. According to the documentation they make sure an action happens instead of relying on the model to perform it (Hooks). Where text is needed after all, one study argues for prohibitions: it analysed more than 5,000 runs with Claude Code. Of 18 rules tested individually, three were helpful and four harmful; the helpful ones were all prohibitions, the harmful ones all positive directives (Zhang et al. 2026).
- Every step can be checked. Gates return green or red. The same documentation recommends giving Claude a check it can run itself: tests, a build, a screenshot to compare against.
- Handoffs run through documents. Use case, concept and plan are artifacts that a reviewer checks before any code is written. MetaGPT describes the same principle: fixed procedures that check intermediate results are meant to reduce errors when agents are chained (Hong et al., ICLR 2024).
A team of agents is not automatically better than a single agent, though. A study, mostly from UC Berkeley, found that multi-agent systems on common benchmarks often achieved only minimal gains. It assigns their failures to three categories: system design, coordination between the agents, and verification (Cemri et al. 2025). My workflow addresses these three points: fixed roles and the adapter for design, documents for handoffs, gates and reviews for verification. On top of that come my approvals and an upper limit on review rounds.
I align the setup with Anthropic's official recommendations and check it against the current documentation, because Claude Code changes quickly. A script generates the variants of the workflow for GitHub Copilot CLI and opencode from the same sources (the same workflow in three tools), so within limits the core is also independent of the tool.
That my own implementation violated this dividing line for a long time, and what that cost me in tokens, is the story of Part 2.
Where I Still Step In
I counted how much I still do myself in six weeks of session transcripts from two of my projects. An agent assigned each of my messages to a category. In that time, 30 pieces of work (features and bug fixes) went through the pipeline, and I merged 77 PRs. One piece of work can have several PRs when adjustments follow after the first one.
More than half of my input was planned: the brief in a few sentences, approving the use case and concept, answering questions and the merge. I stepped in unplanned in about one message in five, mostly because of the environment or an error in the result. A little over half of the pieces of work needed no correction at all.
The 32 errors I did have to correct mostly showed up where no gate looks: in the behavior on a real device and in functional gaps in the specification. Only four of them were caught by CI.
So today I check at two points. Before the code, I check the intent, meaning the use case and concept. Before the merge, I check the result, meaning the E2E tests and a test on the device. The code in between is checked by the code reviewer agent and the gates.
In June it looked different. In the walkthrough in post 15 I stepped in at four of five checkpoints for a single feature. Today a little over half of the pieces of work get through without a correction. The two figures were collected differently, one feature then against 30 pieces of work now, but they point the same way.
Control work remains all the same (I wrote about it in post 22): status questions, maintaining the workflow itself and coordinating parallel sessions still take attention.
The Preconditions That Have Nothing to Do With Technology
While taking it apart I noticed that the workflow generalises across technologies but makes tacit assumptions about context. They now sit as a table at the front of the documentation, because otherwise they only surface when it is too late:
- The gates have to be cheap. The rhythm "one commit per plan step, gates after every step" presupposes runtimes in minutes. With expensive codegen the economics stop working, and then you need a fast profile per step and the full profile at the end.
- One person holds all three approvals. Requirement, concept, merge: in my case that is me. In a team these gates have to be assigned to roles, and the workflow does not enforce the separation.
- The repo host needs a PR gate. Without branch restrictions on the default branch there is no technical enforcement of the merge gate, and it once again rests on discipline alone.
Anyone who adopts the workflow without these preconditions gets the structure but not its effect.
The Price: Tokens
The setup uses noticeably more tokens than a single session with a good prompt, and I regularly ran into my subscription limit with it.
The costs have a clear origin. Every subagent starts with its own context and loads the project configuration again, including all rules without a path binding. What an agent already occupies in its first turn I call its startup load. A developer agent that is called for each plan step pays it at every step, and subagents count against the same usage limit as the main session (Subagents). Anthropic measured for its own research system that agents use about four times and multi-agent systems about fifteen times as many tokens as a chat (Multi-agent research system).
I pay the price anyway. The main session stays small, because a subagent reads twenty files and returns only its result to it. Anthropic describes subagents the same way in its guide to context engineering: they return a condensed summary, often 1,000 to 2,000 tokens (Effective context engineering). The gates script and the hooks run outside the context, so a rule that a script checks does not have to travel along as text in every session. Gates catch errors early: a gate that turns red after a plan step costs a short correction run, while an error that only surfaces in review costs a long session full of follow-up questions. And because stack knowledge, roles and process live separately, I can save in targeted ways: give the coding guidelines only to the developer and the styling rules only to the UI agents, and put mechanical roles on a cheaper model. A single large CLAUDE.md is loaded in full by every agent.
More configuration is not automatically better, though: a study with participation from ETH Zurich measured that context files do not significantly improve the success rate but do raise inference costs: by 20 to 23% on average for automatically generated files and by up to 19% for files written by developers (Gloaguen et al. 2026).
Where the Workflow Runs Today
By now the workflow runs in seven projects on four stacks: Flutter, Nuxt, FastAPI and React. The three Flutter projects share the stack of the original repository and mainly show that copying works and that the UI module can be switched on cleanly. The real moves were Nuxt, FastAPI and the VS Code plugin in React: different languages, different directory structures, different tools for tests and gates. Only the adapters were written anew there, and the core stayed as it was.
A running project does not show whether an agent improvises. To measure how generic the core is, I initially counted stack mentions per file, that is, how often "Flutter", "Dart" or "pub" appear in a core file. The number went down nicely, and what it measured was the vocabulary. A file can be phrased in a stack-neutral way and still presuppose a directory structure that does not exist elsewhere.
The move to Nuxt did not uncover this either. The workflow ran there without anything breaking loudly. The remaining coupling was only found by the audit from Part 2, which checked every core file with evidence: the test agent and two templates still presupposed Flutter's test directory, test API and selectors. That is the same failure mode as at the start of this post.
Since then I check coupling directly: whenever the setup path changes, a self-test runs installation and checks on small sample projects in three stacks. I describe how that is built in the post about the same workflow in three tools.
One question remains open that none of these projects answers, because I built all of them alone: whether the workflow holds up just as well when the three approvals are spread across several roles in a team. I have not tried that yet.
What I Take Away
Something becomes reusable when its dependencies point in one direction. My agents were attached to the project in every direction, even though each one was neatly cut on its own, and that is why they could not be extracted. Now that their dependencies point one way, I can use them in seven projects and only have to check things myself at two points.
The dividing lines I take away:
- Process knowledge into the core, stack knowledge into the adapter, project knowledge into the project. When I am unsure where something belongs, I ask: what happens if this piece of information is missing in the next project?
- Every piece of knowledge only where it is needed, and everything that must be guaranteed into a mechanism.
In Part 2 I show how I used an audit to measure where my tokens went, at which points my own setup violated the second dividing line, and what the rebuild achieved. Part 3 shows what helped after that, which experiment I abandoned, and what the numbers from two real projects say.
How many projects do you run with your agent setup, and at which points do you still step in yourself?