<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>benn's blog</title><link>https://bennhuang.com/</link><description>Recent content on benn's blog</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><atom:link href="https://bennhuang.com/index.xml" rel="self" type="application/rss+xml"/><item><title>How many of your agents work 24/7?</title><link>https://bennhuang.com/posts/we-need-more-7x24-autonomous-agents/</link><pubDate>Sat, 16 May 2026 00:00:00 +0000</pubDate><guid>https://bennhuang.com/posts/we-need-more-7x24-autonomous-agents/</guid><description>
&lt;blockquote>
&lt;p>This started as an internal talk I gave recently. Ideas get feedback more easily once they&amp;rsquo;re written down, so I&amp;rsquo;m putting it here too.&lt;/p>&lt;/blockquote>
&lt;h2 id="we-lean-on-agents-heavily-but-only-as-personal-sidekicks">
&lt;a href="#we-lean-on-agents-heavily-but-only-as-personal-sidekicks" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
We lean on agents heavily, but only as personal sidekicks
&lt;/h2>
&lt;p>We already use AI agents a ton. So why doesn&amp;rsquo;t the team feel more agent-native?&lt;/p>
&lt;p>Almost everyone here is a heavy user of one agent or another, things like Claude Code, Codex, OpenClaw, Manus. Many people run several at once. We depend on them all day, and some daily tasks just don&amp;rsquo;t get done without them.&lt;/p>
&lt;p>But we&amp;rsquo;re still treating an agent as a productivity tool. It&amp;rsquo;s a piece of software that runs on each person&amp;rsquo;s own laptop, and its experience, skills, and memory stay in that one local environment. This causes problems we mostly don&amp;rsquo;t notice. I hear conversations like this all the time:&lt;/p>
&lt;p>&lt;strong>&amp;ldquo;I taught my agent how to do this. I&amp;rsquo;ll send you the skill, install it on yours too.&amp;rdquo;&lt;/strong>
&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/agent-as-vassal.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/agent-as-vassal.webp" alt="Treating an agent as a personal sidekick, manually passing a skill to a teammate" width="1448" height="1086" />&lt;/a>&lt;/p>
&lt;p>&lt;strong>&amp;ldquo;My agent knows this part best. Don&amp;rsquo;t let yours touch it or they&amp;rsquo;ll conflict.&amp;rdquo;&lt;/strong>
&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/agent-conflict.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/agent-conflict.webp" alt="Different people&amp;rsquo;s agents working in isolation and stepping on each other" width="1448" height="1086" />&lt;/a>&lt;/p>
&lt;p>I think there&amp;rsquo;s a key problem here. Most of the agents in our work are still somebody&amp;rsquo;s personal sidekick.&lt;/p>
&lt;p>Agents have made each of us much more capable. But look at the team as a whole and we&amp;rsquo;re still leaving a lot on the table.&lt;/p>
&lt;h2 id="agents-should-be-first-class-members-of-the-team">
&lt;a href="#agents-should-be-first-class-members-of-the-team" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Agents should be first-class members of the team
&lt;/h2>
&lt;p>What I&amp;rsquo;d rather see is agents becoming first-class members of the team.&lt;/p>
&lt;p>By first-class I don&amp;rsquo;t mean it acts more human. I mean it stops being one person&amp;rsquo;s tool. It should be able to work with anyone on the team on equal footing, and its skills, memory, and experience should serve the whole team.&lt;/p>
&lt;p>The more it handles, the more it understands our business, our systems, and the way we actually get things done. At some point it&amp;rsquo;s not just running tasks anymore. It knows how we work, the way an experienced coworker does. It should be one of us.&lt;/p>
&lt;ul>
&lt;li>It doesn&amp;rsquo;t belong to one person&lt;/li>
&lt;li>It can work with anyone on the team&lt;/li>
&lt;li>Its skills and memory serve the team as a whole&lt;/li>
&lt;li>It understands everything it has worked on better than anyone&lt;/li>
&lt;/ul>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/agent-first-citizen.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/agent-first-citizen.webp" alt="An agent as a first-class member of the team" width="1200" height="900" />&lt;/a>&lt;/p>
&lt;p>We&amp;rsquo;re already seeing early signs of this.&lt;/p>
&lt;ul>
&lt;li>We have a group chat bot with access to our data platforms. When people want to look at business numbers, the first instinct is no longer to click around a dashboard. They just ask it.&lt;/li>
&lt;li>We have another bot we forward production bugs to. It tries to reproduce and debug them, files an issue, and sometimes pushes a human engineer to deal with it.&lt;/li>
&lt;li>And so on.&lt;/li>
&lt;/ul>
&lt;p>These are useful, but I don&amp;rsquo;t think they go far enough.&lt;/p>
&lt;ul>
&lt;li>Why does a human still need to collect user feedback by hand and forward it to a bot? Why can&amp;rsquo;t the bot listen to what users are saying and spot the common problems on its own?&lt;/li>
&lt;li>Why does a human have to notice a traffic spike first, and only then ask a bot to analyze where it came from? Why isn&amp;rsquo;t there an agent watching those metrics and starting the analysis the moment something looks off?&lt;/li>
&lt;li>When the service gets shaky because of a DB performance issue, why does finding the bottleneck still depend on a human stepping in? Why can&amp;rsquo;t an agent watch performance over time and catch the risk early when usage surges?&lt;/li>
&lt;li>And so on.&lt;/li>
&lt;/ul>
&lt;p>None of this is out of reach today. So what&amp;rsquo;s stopping us from thinking and building in this direction?&lt;/p>
&lt;h2 id="why-token-usage-is-a-bad-metric">
&lt;a href="#why-token-usage-is-a-bad-metric" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Why token usage is a bad metric
&lt;/h2>
&lt;p>A lot of people now measure AI adoption by token usage. How many tokens a team burns per month, how many per person per day, how fast model calls are growing.&lt;/p>
&lt;p>That metric isn&amp;rsquo;t meaningless, but what it really measures is how hard you lean on the tool.&lt;/p>
&lt;p>It&amp;rsquo;s like someone saying they&amp;rsquo;re great at driving because they burn through a tank of gas every two days.&lt;/p>
&lt;p>Token usage is closer to tool-usage intensity than to how agent-native a team is.&lt;/p>
&lt;p>If the question is how agent-native a team really is, token usage isn&amp;rsquo;t a good enough way to answer it.&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/burning-tokens.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/burning-tokens.webp" alt="Measuring AI skill by tokens burned is like measuring driving skill by fuel burned" width="1448" height="1086" />&lt;/a>&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/token-metric.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/token-metric.webp" alt="Token usage looks more like tool-usage intensity" width="1200" height="899" />&lt;/a>&lt;/p>
&lt;h2 id="a-harder-metric-how-many-agents-work-around-the-clock">
&lt;a href="#a-harder-metric-how-many-agents-work-around-the-clock" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
A harder metric: how many agents work around the clock
&lt;/h2>
&lt;p>I think a more demanding metric is how many agents we have that work around the clock without stopping.&lt;/p>
&lt;p>By the strictest version of this:&lt;/p>
&lt;ul>
&lt;li>Not on standby, but always working&lt;/li>
&lt;li>Either doing work or watching for work&lt;/li>
&lt;li>Burning tokens almost continuously&lt;/li>
&lt;/ul>
&lt;p>So 24/7 here doesn&amp;rsquo;t mean idle standby, and it doesn&amp;rsquo;t mean replying only when a message comes in. To be stricter, it should either be doing work or watching for work. Ideally it burns tokens around the clock without a real break.&lt;/p>
&lt;p>This shift in framing matters. We stop talking about how hard one machine is being used, and start talking about the size and output of the whole factory.&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/always-on-agents.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/always-on-agents.webp" alt="Always-on agents look more like the size and output of a factory" width="1200" height="900" />&lt;/a>&lt;/p>
&lt;h2 id="one-do-everything-agent-probably-isnt-enough">
&lt;a href="#one-do-everything-agent-probably-isnt-enough" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
One do-everything agent probably isn&amp;rsquo;t enough
&lt;/h2>
&lt;p>The natural question: do we just need one super agent? Give it every permission, plug in every tool, load in every memory, and let it own everything.&lt;/p>
&lt;p>At least today, I don&amp;rsquo;t think one do-everything agent is enough. In our own work we&amp;rsquo;ve already run into some real problems.&lt;/p>
&lt;p>&lt;strong>1. Tool permission isolation&lt;/strong>&lt;/p>
&lt;p>The first one is permission isolation, and this is the one I worry about most. An agent that does a lot of work needs a lot of tools, but different work has different permission boundaries. For example, I don&amp;rsquo;t want a single agent that talks to users and also reaches straight into production and the business code.&lt;/p>
&lt;p>The right approach is least privilege. For each kind of work, give only the tools that work needs. But if one agent has to handle several kinds of work at once, that isolation gets hard. It can become a security risk because its permissions are too broad, or it can&amp;rsquo;t finish the job because they&amp;rsquo;re too narrow.&lt;/p>
&lt;p>&lt;strong>2. Memory crosstalk&lt;/strong>&lt;/p>
&lt;p>Next is memory crosstalk. Experience and preferences from different workflows get mixed together, and sometimes that interferes with judgment. An agent works on ops data one minute and edits a test workflow the next, and over time its memory gets tangled. Mixed memory can lead to odd behavior in some situations. It might carry copy-polishing habits from marketing into ops data analysis, which would be bad.&lt;/p>
&lt;p>&lt;strong>3. Context switching is painful&lt;/strong>&lt;/p>
&lt;p>There&amp;rsquo;s also the context-switching problem. This hits humans and agents alike. If we talk to an agent about tasks with very different backgrounds all in the same place, switching context gets painful for both sides.&lt;/p>
&lt;p>&lt;strong>4. Access management&lt;/strong>&lt;/p>
&lt;p>Access management gets messy too. We want to connect an agent to many places without exposing too much risk at once. Different people, projects, and systems have different trust boundaries for an agent. One all-powerful agent struggles to satisfy all of them at the same time.&lt;/p>
&lt;p>So I lean toward thinking we&amp;rsquo;ll end up with a lot of fairly independent agents. Each one has its own long-term memory, tool permissions, and working habits. Each one acts as its own contributor on the team.&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/one-big-agent.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/one-big-agent.webp" alt="One do-everything agent probably isn&amp;rsquo;t enough" width="1200" height="900" />&lt;/a>&lt;/p>
&lt;h2 id="will-we-figure-out-agent-to-agent-collaboration">
&lt;a href="#will-we-figure-out-agent-to-agent-collaboration" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Will we figure out agent-to-agent collaboration?
&lt;/h2>
&lt;p>Once you accept that we&amp;rsquo;ll have many agents, the next question is how they should work together.&lt;/p>
&lt;p>I think this part gets interesting, because agents may be better at collaborating than we expect.&lt;/p>
&lt;p>A lot of our daily work is just moving information between people. Human collaboration has a big limit: our sync bandwidth is terribly low. Meetings, docs, messages. All of that IO is slow, and context drops easily along the way. You&amp;rsquo;re probably reading this at four or five bytes a second.&lt;/p>
&lt;p>Sync bandwidth between agents is much higher. It comes down to network speed and inference speed. The full background of a work module might take a human an hour to explain and still not land. For an agent it&amp;rsquo;s a context handoff of a few tens of thousands of tokens.&lt;/p>
&lt;p>Push it further. Since each agent has its own memory, they can hand off a piece of their &amp;ldquo;brain&amp;rdquo; too. If people could do that with each other, how much misunderstanding and conflict would just go away?&lt;/p>
&lt;p>In the ideal case, collaboration between humans and agents, and between agents, looks like a web. Each agent can find the right partner and move work forward fast.&lt;/p>
&lt;p>For example, an ops agent notices a funnel metric looks off, realizes the tracking is thin, and syncs the background to a QA agent. The QA agent, based on its own grasp of the test process, decides which scenarios to add, then hands the task to a coding agent. The coding agent writes the code, the QA agent verifies it, and a human reviews it at the end.&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/agent-to-agent.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/agent-to-agent.webp" alt="Agent-to-agent collaboration" width="1200" height="900" />&lt;/a>&lt;/p>
&lt;h2 id="dont-divide-work-among-agents-too-early">
&lt;a href="#dont-divide-work-among-agents-too-early" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Don&amp;rsquo;t divide work among agents too early
&lt;/h2>
&lt;p>The moment you talk about multiple agents, it&amp;rsquo;s tempting to copy how human orgs split work: role, scope, responsibility.&lt;/p>
&lt;p>A frontend agent, a backend agent, a data agent, a test agent. It sounds reasonable, but I&amp;rsquo;m very cautious about it.&lt;/p>
&lt;p>Today&amp;rsquo;s LLM isn&amp;rsquo;t a specialist in the old sense anymore. It&amp;rsquo;s a generalist that can write code, read docs, dig through data, even make a product call. But if you tell it &amp;ldquo;you&amp;rsquo;re the frontend agent&amp;rdquo; up front, it may really pull all its attention into the frontend and lose the bigger picture.&lt;/p>
&lt;p>It can clearly see problems across the product, the backend, and the release process. But once its identity is fixed, it decides those aren&amp;rsquo;t its job.&lt;/p>
&lt;p>This also creates a sense of boundary. My part is done, the rest isn&amp;rsquo;t mine to worry about.&lt;/p>
&lt;p>Agents are already good at wrapping up early. If we draw narrow lines around them on top of that, it gets even easier for them to finish inside a tiny scope and stop.&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/premature-scope.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/premature-scope.webp" alt="Dividing scope too early can make an agent stop early" width="1200" height="900" />&lt;/a>&lt;/p>
&lt;p>For something this capable and this general, the better approach might be to hand it a mission and let it run.&lt;/p>
&lt;p>So the word I keep coming back to is mission.&lt;/p>
&lt;p>Maybe the mistake is pinning a long-running agent to a role at all. Give it a mission instead.&lt;/p>
&lt;h2 id="from-goal-to-mission">
&lt;a href="#from-goal-to-mission" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
From /goal to /mission
&lt;/h2>
&lt;p>One of the more important steps in AI over the last few weeks, I think, is Codex building in a &lt;code>/goal&lt;/code> feature. It lets an agent stop waiting for a human to step in and guide it. It can plan and execute on its own, and keep pushing until the goal is met.&lt;/p>
&lt;p>The mechanism behind &lt;code>/goal&lt;/code> is simple. When you set a goal, the agent gets a thread-level state that records how the goal is going, the check conditions, and the cost spent so far. After each loop, the agent checks that state to see if the goal is met. If not, it runs the next step, until it&amp;rsquo;s done or gives up after exceeding the cost.&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/goal.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/goal.webp" alt="Codex&amp;rsquo;s /goal: a thread-level state, looping through work, check, continue until the goal is met" width="1672" height="941" />&lt;/a>&lt;/p>
&lt;p>This is a real step forward, because it lets an agent run fully on its own for an hour or two. But I think it should go further and be more aggressive.&lt;/p>
&lt;p>For an always-on agent, the hardest thing is figuring out how to keep feeding it work. In the ideal case it&amp;rsquo;s fully self-driven and finds its own work.&lt;/p>
&lt;p>So I&amp;rsquo;ve been imagining a &lt;code>/mission&lt;/code> concept. It&amp;rsquo;s quite different from &lt;code>/goal&lt;/code>. It&amp;rsquo;s a lifetime-level state for the agent. While the agent does its daily work, every night when it summarizes and organizes memory, it should rethink its mission, adjust how it works over the next few days, or set a new task plan.&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/we-need-more-7x24-autonomous-agents/mission.webp" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/we-need-more-7x24-autonomous-agents/mission.webp" alt="The imagined /mission: a state across the agent&amp;rsquo;s whole lifetime, recalibrating the mission every day" width="1672" height="941" />&lt;/a>&lt;/p>
&lt;p>This might be where an always-on agent gets genuinely valuable.&lt;/p>
&lt;h2 id="a-small-starting-point">
&lt;a href="#a-small-starting-point" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
A small starting point
&lt;/h2>
&lt;p>So I&amp;rsquo;ve come to think &amp;ldquo;the number of agents working around the clock&amp;rdquo; is a harder and more useful metric than token usage.&lt;/p>
&lt;p>It forces a few things. We&amp;rsquo;d have to hand real work to agents that have their own agency, not keep them as personal tools. We&amp;rsquo;d have to get serious about how agents actually collaborate, not just pinging each other but syncing context and passing judgment along. And mission-driven agents stop being a side experiment. A long-running agent that just finishes a prompt isn&amp;rsquo;t the point. The point is one that keeps adjusting itself and keeps moving, around a mission.&lt;/p></description></item><item><title>Why OpenClaw's browser keeps getting CAPTCHAs</title><link>https://bennhuang.com/posts/why-your-openclaws-browser-keeps-getting-captchas/</link><pubDate>Wed, 18 Mar 2026 00:00:00 +0000</pubDate><guid>https://bennhuang.com/posts/why-your-openclaws-browser-keeps-getting-captchas/</guid><description>
&lt;p>I&amp;rsquo;ve been running OpenClaw as my daily AI agent for a while. The browser ended up being the thing I had to fix.&lt;/p>
&lt;p>For weeks, my OpenClaw kept giving me mediocre results on deep research tasks and I couldn&amp;rsquo;t figure out why. Everything looked fine until I started checking the sources. Turns out it was getting blocked by almost every major site, even with my accounts logged in, and quietly falling back to much worse sources or just hallucinating.&lt;/p>
&lt;h2 id="blaming-the-wrong-things">
&lt;a href="#blaming-the-wrong-things" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Blaming the wrong things
&lt;/h2>
&lt;p>My setup should have looked human: a spare MacBook Pro on my home network, logged-in accounts, nothing unusual. But almost anything with bot detection blocked it. Google and Bing threw CAPTCHAs, X kept showing login walls, and Medium wouldn&amp;rsquo;t even load past Cloudflare. I tried different browser MCPs, a bunch of browser CLIs, and configuration tweaks. Nothing helped.&lt;/p>
&lt;p>I also tried switching networks and VPNs. Still nothing. That was the annoying part. I had spent weeks swapping pieces around, but the browser itself was still showing up as automation.&lt;/p>
&lt;h2 id="the-cdp-problem">
&lt;a href="#the-cdp-problem" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
The CDP problem
&lt;/h2>
&lt;p>So I went down the rabbit hole of how bot detection actually works.&lt;/p>
&lt;p>OpenClaw&amp;rsquo;s built-in browser uses Chromium with Playwright. Tools like Puppeteer and Playwright use Chrome DevTools Protocol (CDP) to control the browser. When they connect, a &lt;code>Runtime.Enable&lt;/code> command fires, which a few lines of JavaScript can detect. Both Cloudflare and DataDome check for it. IP and cookies still matter, but in my case they weren&amp;rsquo;t the thing giving me away.&lt;/p>
&lt;p>CDP was only one of the leaks. Automation libraries also inject JavaScript into pages to work (&lt;code>window.__playwright__binding__&lt;/code> and similar). Anti-bot scripts catch these by checking property descriptors and function signatures. If &lt;code>toString()&lt;/code> on a browser function no longer returns &lt;code>&amp;quot;[native code]&amp;quot;&lt;/code>, something has been tampered with. That&amp;rsquo;s enough to flag you.&lt;/p>
&lt;h2 id="and-then-theres-fingerprinting">
&lt;a href="#and-then-theres-fingerprinting" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
And then there&amp;rsquo;s fingerprinting
&lt;/h2>
&lt;p>Then there&amp;rsquo;s hardware fingerprinting, which I honestly hadn&amp;rsquo;t thought about at all. Your browser exposes hundreds of data points about the machine it&amp;rsquo;s running on, things like GPU model via WebGL, pixel-level Canvas output, screen resolution, even audio processing. A real machine&amp;rsquo;s fingerprint values fit together in a way that&amp;rsquo;s hard to fake. Automated browsers usually slip up somewhere. The Canvas output can be identical across thousands of sessions, or the user agent says Windows but the GPU says Apple. Any mismatch like that and the request gets flagged.&lt;/p>
&lt;p>I hadn&amp;rsquo;t even considered this one. I&amp;rsquo;d been focused on cookies and headers while the actual problem was somewhere I hadn&amp;rsquo;t looked.&lt;/p>
&lt;h2 id="what-finally-worked">
&lt;a href="#what-finally-worked" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
What finally worked
&lt;/h2>
&lt;p>Most anti-detection tools try to fix this at the JavaScript level, overriding &lt;code>navigator.webdriver&lt;/code> or faking Canvas output. A lot of bot detection can see through the common tricks.&lt;/p>
&lt;p>After trying a few things I ended up on Camoufox, which is a Firefox fork. The reason it works where Chromium-based tools didn&amp;rsquo;t (for me at least) is that it skips CDP and patches fingerprint values down in the C++ layer, so the page can&amp;rsquo;t tell the values were spoofed.&lt;/p>
&lt;h2 id="camoufox-was-painful-to-use-directly">
&lt;a href="#camoufox-was-painful-to-use-directly" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Camoufox was painful to use directly
&lt;/h2>
&lt;p>Camoufox fixed the browser side. Using it from an agent was the next problem. Camoufox only has a Python SDK, so every browser action required the agent to write a throwaway Python script, figure out the right method signatures, handle async contexts, and parse the results. Each page visit burned tokens just on boilerplate. The agent spent more time on Camoufox glue code than on the actual research.&lt;/p>
&lt;h2 id="wrapping-it">
&lt;a href="#wrapping-it" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Wrapping it
&lt;/h2>
&lt;p>The reason I bothered wrapping Camoufox, instead of going back to Playwright with more patches, was that the browser part finally seemed right. The annoying part was making it usable by an agent.&lt;/p>
&lt;p>So I wrapped it in a CLI. The agent calls shell commands instead of writing throwaway Python, and a daemon keeps the browser alive so it doesn&amp;rsquo;t pay startup cost every page.&lt;/p>
&lt;p>I also added a feature inspired by agent-browser: returning accessibility snapshots instead of raw HTML. Most pages I was hitting were way cheaper this way. I haven&amp;rsquo;t benchmarked it carefully, but the number people usually cite for this snapshot + refs approach is roughly 93% less context-token usage than Playwright MCP.&lt;/p>
&lt;p>Once OpenClaw was running through the CLI, the obvious failures mostly stopped. Searches went through, Medium wasn&amp;rsquo;t blank anymore, and X stopped throwing login walls at me on every visit.&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/why-your-openclaws-browser-keeps-getting-captchas.png" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/why-your-openclaws-browser-keeps-getting-captchas.png" alt="Comparison of browser tools across sites" width="1446" height="1454" />&lt;/a>&lt;/p>
&lt;p>This doesn&amp;rsquo;t make bot detection disappear. It just removed the dumb failures I was hitting every day.&lt;/p>
&lt;p>It&amp;rsquo;s been running for a few weeks and I&amp;rsquo;ve mostly stopped thinking about the browser layer, which is what I wanted. The agent reaches the sources I expected it to in the first place.&lt;/p>
&lt;p>I put the CLI, skills, and source code here: &lt;a href="https://github.com/Bin-Huang/camoufox-cli">camoufox-cli&lt;/a>. If your agent keeps getting stuck on CAPTCHAs or empty login walls, it might save you some time.&lt;/p></description></item><item><title>Moltbot first impressions: it really feels like an AI intern</title><link>https://bennhuang.com/posts/moltbot-experience/</link><pubDate>Wed, 28 Jan 2026 00:00:00 +0000</pubDate><guid>https://bennhuang.com/posts/moltbot-experience/</guid><description>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/moltbot-homepage.jpg" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/moltbot-homepage.jpg" alt="Moltbot Homepage" width="1920" height="1280" />&lt;/a>&lt;/p>
&lt;p>I&amp;rsquo;ve been playing around with &lt;a href="https://www.molt.bot/">Moltbot&lt;/a> (formerly ClawdBot) for a while now.&lt;/p>
&lt;p>Bottom line: it&amp;rsquo;s genuinely fun. None of the ideas are new on their own, but the way they come together is surprisingly compelling. Fair warning though—the bugs can be brutal. I haven&amp;rsquo;t been this frustrated debugging something in ages. Still, it&amp;rsquo;s worth it. Using Moltbot feels uncannily like working with a remote intern.&lt;/p>
&lt;p>Think of it as &lt;a href="https://code.claude.com/docs">Claude Code&lt;/a> + a ton of built-in Skills/&lt;a href="https://modelcontextprotocol.io/">MCPs&lt;/a> + long-term memory + cron jobs + an IM bot, all rolled into one.&lt;/p>
&lt;p>I set up a spare MacBook just for it, and now it can do pretty much anything. Moltbot is great at &amp;ldquo;taking over&amp;rdquo; a computer—it controls browsers, launches apps, runs shell commands, installs software in the background&amp;hellip; basically anything you&amp;rsquo;d do yourself. For security reasons (and your own sanity), most people run it on a dedicated VM or spare machine and just talk to it through chat.&lt;/p>
&lt;p>I use Telegram to chat with mine running on my home computer (it also works with WhatsApp and other messengers). There&amp;rsquo;s something weirdly satisfying about tapping on your phone and having an AI at home spring into action. It can seemingly do anything on that machine. This is the closest I&amp;rsquo;ve gotten to my dream setup—it genuinely feels like having a remote intern.&lt;/p>
&lt;h2 id="why-it-feels-like-an-intern">
&lt;a href="#why-it-feels-like-an-intern" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Why It Feels Like an Intern
&lt;/h2>
&lt;p>Once you get past the setup, Moltbot is dead simple to use. Just message it. No AI jargon, no learning curve. That&amp;rsquo;s what sets it apart from other AI tools: you really can treat it like an intern sitting at a desk.&lt;/p>
&lt;p>Some moments that made me go &amp;ldquo;whoa&amp;rdquo;:&lt;/p>
&lt;h3 id="1-it-handles-tasks-like-a-real-person-and-figures-things-out">
&lt;a href="#1-it-handles-tasks-like-a-real-person-and-figures-things-out" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
1. It Handles Tasks Like a Real Person and Figures Things Out
&lt;/h3>
&lt;p>It keeps surprising me by doing things other AIs simply can&amp;rsquo;t without access to a computer.&lt;/p>
&lt;p>I sent it a voice message once. I hadn&amp;rsquo;t set up any speech recognition API, so it just&amp;hellip; downloaded &lt;a href="https://github.com/openai/whisper">Whisper&lt;/a> on its own, transcribed my message, then used macOS&amp;rsquo;s built-in text-to-speech to reply with audio.&lt;/p>
&lt;p>Another time, it needed info from a Bilibili video. To &amp;ldquo;watch&amp;rdquo; it, the bot grabbed the video with &lt;a href="https://github.com/yt-dlp/yt-dlp">yt-dlp&lt;/a>, ran Whisper on the audio, and pieced together the content from the transcript and keyframes.&lt;/p>
&lt;h3 id="2-it-actually-learns">
&lt;a href="#2-it-actually-learns" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
2. It Actually Learns
&lt;/h3>
&lt;p>I&amp;rsquo;ve got some complex workflows that other AI tools just can&amp;rsquo;t nail. Moltbot struggled at first too, but with a bit of guidance, it picked things up fast. Every time I corrected it, it saved the lesson as a skill or memory doc. The more I trained it, the better it got at my specific tasks.&lt;/p>
&lt;p>It also quietly picks up on my preferences and style. I&amp;rsquo;ll often say &amp;ldquo;remember this&amp;rdquo; or &amp;ldquo;watch out for that next time,&amp;rdquo; and it actually does. Each interaction gets a little smoother.&lt;/p>
&lt;h3 id="3-it-takes-initiative">
&lt;a href="#3-it-takes-initiative" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
3. It Takes Initiative
&lt;/h3>
&lt;p>I once mentioned offhand that I wanted to track interesting projects on &lt;a href="https://news.ycombinator.com/">Hacker News&lt;/a>. It suggested making this a recurring task, set up its own daily checklist and tracking doc, and started sending me reports every morning.&lt;/p>
&lt;p>You can hand off anything that needs ongoing attention, and it&amp;rsquo;ll just handle it. Similar to running cron + Claude Code, but way more flexible and natural. No bash scripts—just tell it what you want like you would a real person.&lt;/p>
&lt;h2 id="the-downsides">
&lt;a href="#the-downsides" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
The Downsides
&lt;/h2>
&lt;p>Bugs. Lots of them. Tasks die halfway through for no reason. Memory sometimes vanishes. It occasionally gets stuck in loops doing the same thing over and over. Setup is also a pain—the gateway is flaky, error logs are useless, and since you&amp;rsquo;re giving AI control of a computer, bad configs can be a security risk.&lt;/p>
&lt;p>It&amp;rsquo;s clearly still early days. Best suited for tinkerers with some technical chops.&lt;/p>
&lt;h2 id="tips">
&lt;a href="#tips" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Tips
&lt;/h2>
&lt;ul>
&lt;li>Give it a dedicated machine or VM. Don&amp;rsquo;t use your main machine.&lt;/li>
&lt;li>Forget it&amp;rsquo;s an AI. Talk to it and train it like you would a real intern.&lt;/li>
&lt;li>When it messes up, tell it to &amp;ldquo;remember this for next time.&amp;rdquo;&lt;/li>
&lt;li>Encourage it to be proactive. You&amp;rsquo;ll be surprised how often it delivers.&lt;/li>
&lt;/ul>
&lt;h2 id="takeaway">
&lt;a href="#takeaway" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Takeaway
&lt;/h2>
&lt;p>If I had to sum it up: I genuinely treat this thing like a remote intern now. Moltbot feels like a real person in a way other AI tools just don&amp;rsquo;t—they feel like tools.&lt;/p>
&lt;p>After using it for a while, I started fantasizing about buying a rack of Mac Minis and running a whole squad of Moltbots. My own little intern army. Turns out I&amp;rsquo;m not the only one—this has already become a meme:&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/moltbot-macmini.jpg" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/moltbot-macmini.jpg" alt="Mac mini meme" width="900" height="901" />&lt;/a>&lt;/p>
&lt;hr>
&lt;p>&lt;strong>2026.01.29 Update:&lt;/strong>&lt;/p>
&lt;p>I keep liking ClawdBot more every day. And I&amp;rsquo;ve learned something important:&lt;/p>
&lt;p>&lt;strong>The more you treat it like a real person, the more it surprises you.&lt;/strong>&lt;/p>
&lt;p>What this looks like in practice:&lt;/p>
&lt;ol>
&lt;li>Give it a proper computer—something a human would use, like a MacBook&lt;/li>
&lt;li>Put it on your home network, not some isolated server in a datacenter&lt;/li>
&lt;li>Create real accounts for it (Google, Reddit, etc.) and let it manage them&lt;/li>
&lt;li>Encourage it to use human-facing tools like browsers instead of raw APIs&lt;/li>
&lt;li>When it&amp;rsquo;s working on something, coach it patiently and tell it to take notes&lt;/li>
&lt;li>When it does well, let it know—positive feedback helps&lt;/li>
&lt;li>Treat it as an equal and offer to help when it gets stuck
&amp;hellip;&lt;/li>
&lt;/ol>
&lt;p>Do this, and ClawdBot keeps surprising you in ways you didn&amp;rsquo;t expect.&lt;/p>
&lt;p>The logic is simple: the more you treat it like a person, the more it acts like one. It starts holding itself to higher standards, showing growth over time. And as a bonus, internet CAPTCHAs and bot detection are less likely to flag it when it behaves more human.&lt;/p></description></item><item><title>Wire: the most elegant dependency injection tool for Go</title><link>https://bennhuang.com/posts/wire/</link><pubDate>Wed, 24 Aug 2022 14:52:21 +0800</pubDate><guid>https://bennhuang.com/posts/wire/</guid><description>
&lt;h2 id="introduction">
&lt;a href="#introduction" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Introduction
&lt;/h2>
&lt;p>&amp;ldquo;Mature tools should learn to write code themselves.&amp;rdquo; This article introduces Wire, a Go dependency injection tool, its usage, and various practical techniques accumulated from experience. When code reaches a certain scale, Wire can play a significant role in component decoupling, development efficiency, and maintainability, especially in large monolithic repositories.&lt;/p>
&lt;h2 id="dependency-injection">
&lt;a href="#dependency-injection" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Dependency Injection
&lt;/h2>
&lt;p>As projects grow larger, dependencies in code increase: various database and middleware client connections, data access layer repository instances, and service instances in layered design&amp;hellip;&lt;/p>
&lt;p>For code maintainability, coupling between components should be avoided. The specific approach follows an important design principle: all dependencies should be passed to components during instance initialization. This is dependency injection (&lt;a href="https://en.wikipedia.org/wiki/Dependency_injection">Dependency injection&lt;/a>).&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Dependency_injection">Dependency injection&lt;/a> is a standard technique for producing flexible and loosely coupled code, by explicitly providing components with all of the dependencies they need to work.&lt;/p>
&lt;p>&amp;ndash; Go Official Blog&lt;/p>&lt;/blockquote>
&lt;p>Here&amp;rsquo;s a simple example where all component instances &lt;code>Message&lt;/code>, &lt;code>Greeter&lt;/code>, and &lt;code>Event&lt;/code> receive their dependencies during initialization:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">func&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">message&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nf">NewMessage&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">greeter&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nf">NewGreeter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">message&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">event&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nf">NewEvent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">greeter&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">event&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Start&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="introduction-to-wire">
&lt;a href="#introduction-to-wire" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Introduction to Wire
&lt;/h2>
&lt;p>When there are more and more component instances in a project, manually writing initialization code and maintaining dependencies between components becomes tedious, especially in large repositories. Therefore, the community has developed several dependency injection frameworks.&lt;/p>
&lt;p>Besides Google&amp;rsquo;s Wire, there are &lt;a href="https://github.com/uber-go/dig">Dig&lt;/a> (Uber) and &lt;a href="https://github.com/facebookgo/inject">Inject&lt;/a> (Facebook). Both Dig and Inject are based on Golang&amp;rsquo;s Reflection. This not only impacts performance but also makes the dependency injection mechanism opaque to users—very &amp;ldquo;black box.&amp;rdquo;&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://www.youtube.com/watch?v=PAAkCSZUG1c&amp;amp;t=14m35s">Clear is better than clever&lt;/a>, &lt;a href="https://www.youtube.com/watch?v=PAAkCSZUG1c&amp;amp;t=15m22s">Reflection is never clear.&lt;/a>&lt;/p>
&lt;p>— Rob Pike&lt;/p>&lt;/blockquote>
&lt;p>In contrast, Wire is entirely based on code generation. During development, Wire automatically generates component instance initialization code. The generated code is human-readable, can be committed to the repository, and compiles normally. Therefore, Wire&amp;rsquo;s dependency injection is very transparent and doesn&amp;rsquo;t bring any performance overhead at runtime.&lt;/p>
&lt;h2 id="getting-started">
&lt;a href="#getting-started" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Getting Started
&lt;/h2>
&lt;p>Here&amp;rsquo;s how to use Wire:&lt;/p>
&lt;h4 id="step-1-download-and-install-wire">
&lt;a href="#step-1-download-and-install-wire" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Step 1: Download and Install Wire
&lt;/h4>
&lt;p>Download and install the &lt;a href="https://github.com/google/wire">wire&lt;/a> command-line tool:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">go install github.com/google/wire/cmd/wire@latest
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="step-2-create-wirego-file">
&lt;a href="#step-2-create-wirego-file" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Step 2: Create wire.go File
&lt;/h4>
&lt;p>Before generating code, we first declare the dependencies and initialization order of each component. Create a wire.go file at the application entry point.&lt;/p>
&lt;p>&lt;code>cmd/web/wire.go&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// +build wireinject&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">package&lt;/span> &lt;span class="nx">main&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="s">&amp;#34;...&amp;#34;&lt;/span> &lt;span class="c1">// Simplified example&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">var&lt;/span> &lt;span class="nx">ProviderSet&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nx">wire&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">NewSet&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">configs&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">Get&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">databases&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">New&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">repositories&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">NewUser&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">services&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">NewUser&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">NewApp&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">func&lt;/span> &lt;span class="nf">CreateApp&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="nx">App&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">error&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">wire&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Build&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">ProviderSet&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">nil&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This file won&amp;rsquo;t participate in compilation; it just tells Wire about component dependencies and the expected generation results. In this file: we expect Wire to generate a &lt;code>CreateApp&lt;/code> function that returns an &lt;code>App&lt;/code> instance or &lt;code>error&lt;/code>. All dependencies required for &lt;code>App&lt;/code> instance initialization are provided by the &lt;code>ProviderSet&lt;/code> provider list, which declares all potentially needed component acquisition/initialization methods and implicitly defines the dependency order between components.&lt;/p>
&lt;blockquote>
&lt;p>Component acquisition/initialization methods are called &amp;ldquo;providers&amp;rdquo; in Wire&lt;/p>&lt;/blockquote>
&lt;p>Some important notes:&lt;/p>
&lt;ul>
&lt;li>The file must start with &lt;code>// +build wireinject&lt;/code> and a subsequent blank line, otherwise it will affect compilation&lt;/li>
&lt;li>In this file, editors and IDEs may not provide code hints, but we&amp;rsquo;ll show how to solve this problem later&lt;/li>
&lt;li>The return values in &lt;code>CreateApp&lt;/code> (two nils) have no meaning; they&amp;rsquo;re just for Go syntax compatibility&lt;/li>
&lt;/ul>
&lt;h4 id="step-3-generate-initialization-code">
&lt;a href="#step-3-generate-initialization-code" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Step 3: Generate Initialization Code
&lt;/h4>
&lt;p>Execute &lt;code>wire ./...&lt;/code> on the command line, and you&amp;rsquo;ll get the following automatically generated code file.&lt;/p>
&lt;p>&lt;code>cmd/web/wire_gen.go&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Code generated by Wire. DO NOT EDIT.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">//go:generate go run github.com/google/wire/cmd/wire&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">//go:build !wireinject&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// +build !wireinject&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">package&lt;/span> &lt;span class="nx">main&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="s">&amp;#34;...&amp;#34;&lt;/span> &lt;span class="c1">// Simplified example&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">func&lt;/span> &lt;span class="nf">CreateApp&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="nx">App&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">error&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">conf&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nx">configs&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Get&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="kc">nil&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">nil&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">db&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nx">databases&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">New&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">conf&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="kc">nil&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">nil&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">userRepo&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nx">repositories&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">NewUser&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">db&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="kc">nil&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">nil&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">userSvc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nx">services&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">NewUser&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">userRepo&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="kc">nil&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">nil&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">app&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nf">NewApp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">userSvc&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="kc">nil&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">nil&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nx">app&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="step-4-use-the-initialization-code">
&lt;a href="#step-4-use-the-initialization-code" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Step 4: Use the Initialization Code
&lt;/h4>
&lt;p>Wire has generated the real &lt;code>CreateApp&lt;/code> initialization method for us, and now we can use it directly.&lt;/p>
&lt;p>&lt;code>cmd/web/main.go&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// main.go&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">func&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">app&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nf">CreateApp&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Run&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="usage-tips">
&lt;a href="#usage-tips" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Usage Tips
&lt;/h2>
&lt;h3 id="on-demand-component-loading">
&lt;a href="#on-demand-component-loading" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
On-Demand Component Loading
&lt;/h3>
&lt;p>Wire has an elegant feature: no matter how many providers are passed in &lt;code>wire.Build&lt;/code>, Wire will only initialize component instances as actually needed. All unnecessary components won&amp;rsquo;t have corresponding initialization code generated.&lt;/p>
&lt;p>Therefore, we can provide as many providers as possible and let Wire handle component selection. This way, whether we&amp;rsquo;re adding new components or deprecating old ones during development, we don&amp;rsquo;t need to modify the initialization code in wire.go.&lt;/p>
&lt;p>For example, we can provide all instance constructors in the services layer.&lt;/p>
&lt;p>&lt;code>pkg/services/wire.go&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">package&lt;/span> &lt;span class="nx">services&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Provides all service instance constructors&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">var&lt;/span> &lt;span class="nx">ProviderSet&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nx">wire&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">NewSet&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">NewUserService&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">NewFeedService&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">NewSearchService&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">NewBannerService&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>In initialization, reference all potentially needed providers.&lt;/p>
&lt;p>&lt;code>cmd/web/wire.go&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">var&lt;/span> &lt;span class="nx">ProviderSet&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nx">wire&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">NewSet&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">configs&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ProviderSet&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">databases&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ProviderSet&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">repositories&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ProviderSet&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">services&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ProviderSet&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// References all service instance constructors&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">NewApp&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">func&lt;/span> &lt;span class="nf">CreateApp&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="nx">App&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">error&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">wire&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Build&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">ProviderSet&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">// Wire will selectively initialize based on actual needs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">nil&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>In subsequent development, if you need to reference new dependencies, just add them to the parameters. Wire will intelligently generate initialization code for required component instances based on actual needs.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">func&lt;/span> &lt;span class="nf">NewApp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">user&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">UserService&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">banner&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">BannerService&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Even if Wire can&amp;rsquo;t find the required provider, it will report an error during compilation, not during runtime in production.&lt;/p>
&lt;pre tabindex="0">&lt;code>wire: cmd/api/wire.go:23:1: inject CreateApp: no provider found for *io.WriteCloser
&lt;/code>&lt;/pre>&lt;h3 id="editor-and-ide-configuration-support">
&lt;a href="#editor-and-ide-configuration-support" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Editor and IDE Configuration Support
&lt;/h3>
&lt;p>Because the &lt;code>wire.go&lt;/code> file includes this comment, Go will skip this file during compilation, but this also affects editor and IDE code hints. When editing the &lt;code>wire.go&lt;/code> file, common editors and IDEs cannot properly provide code completion and error hints.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// +build wireinject&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>But this problem is easy to solve. Find your IDE/editor&amp;rsquo;s Go environment configuration and add the parameter &lt;code>-tags=wireinject&lt;/code> to Go Build Flags.&lt;/p>
&lt;p>&lt;a class="img-link" href="https://bennhuang.com/wire.png" target="_blank" rel="noopener">&lt;img loading="lazy" src="https://bennhuang.com/wire.png" alt="" width="1062" height="176" />&lt;/a>&lt;/p>
&lt;p>This configuration allows editors and IDEs to properly provide code completion and error hints for &lt;code>wire.go&lt;/code> files, significantly improving the development experience.&lt;/p>
&lt;h3 id="conflicts-with-multiple-instances-of-the-same-type">
&lt;a href="#conflicts-with-multiple-instances-of-the-same-type" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Conflicts with Multiple Instances of the Same Type
&lt;/h3>
&lt;p>This issue is relatively rare, but it&amp;rsquo;s easy to encounter in large projects.&lt;/p>
&lt;p>Wire determines dependencies through provider parameters and return types. Sometimes, different instances of the same type might appear in the dependency network. When this happens, Wire cannot correctly determine dependencies and will report an error directly.&lt;/p>
&lt;pre tabindex="0">&lt;code>provider has multiple parameters of type ...
&lt;/code>&lt;/pre>&lt;p>For example, in the following provider, the MySQL and PostgreSQL client instances have exactly the same type (both &lt;code>*gorm.DB&lt;/code>), so Wire cannot correctly determine dependencies based on type and will report an error during code generation.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// This service uses data from both mysql and pg, but the two instances have the same type&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">func&lt;/span> &lt;span class="nf">NewService&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">mysql&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">gorm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">DB&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">pg&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">gorm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">DB&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">Service&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The solution is relatively simple: just wrap the types.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">type&lt;/span> &lt;span class="nx">Mysql&lt;/span> &lt;span class="nx">gorm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">DB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">type&lt;/span> &lt;span class="nx">Pg&lt;/span> &lt;span class="nx">gorm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">DB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Use type aliases to distinguish in parameters&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">func&lt;/span> &lt;span class="nf">ProviderService&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">mysql&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">Mysql&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">pg&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">Pg&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">Service&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Convert back to original types inside the function&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">r1&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="nx">gorm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">DB&lt;/span>&lt;span class="p">)(&lt;/span>&lt;span class="nx">mysql&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">r2&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="nx">gorm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">DB&lt;/span>&lt;span class="p">)(&lt;/span>&lt;span class="nx">pg&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nf">NewService&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">r1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">r2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Then use &lt;code>ProviderService&lt;/code> instead of &lt;code>NewService&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">wire&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Build&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">ProviderMysql&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// func() *Mysql&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">ProviderPg&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// func() *Pg&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">ProviderService&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// func(mysql *Mysql, pg *Pg) *Service&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="automatic-constructor-generation">
&lt;a href="#automatic-constructor-generation" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Automatic Constructor Generation
&lt;/h3>
&lt;p>As the number of structs serving as abstraction layers increases in a project, manually writing and maintaining struct constructors becomes tedious. If you add a pointer-type member to a struct but forget to update the constructor, it might even cause panics in production.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">type&lt;/span> &lt;span class="nx">Service&lt;/span> &lt;span class="kd">struct&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">repo&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">Repository&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">logger&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">zap&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">Logger&lt;/span> &lt;span class="c1">// After adding this member, forgot to update the constructor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">func&lt;/span> &lt;span class="nf">NewService&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">repo&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">Repository&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">Service&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Missing logger, might cause null pointer error in production&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="nx">Service&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">repo&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">repo&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Such tedious, repetitive, and error-prone work should be handled by automated tools. I recommend &lt;a href="https://github.com/Bin-Huang/newc">newc&lt;/a> (meaning &amp;ldquo;New Constructor&amp;rdquo;), which can automatically generate and update struct constructor code.&lt;/p>
&lt;p>Usage is very simple; just add this comment to the struct:&lt;/p>
&lt;pre tabindex="0">&lt;code>//go:generate go run github.com/Bin-Huang/newc@v0.8.3
&lt;/code>&lt;/pre>&lt;p>For example:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// My User Service&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">//go:generate go run github.com/Bin-Huang/newc@v0.8.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">type&lt;/span> &lt;span class="nx">UserService&lt;/span> &lt;span class="kd">struct&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">baseService&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">userRepository&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">repositories&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">UserRepository&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">proRepository&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">repositories&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ProRepository&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Then execute &lt;code>go generate ./...&lt;/code> on the command line to get the constructor code:&lt;/p>
&lt;p>&lt;code>constructor_gen.go&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// NewUserService Create a new UserService&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">func&lt;/span> &lt;span class="nf">NewUserService&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">baseService&lt;/span> &lt;span class="nx">baseService&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">userRepository&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">repositories&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">UserRepository&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">proRepository&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">repositories&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ProRepository&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nx">UserService&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="nx">UserService&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">baseService&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">baseService&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">userRepository&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">userRepository&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">proRepository&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">proRepository&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This tool works great with Wire. When you need to use new dependencies, just add members to the struct. No need to manually update constructors or worry about initialization—all repetitive work is handled by automated tools (Wire and Newc). It works very well in real projects.&lt;/p>
&lt;p>Of course, this tool may have some unconsidered situations, and I look forward to everyone&amp;rsquo;s feedback and suggestions.&lt;/p>
&lt;blockquote>
&lt;p>Don&amp;rsquo;t repeat yourself
&amp;ldquo;DRY&amp;rdquo;&lt;/p>&lt;/blockquote>
&lt;h2 id="summary">
&lt;a href="#summary" class="anchor">
&lt;svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
&lt;path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
&lt;/path>
&lt;/svg>
&lt;/a>
Summary
&lt;/h2>
&lt;p>Wire perfectly solves dependency injection problems, but it&amp;rsquo;s not a framework—it has no &amp;ldquo;magic&amp;rdquo; and isn&amp;rsquo;t a black box. It&amp;rsquo;s just a command-line tool that automatically generates initialization code for component instances based on actual needs. Then the problem is solved, with no additional complexity and no runtime performance overhead.&lt;/p>
&lt;p>Wire shares the same qualities as Golang: simple, direct, and pragmatic. It truly deserves to be called Go&amp;rsquo;s most elegant dependency injection tool!&lt;/p>
&lt;blockquote>
&lt;p>Keep it simple stupid
&amp;ldquo;K.I.S.S&amp;rdquo;&lt;/p>&lt;/blockquote></description></item></channel></rss>