<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>halcight · System design and AI coding</title><description>Tech lead and software engineer halcight writes about system design and AI coding.</description><link>https://halcight.dev/</link><language>en</language><atom:link href="https://halcight.dev/rss.xml" rel="self" type="application/rss+xml"/><item><title>Hiring engineers in the age of AI</title><link>https://halcight.dev/posts/hiring-engineers-in-the-ai-era/</link><guid isPermaLink="true">https://halcight.dev/posts/hiring-engineers-in-the-ai-era/</guid><description>Coding skill is no longer the bar for hiring. What deserves a closer look: whether someone can communicate precisely with AI, form their own judgment about a whole system, and keep learning new technology.</description><pubDate>Fri, 13 Nov 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Technical interviews have traditionally centered on coding: which languages and frameworks a candidate knows, and whether they can write out the solution to an algorithm problem on a whiteboard.&lt;/p&gt;
&lt;p&gt;In the age of AI, that is no longer an effective bar. Someone who isn’t familiar with a particular programming language can still deliver a valuable product with AI’s help.&lt;/p&gt;
&lt;p&gt;Two abilities deserve a closer look.&lt;/p&gt;
&lt;p&gt;The first is &lt;strong&gt;an understanding of the whole system&lt;/strong&gt;: which parts a complete system should have, how they work together, and how to confirm it is running properly once it is live. Without that understanding, there is no way to evaluate the designs AI proposes.&lt;/p&gt;
&lt;p&gt;The second is &lt;strong&gt;curiosity&lt;/strong&gt;: actively keeping up with new knowledge, especially in AI. Tools and models change quickly, and today’s best practice may be outdated in six months. Whether someone keeps learning, trying and reflecting on new technology has a direct effect on how they grow as an engineer.&lt;/p&gt;
&lt;h2 id=&quot;the-six-abilities-that-matter-most-now&quot;&gt;The six abilities that matter most now&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1. Expressing intent precisely to AI.&lt;/strong&gt; AI can only work with the information it is given: the goal, the constraints, what counts as done, what is decided and what isn’t. The more clearly these are stated, the closer the output comes to what was intended. Vague input tends to produce a result that looks reasonable but misses the requirement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Understanding the AI’s intent.&lt;/strong&gt; When AI hands back a plan or a piece of code, an engineer has to be able to follow its reasoning: how it understood the requirement, what it assumed, and where it is guessing. Recognizing that the AI has misunderstood matters more than being able to write the same code by hand.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Forming an initial view of a system from a vague goal.&lt;/strong&gt; Requirements are usually vague at the start. Before starting work, a good engineer forms an initial view of the system: roughly which parts it will need and where the hard problems may lie. They revise that view as new information arrives. Only with that view can they tell whether the AI’s design is heading in the right direction. (How I do it: &lt;a href=&quot;https://halcight.dev/how-i-design-systems/&quot;&gt;How I design systems now&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Designing tests.&lt;/strong&gt; However fast code is generated, verification can’t be skipped. Which parts must be tested, in what way, and whether the tests actually cover the behavior they are meant to verify: all of this takes an engineer’s judgment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Designing monitoring.&lt;/strong&gt; Before release, tests check key behavior and reduce the risk of defects; after release, monitoring watches how the system runs and surfaces problems early. Neither guarantees the system is always correct, but both are needed. Which logs and metrics are needed, and who finds out about a failure and how quickly, should be considered at design time, not patched in after an incident.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. Managing an AI workflow.&lt;/strong&gt; Whether with one agent or several, how work is divided, how output is reviewed, how context is kept, and how to avoid becoming the bottleneck are engineering skills in their own right. (How I do it: &lt;a href=&quot;https://halcight.dev/posts/managing-a-dozen-agents/&quot;&gt;How I run a dozen AI agents at once&lt;/a&gt;.)&lt;/p&gt;
&lt;h2 id=&quot;how-to-assess-them-in-an-interview&quot;&gt;How to assess them in an interview&lt;/h2&gt;
&lt;h3 id=&quot;using-grill-me-to-assess-judgment-and-communication&quot;&gt;Using grill-me to assess judgment and communication&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/skills/productivity/grill-me/SKILL.md&quot;&gt;&lt;code&gt;grill-me&lt;/code&gt;&lt;/a&gt; is an AI skill: given a plan, the AI asks questions in rounds, following how the decisions depend on each other, and attaches a recommended answer to each question until every decision is settled.&lt;/p&gt;
&lt;p&gt;In the interview, give the candidate a vague requirement and ask them to talk it through with the AI using grill-me, until it becomes a clear design. Before the conversation, ask the candidate to outline the system’s boundaries, key assumptions and open questions; afterwards, ask which judgments changed and why. This step assesses ability 3: what the candidate’s own judgment was before the AI made any suggestions.&lt;/p&gt;
&lt;p&gt;During the conversation, the interviewer watches for two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Independent judgment.&lt;/strong&gt; The test is not whether the candidate disagrees with the AI, but whether they can explain why they accept or reject each suggestion, and how they would verify it. Someone who relies on the AI entirely will struggle to notice when it is wrong.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Precise communication.&lt;/strong&gt; Are the answers clear, with the context and reasons the AI needs? When the AI misunderstands, does the candidate notice and correct it?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compared with a whiteboard problem, this is much closer to the candidate’s daily work.&lt;/p&gt;
&lt;h3 id=&quot;system-design-do-they-consider-testing-and-monitoring-on-their-own&quot;&gt;System design: do they consider testing and monitoring on their own?&lt;/h3&gt;
&lt;p&gt;System design questions are still valuable, but what they assess has changed. AI can draw components and data flows too. What deserves attention is whether the candidate brings up, unprompted, how the system will be tested, how it will be monitored once live, and how failures will be detected. Bringing these up is only a lead; follow up with a concrete failure scenario: how a test would expose the problem, which signal would reveal it in production, and who would respond. These answers provide evidence of whole-system understanding, but one scenario is not enough to establish it.&lt;/p&gt;
&lt;h3 id=&quot;how-the-candidate-manages-ai-agents-day-to-day&quot;&gt;How the candidate manages AI agents day to day&lt;/h3&gt;
&lt;p&gt;Finally, ask the candidate how they work with AI day to day: how many agents they use at once, how they divide the work, how they review the output, what problems they have run into, which new tools they have tried recently, and why they kept or dropped them.&lt;/p&gt;
&lt;p&gt;Concrete experiences and lessons are a basis for further questions, but actual ability can’t be judged by how fluently a story is told. The question also assesses curiosity: what someone has been trying lately says more than the list of skills on their résumé.&lt;/p&gt;
&lt;h3 id=&quot;keeping-it-fair&quot;&gt;Keeping it fair&lt;/h3&gt;
&lt;p&gt;The hiring team should provide the same AI tool, model and account for everyone, with the needed skills installed in advance and time to get familiar with the setup, and use the same task, time limit and scoring criteria. No points for the number of agents or for experience with paid tools: a candidate who hasn’t had the chance to use these tools can still show, in the live task, how they organize work, verify results and learn new methods.&lt;/p&gt;
&lt;h2 id=&quot;in-closing&quot;&gt;In closing&lt;/h2&gt;
&lt;p&gt;What the age of AI needs is not the fastest coder, but engineers who can work with AI to turn a vague goal into a complete system that can be tested and monitored, and who keep learning.&lt;/p&gt;
</content:encoded></item><item><title>How I run a dozen AI agents at once</title><link>https://halcight.dev/posts/managing-a-dozen-agents/</link><guid isPermaLink="true">https://halcight.dev/posts/managing-a-dozen-agents/</guid><description>I align in depth only with each project&apos;s main agent. Another agent checks on all of them every 5 minutes and reports just two things: where work overlaps, and what is waiting for my decision.</description><pubDate>Sat, 07 Nov 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I work on eight projects in parallel, with as many as 17 agents running at peak.&lt;/p&gt;
&lt;p&gt;I manage them in &lt;a href=&quot;https://herdr.dev/tui/&quot;&gt;Herdr&lt;/a&gt;, a terminal workspace for coding agents. Each agent gets its own pane, and Herdr can tell whether it is working, blocked, done or idle. Agents can also read each other’s output and send each other messages.&lt;/p&gt;
&lt;p&gt;But the tool only solves visibility. The real bottleneck is my attention: every switch to another pane means rebuilding that project’s context in my head. The more agents I run, the more I become the slowest part of the system.&lt;/p&gt;
&lt;p&gt;My answer is a structure with two levels, plus one agent whose only job is to check on the others for me.&lt;/p&gt;
&lt;h2 id=&quot;deep-conversations-with-main-agents-shallow-reads-of-everyone&quot;&gt;Deep conversations with main agents, shallow reads of everyone&lt;/h2&gt;
&lt;figure class=&quot;diagram&quot;&gt;
&lt;svg font-family=&quot;JetBrains Mono, ui-monospace, monospace&quot; font-size=&quot;14&quot; fill=&quot;#545c57&quot; viewBox=&quot;0 0 760 396&quot; role=&quot;img&quot; aria-label=&quot;The shape: I talk in depth with four main agents; the orchestrator checks every agent and reports to me only what needs me; under the main agents are subagents, two levels in all.&quot;&gt;
&lt;defs&gt;&lt;marker id=&quot;d1-head&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;9&quot; refY=&quot;5&quot; markerWidth=&quot;6&quot; markerHeight=&quot;6&quot; orient=&quot;auto&quot;&gt;&lt;path fill=&quot;#9b3328&quot; d=&quot;M0 0L10 5L0 10z&quot;/&gt;&lt;/marker&gt;&lt;/defs&gt;
&lt;g fill=&quot;none&quot; stroke=&quot;#1d2320&quot; stroke-width=&quot;2.5&quot;&gt;&lt;path d=&quot;M105 86L100 170&quot;/&gt;&lt;path d=&quot;M105 86L293 170&quot;/&gt;&lt;path d=&quot;M105 86L486 170&quot;/&gt;&lt;path d=&quot;M105 86L680 170&quot;/&gt;&lt;/g&gt;
&lt;g fill=&quot;none&quot; stroke=&quot;#127a37&quot; stroke-width=&quot;2&quot; stroke-dasharray=&quot;6 5&quot;&gt;&lt;path d=&quot;M655 86L100 170&quot;/&gt;&lt;path d=&quot;M655 86L293 170&quot;/&gt;&lt;path d=&quot;M655 86L486 170&quot;/&gt;&lt;path d=&quot;M655 86L680 170&quot;/&gt;&lt;/g&gt;
&lt;g fill=&quot;none&quot; stroke=&quot;#545c57&quot; stroke-width=&quot;1.5&quot;&gt;&lt;path d=&quot;M293 226L251 290&quot;/&gt;&lt;path d=&quot;M293 226L337 290&quot;/&gt;&lt;path d=&quot;M486 226L417 290&quot;/&gt;&lt;path d=&quot;M486 226L486 290&quot;/&gt;&lt;path d=&quot;M486 226L555 290&quot;/&gt;&lt;path d=&quot;M680 226L638 290&quot;/&gt;&lt;path d=&quot;M680 226L720 290&quot;/&gt;&lt;/g&gt;
&lt;path fill=&quot;none&quot; stroke=&quot;#9b3328&quot; stroke-width=&quot;3&quot; d=&quot;M568 46H198&quot; marker-end=&quot;url(#d1-head)&quot;/&gt;
&lt;text font-size=&quot;14&quot; fill=&quot;#9b3328&quot; font-weight=&quot;500&quot; x=&quot;383&quot; y=&quot;34&quot; text-anchor=&quot;middle&quot;&gt;“needs you” alerts · one short report&lt;/text&gt;
&lt;rect fill=&quot;#127a37&quot; x=&quot;20&quot; y=&quot;20&quot; width=&quot;170&quot; height=&quot;66&quot; rx=&quot;12&quot;/&gt;
&lt;text font-size=&quot;15&quot; fill=&quot;#fff&quot; font-weight=&quot;500&quot; x=&quot;105&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot;&gt;Me&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; fill=&quot;#fff&quot; x=&quot;105&quot; y=&quot;70&quot; text-anchor=&quot;middle&quot;&gt;direction, decisions&lt;/text&gt;
&lt;rect fill=&quot;#fbfcfa&quot; stroke=&quot;#127a37&quot; stroke-width=&quot;2&quot; x=&quot;570&quot; y=&quot;20&quot; width=&quot;170&quot; height=&quot;66&quot; rx=&quot;12&quot;/&gt;
&lt;text font-size=&quot;15&quot; fill=&quot;#1d2320&quot; font-weight=&quot;500&quot; x=&quot;655&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot;&gt;Orchestrator&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; x=&quot;655&quot; y=&quot;70&quot; text-anchor=&quot;middle&quot;&gt;checks every 5 min&lt;/text&gt;
&lt;g fill=&quot;#fbfcfa&quot;&gt;&lt;rect x=&quot;20&quot; y=&quot;170&quot; width=&quot;160&quot; height=&quot;56&quot; rx=&quot;12&quot;/&gt;&lt;rect x=&quot;213&quot; y=&quot;170&quot; width=&quot;160&quot; height=&quot;56&quot; rx=&quot;12&quot;/&gt;&lt;rect x=&quot;406&quot; y=&quot;170&quot; width=&quot;160&quot; height=&quot;56&quot; rx=&quot;12&quot;/&gt;&lt;rect x=&quot;600&quot; y=&quot;170&quot; width=&quot;160&quot; height=&quot;56&quot; rx=&quot;12&quot;/&gt;&lt;/g&gt;
&lt;text font-size=&quot;15&quot; fill=&quot;#1d2320&quot; font-weight=&quot;500&quot; x=&quot;100&quot; y=&quot;194&quot; text-anchor=&quot;middle&quot;&gt;Main agent A&lt;/text&gt;&lt;text font-size=&quot;12.5&quot; x=&quot;100&quot; y=&quot;214&quot; text-anchor=&quot;middle&quot;&gt;Project A&lt;/text&gt;
&lt;text font-size=&quot;15&quot; fill=&quot;#1d2320&quot; font-weight=&quot;500&quot; x=&quot;293&quot; y=&quot;194&quot; text-anchor=&quot;middle&quot;&gt;Main agent B&lt;/text&gt;&lt;text font-size=&quot;12.5&quot; x=&quot;293&quot; y=&quot;214&quot; text-anchor=&quot;middle&quot;&gt;Project B&lt;/text&gt;
&lt;text font-size=&quot;15&quot; fill=&quot;#1d2320&quot; font-weight=&quot;500&quot; x=&quot;486&quot; y=&quot;194&quot; text-anchor=&quot;middle&quot;&gt;Main agent C&lt;/text&gt;&lt;text font-size=&quot;12.5&quot; x=&quot;486&quot; y=&quot;214&quot; text-anchor=&quot;middle&quot;&gt;Project C&lt;/text&gt;
&lt;text font-size=&quot;15&quot; fill=&quot;#1d2320&quot; font-weight=&quot;500&quot; x=&quot;680&quot; y=&quot;194&quot; text-anchor=&quot;middle&quot;&gt;Main agent D&lt;/text&gt;&lt;text font-size=&quot;12.5&quot; x=&quot;680&quot; y=&quot;214&quot; text-anchor=&quot;middle&quot;&gt;Project D&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; x=&quot;100&quot; y=&quot;313&quot; text-anchor=&quot;middle&quot;&gt;works alone&lt;/text&gt;
&lt;g fill=&quot;#eef1ed&quot; stroke=&quot;rgb(52,66,56)&quot; stroke-opacity=&quot;0.22&quot; stroke-width=&quot;1&quot;&gt;&lt;rect x=&quot;211&quot; y=&quot;290&quot; width=&quot;80&quot; height=&quot;36&quot; rx=&quot;9&quot;/&gt;&lt;rect x=&quot;297&quot; y=&quot;290&quot; width=&quot;80&quot; height=&quot;36&quot; rx=&quot;9&quot;/&gt;&lt;rect x=&quot;385&quot; y=&quot;290&quot; width=&quot;64&quot; height=&quot;36&quot; rx=&quot;9&quot;/&gt;&lt;rect x=&quot;454&quot; y=&quot;290&quot; width=&quot;64&quot; height=&quot;36&quot; rx=&quot;9&quot;/&gt;&lt;rect x=&quot;523&quot; y=&quot;290&quot; width=&quot;64&quot; height=&quot;36&quot; rx=&quot;9&quot;/&gt;&lt;rect x=&quot;600&quot; y=&quot;290&quot; width=&quot;76&quot; height=&quot;36&quot; rx=&quot;9&quot;/&gt;&lt;rect x=&quot;682&quot; y=&quot;290&quot; width=&quot;76&quot; height=&quot;36&quot; rx=&quot;9&quot;/&gt;&lt;/g&gt;
&lt;g font-size=&quot;12.5&quot; fill=&quot;#1d2320&quot; text-anchor=&quot;middle&quot;&gt;&lt;text x=&quot;251&quot; y=&quot;313&quot;&gt;build&lt;/text&gt;&lt;text x=&quot;337&quot; y=&quot;313&quot;&gt;review&lt;/text&gt;&lt;text x=&quot;417&quot; y=&quot;313&quot;&gt;team a&lt;/text&gt;&lt;text x=&quot;486&quot; y=&quot;313&quot;&gt;team b&lt;/text&gt;&lt;text x=&quot;555&quot; y=&quot;313&quot;&gt;team c&lt;/text&gt;&lt;text x=&quot;638&quot; y=&quot;313&quot;&gt;split&lt;/text&gt;&lt;text x=&quot;720&quot; y=&quot;313&quot;&gt;review&lt;/text&gt;&lt;/g&gt;
&lt;path fill=&quot;none&quot; stroke=&quot;#545c57&quot; stroke-width=&quot;1.5&quot; stroke-dasharray=&quot;3 4&quot; d=&quot;M20 352H760&quot;/&gt;
&lt;text font-size=&quot;12.5&quot; x=&quot;390&quot; y=&quot;380&quot; text-anchor=&quot;middle&quot;&gt;Depth limit: a subagent never starts its own subagents&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption&gt;&lt;ul class=&quot;diagram-key&quot;&gt;
&lt;li&gt;&lt;svg width=&quot;28&quot; height=&quot;8&quot; viewBox=&quot;0 0 28 8&quot; aria-hidden=&quot;true&quot;&gt;&lt;path fill=&quot;none&quot; stroke=&quot;#1d2320&quot; stroke-width=&quot;2.5&quot; d=&quot;M1 4H27&quot;/&gt;&lt;/svg&gt;I align in depth with each main agent&lt;/li&gt;
&lt;li&gt;&lt;svg width=&quot;28&quot; height=&quot;8&quot; viewBox=&quot;0 0 28 8&quot; aria-hidden=&quot;true&quot;&gt;&lt;path fill=&quot;none&quot; stroke=&quot;#127a37&quot; stroke-width=&quot;2&quot; stroke-dasharray=&quot;6 5&quot; d=&quot;M1 4H27&quot;/&gt;&lt;/svg&gt;the orchestrator reads, notifies, relays&lt;/li&gt;
&lt;li&gt;&lt;svg width=&quot;28&quot; height=&quot;8&quot; viewBox=&quot;0 0 28 8&quot; aria-hidden=&quot;true&quot;&gt;&lt;path fill=&quot;none&quot; stroke=&quot;#9b3328&quot; stroke-width=&quot;3&quot; d=&quot;M1 4H27&quot;/&gt;&lt;/svg&gt;alerts to me&lt;/li&gt;
&lt;li&gt;&lt;svg width=&quot;28&quot; height=&quot;8&quot; viewBox=&quot;0 0 28 8&quot; aria-hidden=&quot;true&quot;&gt;&lt;path fill=&quot;none&quot; stroke=&quot;#545c57&quot; stroke-width=&quot;1.5&quot; d=&quot;M1 4H27&quot;/&gt;&lt;/svg&gt;a main agent starts subagents and accepts their work&lt;/li&gt;
&lt;/ul&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Two kinds of conversation run at the same time:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Me and the main agents: in depth.&lt;/strong&gt; Each project has one main agent that holds the project’s full context. I align with it directly on the design, the plan and the open decisions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The orchestrator and every agent: shallow reads.&lt;/strong&gt; The orchestrator owns no project. Every 5 minutes it reads the latest output of every agent, and it reports to me only what needs me.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I see the whole picture without switching between projects. When I need to go deep, I enter one project and talk to one main agent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Only two levels.&lt;/strong&gt; A main agent may start subagents: a reviewer, the implementer of one PR, or a few groups working in parallel. A subagent never starts another level. Every agent is therefore at most one step from a main agent that holds the context, and that main agent accepts its work. Any deeper, and responsibility blurs while context leaks away at every level.&lt;/p&gt;
&lt;h2 id=&quot;four-roles&quot;&gt;Four roles&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Me:&lt;/strong&gt; I set the direction with each main agent, and I handle the decisions that need me, approval dialogs, and the steps only I can take in a web UI. Risky operations, such as writes to cloud resources or infrastructure changes, need my explicit OK.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Main agent:&lt;/strong&gt; owns one project: its context, its plan, its PRs, and a file that records its current state. It owns every PR it opens until merge, including CI, review comments and conflicts. It may start subagents, and it accepts their work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subagent:&lt;/strong&gt; does one well-bounded task for its main agent, such as implementing a PR, reviewing a design or making one cleanup pass. It reports to its main agent and is closed when it is done.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Orchestrator:&lt;/strong&gt; owns no project and no PR. Every 5 minutes it checks every agent, reports what needs me, notifies both sides of any overlap, and relays my answers word for word.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;every-5-minutes-overlaps-first-then-attention&quot;&gt;Every 5 minutes: overlaps first, then attention&lt;/h2&gt;
&lt;figure class=&quot;diagram&quot;&gt;
&lt;svg font-family=&quot;JetBrains Mono, ui-monospace, monospace&quot; font-size=&quot;14&quot; fill=&quot;#545c57&quot; viewBox=&quot;0 0 760 204&quot; role=&quot;img&quot; aria-label=&quot;The 5-minute loop: the overlap check, then the attention check, then a report to me, then the next run.&quot;&gt;
&lt;defs&gt;&lt;marker id=&quot;d2-head&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;9&quot; refY=&quot;5&quot; markerWidth=&quot;6&quot; markerHeight=&quot;6&quot; orient=&quot;auto&quot;&gt;&lt;path fill=&quot;#127a37&quot; d=&quot;M0 0L10 5L0 10z&quot;/&gt;&lt;/marker&gt;&lt;/defs&gt;
&lt;g fill=&quot;none&quot; stroke=&quot;#127a37&quot; stroke-width=&quot;2&quot;&gt;&lt;path d=&quot;M96 72H124&quot; marker-end=&quot;url(#d2-head)&quot;/&gt;&lt;path d=&quot;M340 72H374&quot; marker-end=&quot;url(#d2-head)&quot;/&gt;&lt;path d=&quot;M590 72H624&quot; marker-end=&quot;url(#d2-head)&quot;/&gt;&lt;path d=&quot;M688 116V140Q688 150 678 150H66Q56 150 56 140V118&quot; marker-end=&quot;url(#d2-head)&quot;/&gt;&lt;/g&gt;
&lt;circle fill=&quot;#fbfcfa&quot; stroke=&quot;#127a37&quot; stroke-width=&quot;2&quot; cx=&quot;56&quot; cy=&quot;72&quot; r=&quot;38&quot;/&gt;
&lt;text font-size=&quot;15&quot; fill=&quot;#1d2320&quot; font-weight=&quot;500&quot; x=&quot;56&quot; y=&quot;70&quot; text-anchor=&quot;middle&quot;&gt;5 min&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; x=&quot;56&quot; y=&quot;89&quot; text-anchor=&quot;middle&quot;&gt;timer&lt;/text&gt;
&lt;g fill=&quot;#fbfcfa&quot;&gt;&lt;rect x=&quot;128&quot; y=&quot;30&quot; width=&quot;210&quot; height=&quot;84&quot; rx=&quot;12&quot;/&gt;&lt;rect x=&quot;378&quot; y=&quot;30&quot; width=&quot;210&quot; height=&quot;84&quot; rx=&quot;12&quot;/&gt;&lt;/g&gt;
&lt;rect fill=&quot;#f8e1dc&quot; stroke=&quot;#9b3328&quot; stroke-width=&quot;1.5&quot; x=&quot;628&quot; y=&quot;30&quot; width=&quot;120&quot; height=&quot;84&quot; rx=&quot;12&quot;/&gt;
&lt;text font-size=&quot;15&quot; fill=&quot;#1d2320&quot; font-weight=&quot;500&quot; x=&quot;146&quot; y=&quot;58&quot;&gt;1 · Overlap check&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; x=&quot;146&quot; y=&quot;82&quot;&gt;worktrees, changed areas,&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; x=&quot;146&quot; y=&quot;101&quot;&gt;open PRs and their files&lt;/text&gt;
&lt;text font-size=&quot;15&quot; fill=&quot;#1d2320&quot; font-weight=&quot;500&quot; x=&quot;394&quot; y=&quot;58&quot;&gt;2 · Attention check&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; x=&quot;394&quot; y=&quot;82&quot;&gt;status, last reply,&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; x=&quot;394&quot; y=&quot;101&quot;&gt;dialogs, disk, Docker&lt;/text&gt;
&lt;text font-size=&quot;15&quot; fill=&quot;#9b3328&quot; font-weight=&quot;500&quot; x=&quot;688&quot; y=&quot;68&quot; text-anchor=&quot;middle&quot;&gt;3 · Report&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; fill=&quot;#9b3328&quot; font-weight=&quot;500&quot; x=&quot;688&quot; y=&quot;92&quot; text-anchor=&quot;middle&quot;&gt;a short reply&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; x=&quot;372&quot; y=&quot;141&quot; text-anchor=&quot;middle&quot;&gt;next run&lt;/text&gt;
&lt;text font-size=&quot;12.5&quot; x=&quot;380&quot; y=&quot;190&quot; text-anchor=&quot;middle&quot;&gt;Notices go out during step 1; my answers are relayed between runs&lt;/text&gt;
&lt;/svg&gt;
&lt;/figure&gt;
&lt;p&gt;Every run of the orchestrator follows the same order: the overlap check, the attention check, then the report.&lt;/p&gt;
&lt;p&gt;These two checks are the core of the whole setup. With many agents, the usual problem is not one agent getting something wrong. It is two agents each doing the right thing and colliding, or an agent blocked and waiting for me while I have no idea.&lt;/p&gt;
&lt;h2 id=&quot;overlap-check-one-direction-per-area&quot;&gt;Overlap check: one direction per area&lt;/h2&gt;
&lt;p&gt;Main agents cannot see each other’s context.&lt;/p&gt;
&lt;p&gt;An &lt;strong&gt;overlap&lt;/strong&gt; is one area that two agents are both changing or deciding on: a module, a document or architecture decision record (ADR), an interface contract, a PR, a deployment. The orchestrator matches by meaning, not only by path: &lt;code&gt;services/foo&lt;/code&gt; and &lt;code&gt;docs/spec/foo&lt;/code&gt; are the same area.&lt;/p&gt;
&lt;p&gt;When it finds an overlap, the orchestrator notifies both sides at once. Before either one changes that area again, both must know the other’s plan and agree.&lt;/p&gt;
&lt;p&gt;These are not overlaps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a main agent and its own subagents, which share one task brief;&lt;/li&gt;
&lt;li&gt;an agent that only reads or reviews;&lt;/li&gt;
&lt;li&gt;an area where one side’s change is already merged.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A pair that was notified in the last 24 hours, with no new change since, is not notified again.&lt;/p&gt;
&lt;h3 id=&quot;example-two-frontend-prs-touching-the-same-files&quot;&gt;Example: two frontend PRs touching the same files&lt;/h3&gt;
&lt;p&gt;Projects B and E are building separate apps in the same frontend repository.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The day before&lt;/strong&gt;, the orchestrator first told both about the shared parts of the repository (the component library, the mock backend, the interface contracts), and they agreed which shared files each one could change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;10:11&lt;/strong&gt;: a PR from project E changed the developer guide and the lock file, and it was next in line to merge. Project B’s newly opened skeleton PR changed the same two files. The orchestrator’s read: aligned (separate apps), but whichever merged second would conflict. It notified both and recorded the pair.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;10:12&lt;/strong&gt;: the two agents talked directly and agreed that E merges first and B rebases after. Each wrote this into its state file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;10:16&lt;/strong&gt;: E’s PR merged and was deployed to the development environment.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;10:36&lt;/strong&gt;: B finished its rebase. The guide kept both changes, the lock file was unchanged, and type checks, lint, tests and the build all passed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nobody came to me. My report gained only one line: “Notified … aligned”.&lt;/p&gt;
&lt;p&gt;The notice to project B went roughly like this; project E got the mirror image:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Overlap check (from the orchestrator): you and project E are both changing shared files in the frontend repository: the developer guide and the lock file.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- You: your skeleton PR changes both files.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- Them: a PR that also changes both files is about to merge.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- My read: aligned (separate apps), but the second PR to merge will conflict.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Before you change these files again, send them one message with your plan, read their answer, agree who rebases, and write the agreement into your state file.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;If you cannot agree, or the choice belongs to a human, stop changing these files and say so in your reply.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last sentence is the important one. A conflict the two cannot settle, or a decision that should be mine, is never settled privately between agents. That work stops and shows up in my report as a conflict for me.&lt;/p&gt;
&lt;h2 id=&quot;attention-check-what-counts-as-needs-me&quot;&gt;Attention check: what counts as “needs me”&lt;/h2&gt;
&lt;p&gt;After the overlap check, the orchestrator decides for each agent whether it is waiting for me. The key is a precise definition of “needs me”. Too broad, and the report fills with noise I soon stop reading. Too narrow, and a truly blocked agent slips through.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Needs me:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is blocked on an approval or question dialog. The report quotes the dialog.&lt;/li&gt;
&lt;li&gt;Its last reply asks me to decide, choose or do something, and nothing has answered it since. A step refused by a permission check counts.&lt;/li&gt;
&lt;li&gt;It reports a failure it cannot fix on its own.&lt;/li&gt;
&lt;li&gt;The host is in trouble: less than 30 GiB of disk left, or Docker not responding. Every agent’s builds and end-to-end tests depend on both.&lt;/li&gt;
&lt;li&gt;A hand-off watcher has not polled for more than 10 minutes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Doesn’t need me:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Waiting for a teammate’s approval or for CI. That goes under Waiting.&lt;/li&gt;
&lt;li&gt;Text in an agent’s input box. That is my own unsent input or a suggestion, not a question.&lt;/li&gt;
&lt;li&gt;A question that an answer I relayed has already closed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each agent that doesn’t need me appears on exactly one line: Working, Waiting or Idle. Idle agents note their last area of work, so I can decide whether to give them a new task or close them.&lt;/p&gt;
&lt;h3 id=&quot;the-report&quot;&gt;The report&lt;/h3&gt;
&lt;p&gt;The report always has the same shape: overlaps first, then what needs me, then one line each for Working, Waiting and Idle. Here is one from a morning, with the names replaced:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Overlaps: nothing needs you. Notified: developer guide and lock file in the frontend repository (project B ↔ project E, aligned).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Needs you:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1. Project B (new app skeleton): grant the frontend repository read access to an internal npm package.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2. Project A (performance): an infrastructure change that cuts a service to 1 vCPU. Keep it or close it?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Working: project B&apos;s implementer (app skeleton); project C&apos;s group c (16 end-to-end scenarios)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Waiting: project C&apos;s group a (1 of 2 approvals); project D (1 of 2 approvals)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Idle:    chores (Docker and disk cleanup); a test coverage audit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Host:    313 GiB free, Docker OK&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It takes a few seconds to read, and then I go back to my own work.&lt;/p&gt;
&lt;h3 id=&quot;that-mornings-three-alerts&quot;&gt;That morning’s three alerts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;09:45&lt;/strong&gt; Docker had stopped, so project C’s group c could not run its 16 end-to-end scenarios, and the main agent asked in a dialog. I chose “start Docker”; the orchestrator started it and answered the dialog. The scenarios ran, and group c opened a PR.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;09:53&lt;/strong&gt; Project B needed a step only I could take in the GitHub web UI: granting the frontend repository read access to an internal package. Once I had, the orchestrator relayed “done”, and project B started on its first frontend PR right away.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;09:53&lt;/strong&gt; Project A had measured the load burst at morning start-up, and asked whether to keep or close an infrastructure change that cuts a service to 1 vCPU. I answered “keep it and start”. A few minutes later it opened a PR whose Terraform plan showed only the expected change.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without the orchestrator, I would have found out that Docker had stopped only when I happened to look at project C.&lt;/p&gt;
&lt;h2 id=&quot;attention-goes-to-decisions&quot;&gt;Attention goes to decisions&lt;/h2&gt;
&lt;p&gt;What matters here is not how many agents run, but where attention goes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only I can set the direction and make the trade-offs, so I talk in depth with the main agents.&lt;/li&gt;
&lt;li&gt;“Who is waiting for me” and “who is colliding with whom” can be defined precisely and checked on a schedule, so they go to the orchestrator.&lt;/li&gt;
&lt;li&gt;Two levels mean that every agent’s work is accepted by a main agent that holds the context.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can run many agents in parallel, but only one person makes the decisions. Keep that person’s attention for decisions, and leave the rest to the process.&lt;/p&gt;
</content:encoded></item><item><title>Is Japanese IT behind?</title><link>https://halcight.dev/posts/is-japanese-it-behind/</link><guid isPermaLink="true">https://halcight.dev/posts/is-japanese-it-behind/</guid><description>Yes and no. Japan has no shortage of great engineers. What it lacks is companies built to let them work.</description><pubDate>Wed, 04 Nov 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;People often say Japanese IT is behind. My answer is yes and no.&lt;/p&gt;
&lt;h2 id=&quot;no-shortage-of-great-engineers&quot;&gt;No shortage of great engineers&lt;/h2&gt;
&lt;p&gt;Japanese engineers have given the industry a lot. The &lt;a href=&quot;https://www.qrcode.com/en/history/&quot;&gt;QR code&lt;/a&gt; came out of Denso Wave in 1994, with Masahiro Hara leading its development. Yukihiro Matsumoto released &lt;a href=&quot;https://www.ruby-lang.org/en/about/&quot;&gt;Ruby&lt;/a&gt; in 1995. Lean and kanban in software development both trace back to the Toyota Production System. Japan has never lacked great engineers.&lt;/p&gt;
&lt;p&gt;Those examples say nothing about the average, of course. I do think the average Japanese software engineer is behind their peers in the US and China, and universities have a lot to do with it: software engineering as a discipline is neither widespread nor taken very seriously here. But I don’t think that is the main point. Plenty of engineers in the US came from other majors, and it hasn’t held them back.&lt;/p&gt;
&lt;h2 id=&quot;the-real-problem-is-how-companies-are-built&quot;&gt;The real problem is how companies are built&lt;/h2&gt;
&lt;p&gt;The real problem is that the structure of the companies hasn’t kept up.&lt;/p&gt;
&lt;p&gt;The numbers show it too. According to &lt;a href=&quot;https://www.ipa.go.jp/archive/press/2022/press20230316-2.html&quot;&gt;IPA&lt;/a&gt;, Japan’s Information-technology Promotion Agency, 73.6% of Japan’s IT workers worked at IT companies in 2020, and only about a quarter at companies in other industries. The US is the other way round: only 35.1% were at IT companies in 2021, and most work at the companies that use IT. In other words, many Japanese companies have no engineering team of their own. Their systems go to system integrators, often through layers of subcontractors. The people who decide are far from the people who write the code, and engineers have little say in the product itself.&lt;/p&gt;
&lt;p&gt;On November 2, 2026, GMO Internet Group &lt;a href=&quot;https://atmarkit.itmedia.co.jp/ait/articles/2611/03/news014.html&quot;&gt;held a press conference&lt;/a&gt; about unauthorized access to its Onamae.com Desktop Cloud service. The attackers got in through remote desktop servers used by customers and stole an administrator account, and the group’s own security company had pointed out problems with the system back in 2024. What stayed with me, though, wasn’t the security failure. It was one moment at the conference: as the responsible manager began to explain to the press, the group’s chief interrupted him to &lt;a href=&quot;https://www.j-cast.com/2026/11/02518875.html&quot;&gt;scold him for his unbuttoned jacket&lt;/a&gt;. “We are apologizing, and you leave your jacket open?”&lt;/p&gt;
&lt;p&gt;It’s hard to imagine Satya Nadella or Elon Musk stopping someone over a button, in public or in private. Most people would probably find it absurd, yet the person who did it clearly saw nothing wrong. To me this is exactly why so many Japanese IT companies fall behind: a strict hierarchy built around power doesn’t fit with the open, equal environment that software engineering needs.&lt;/p&gt;
&lt;p&gt;By hierarchy I don’t mean reporting lines. Microsoft and Amazon have hierarchies and reporting lines too, but they divide the work; they are not a chain of command. There, many projects start from the bottom up. In Japanese companies, ideas rarely travel up like that. Whether the deeper cause lies in Japanese society and culture is beyond the scope of this post, and I won’t go into it here. What is clear is that complex software engineering struggles to get anywhere under a strong hierarchy of power.&lt;/p&gt;
&lt;p&gt;Reasoned debate, and knowledge tested by argument, need an environment of equals. Google’s &lt;a href=&quot;https://rework.withgoogle.com/intl/en/guides/understand-team-effectiveness&quot;&gt;Project Aristotle&lt;/a&gt; studied 180 teams and found that, among those teams, of the five factors behind team effectiveness, the most important was psychological safety: team members trust that no one will embarrass or punish them for admitting a mistake, asking a question or offering a new idea. Diversity matters as well. A &lt;a href=&quot;https://hbr.org/2016/11/why-diverse-teams-are-smarter&quot;&gt;Harvard Business Review article&lt;/a&gt; that sums up the research finds that diverse teams focus more on facts, re-examine them more often and make fewer factual errors. These are exactly what many Japanese companies lack.&lt;/p&gt;
&lt;h2 id=&quot;do-the-leaders-know-the-technology&quot;&gt;Do the leaders know the technology?&lt;/h2&gt;
&lt;p&gt;Another difference is whether the people leading teams know the technology. In Japanese IT companies, project managers tend to sit near the top of the hierarchy. American and Chinese IT companies are different. At Microsoft, I saw many PMs (program managers) who wanted to become engineers who write code, and very few engineers who wanted to become PMs; most team managers came up as engineers too.&lt;/p&gt;
&lt;h2 id=&quot;what-responsibility-means&quot;&gt;What responsibility means&lt;/h2&gt;
&lt;p&gt;Then there is how responsibility is understood. In many Japanese companies, one important question behind a decision is whether it keeps the organization from being held responsible: “If I do it this way, I won’t be blamed when something goes wrong.” That’s understandable, but it’s a factor I rarely felt at American IT companies.&lt;/p&gt;
&lt;h2 id=&quot;what-japan-is-good-at&quot;&gt;What Japan is good at&lt;/h2&gt;
&lt;p&gt;Now look at what Japan does well. In its creative industries, what one person contributes counts for a great deal. In heavy industry, cars for one, what counts is how rigorously a team follows the rules. Software engineering needs a third thing: discussion among equals, and fast iteration.&lt;/p&gt;
&lt;p&gt;Japanese IT has its own individual and small-team breakthroughs too. Chainer, the deep learning framework from Preferred Networks, introduced the &lt;a href=&quot;https://chainer.org/announcement/2019/12/05/released-v7.html&quot;&gt;define-by-run&lt;/a&gt; style in 2015, an approach the research community went on to adopt widely. But for the industry as a whole to move forward, the way its teams think has to change.&lt;/p&gt;
&lt;h2 id=&quot;what-japanese-it-companies-should-do&quot;&gt;What Japanese IT companies should do&lt;/h2&gt;
&lt;p&gt;First, learn from the top American tech companies: build engineering teams of your own and outsource less. Your systems are a core capability, and they shouldn’t all be in someone else’s hands. Only engineers inside the company can be close to the business and the product, and answer for the results.&lt;/p&gt;
&lt;p&gt;Second, bring in highly skilled people from abroad, and understand why: you don’t pay top salaries to smart people to tell them what to do. You pay them so they can tell you what to do.&lt;/p&gt;
&lt;p&gt;Third, and most important, embrace an open, equal workplace and weaken the hierarchy of power. At work, focus on the work itself, not, as GMO’s chief did, on a button at a press conference held to apologize.&lt;/p&gt;
&lt;p&gt;Fourth, let people who understand the technology make the technical decisions. Give engineers a career path parallel to management, so senior engineers can reach the matching level and pay without becoming managers. The people who lead engineering teams should ideally be engineers too.&lt;/p&gt;
&lt;p&gt;Fifth, when something goes wrong, review it without blaming anyone. Google’s SRE practice calls this a &lt;a href=&quot;https://sre.google/sre-book/postmortem-culture/&quot;&gt;blameless postmortem&lt;/a&gt;: the review looks only for what caused the incident, accuses no person or team, and assumes everyone acted in good faith and did the right thing with what they knew at the time. What gets fixed is the system and the process, not people. Once people stop fearing blame, decisions go back to asking what is best, not what is least likely to go wrong.&lt;/p&gt;
&lt;p&gt;I’m not writing this to point fingers. I want to show where there is room to improve.&lt;/p&gt;
</content:encoded></item></channel></rss>