Claude agents
Using coding agents without outsourcing engineering judgment
Purposeful subagents, code-enforced hooks, untrusted documents, deterministic scripts, and human approval that is real authority.
Coding agents are useful enough that the wrong mental model can become expensive. I do not treat an agent as an engineer I can hand a repository to and forget. I treat it as a fast collaborator operating inside an engineering system whose boundaries I still design, test, and own.
That distinction matters most when the work touches documents, business rules, or actions that have consequences outside the development environment. A fluent answer can hide a weak control model. The question is not only whether the agent can complete a task. It is whether I can explain what it was allowed to see, what it was allowed to do, how its output was checked, and where a human decision remained final.
I explored those questions directly in Fund Ops, a local portfolio prototype for fund-administration workflows. It uses fictitious data, never sends messages, and keeps approval human-only. The point was not to simulate a fully autonomous fund operator. It was to make delegation useful without outsourcing engineering judgment.
A subagent needs a reason
I create a subagent when isolation improves the quality or safety of the work—not because a multi-agent diagram looks sophisticated.
Fund Ops has three subagents. The document reader exists because source files are untrusted. It receives read-only tools and a narrow extraction task. The reviewer exists because a second check is more valuable when it is genuinely independent; it never sees the drafter's reasoning. The compliance gate exists because the exact text about to become a draft deserves a final check from a context that cannot quietly rewrite what it is judging.
Each boundary answers a concrete failure mode. A general-purpose agent could read a document, form a view, draft a message, review itself, and approve the result in one context. That is efficient in the same way that letting one person prepare, audit, and authorize a transaction is efficient. The problem is not capability. It is correlated judgment and missing separation of duties.
I use the same test before adding any agent: what information should this role not receive, what action should it not perform, and what independent signal does it contribute? If I cannot answer those questions, a function or deterministic script is usually the clearer choice.
Hooks are different from instructions
Prompt instructions are valuable. They define the task, give the model context, and describe the behavior I want. They are not an enforcement layer.
An instruction can say “do not run arbitrary commands.” A hook can inspect the proposed command and reject anything outside an allowlist. An instruction can say “approval belongs to a human.” A hook can block the model from reaching the approval path at all. That difference is the gap between asking for a boundary and implementing one.
Fund Ops uses PreToolUse hooks for that reason. The reviewer can run only the deterministic checks assigned to it, without pipes, chaining, or unrelated shell access. The compliance gate can inspect only the small set of paths and commands needed for its verdict. A human-only guard prevents model-initiated approval and protects the boundary between simulated runs and the real local application.
I still write careful instructions, but I reserve them for reasoning and task context. Permissions belong in code where they can be reviewed and tested. This also makes failures easier to diagnose. When a tool call is blocked, the system can identify the rule that blocked it instead of relying on a vague conclusion that the model “did not follow the prompt.”
Documents are data, not instructions
Documents are a special risk because natural-language systems are designed to follow language. A sentence inside a PDF can look structurally similar to a sentence written by the operator. Without a clear trust boundary, an embedded instruction can redirect the workflow before the agent has extracted the facts it was asked to find.
My pattern is to run a prompt-injection guard before any agent reads a document, then give the document reader only read and search capabilities. The source is explicitly treated as data. Suspicious instructions become something to report, not something to execute.
This is not a claim that a filter makes arbitrary documents safe. It is defense in depth: early detection, reduced permissions, narrow task scope, and separation between extraction and later decisions. If the reader cannot write files, run general commands, approve drafts, or contact an external system, the cost of a mistaken interpretation is constrained.
The same principle applies outside document workflows. Issue descriptions, web pages, logs, imported CSV fields, and user-generated content can all carry text that was not written for the agent to obey. I want the architecture to preserve that distinction even when the prose itself sounds authoritative.
Use scripts for exact work
I do not ask a language model to be a calculator with a good writing style. Dates, amounts, required-field checks, status transitions, and other exact operations belong in deterministic code.
In Fund Ops, scripts own those calculations and validations. The agent can interpret the situation, choose the relevant workflow, and explain the result, but it consumes outputs from code for facts that should be reproducible. Draft linting, persistence, task logging, and approval records also have explicit implementations rather than existing only as prompt conventions.
This division improves more than numerical accuracy. It gives tests something stable to assert, creates artifacts that can be inspected after a run, and reduces the amount of hidden state carried in the conversation. When a rule changes, I can update and test one deterministic component instead of hoping every prompt and agent context expresses the change consistently.
My working shorthand is: code calculates; the model reasons. The boundary is not absolute, but it is a useful default whenever an answer must be exact rather than merely plausible.
Human approval should be real authority
A human-in-the-loop label is weak if the system can proceed without the human or if the approver sees only a summary of what will happen. I prefer an approval boundary tied to the exact artifact and the exact action.
Fund Ops prepares drafts and quality evidence, then stops. The human-only approval command records who approved the exact draft and when. Approval does not send anything, and the prototype has no sending path. That keeps review, authorization, and external delivery conceptually separate.
For production systems, the final action may be a message, a database change, a deployment, or a financial operation. The same design question applies: does the person understand precisely what they are authorizing, and can the agent bypass that point through another tool?
I also need the surrounding evidence. Audit logs, run status, tests, and a local dashboard are not decorative administration. They help me reconstruct what happened and judge whether the workflow is behaving as designed.
Coding agents can accelerate implementation and widen the range of experiments I can run. They do not remove my responsibility for architecture, permissions, verification, or outcomes. I decide where delegation creates leverage, where code must be deterministic, where isolation reduces correlated mistakes, and where a person must retain authority. That is not friction around the engineering work. It is the engineering work.
