Claude and Codex Agent Engineering

Architecture diagram: Claude and Codex agents work from a git repository in isolated branches, opening pull requests that pass through CI and human review before merge.

Claude and Codex agent engineering is how development teams get AI that works inside their actual codebase — not a chat window they copy-paste from. Software Depo sets up repository-aware coding agents with project instructions, reusable skills, and safe access to your systems, so the agent understands your code and follows your rules.

Agents That Know Your Project

A generic AI assistant starts from zero every conversation. A properly engineered repository agent carries persistent project knowledge: your architecture, conventions, and the reasons behind past decisions — captured in project instructions and reusable skills so successful workflows are not re-explained every time.

What We Set Up

  • Repository-aware Claude Code and Codex agents with project instructions
  • Reusable skills and workflows so proven procedures are repeatable
  • MCP connections giving agents safe, scoped access to your internal systems
  • Hooks and automation for tests, checks, and review steps
  • Code-review and test-generation agents that assist without merging on their own
  • Sandboxed execution and human approval before any change is published

Claude or Codex?

Both are capable; the right choice depends on your stack, your tooling, and where your team already works. We are not tied to one — we will recommend based on your repositories, your CI, and your security requirements, and set up whichever fits with the guardrails that keep it safe.

Safe by Construction

Coding agents touch source, credentials, and infrastructure — so we scope their access, sandbox execution, and require human approval before anything ships. The agent proposes; a person decides.

Tell us about your codebase and workflow — languages, repositories, CI, and what you want an agent to help with. We will set it up with the right guardrails.

Related services

What Are Coding Agents Actually Good At?

Current coding agents are strong at bounded, well-specified work in a codebase they can read: implementing a described change across several files, writing tests, migrating a pattern consistently, explaining unfamiliar code, and doing the mechanical parts of a refactor. They are weakest where the requirement is ambiguous, where the judgement is architectural, and where the consequence of being subtly wrong is high.

The productive framing is not “does it replace a developer” but “which parts of the work are mechanical enough to delegate, with review”. That is a large fraction of most codebases.

How Do You Adopt Them Without Creating a Mess?

  • Review everything. Agent output goes through the same review as human output. Teams that relax this accumulate code nobody understands.
  • Tests are the guardrail. A codebase with good test coverage is one where agents are genuinely useful. One without is where they are dangerous.
  • Give them the project context. Conventions, architecture and constraints recorded in the repository make output dramatically better than a general prompt does.
  • Bound the permissions. What an agent may run, install and push should be an explicit decision, especially in CI.
  • Keep secrets out. Credentials, customer data and proprietary keys need the same handling they always did.

What Does Rolling This Out to a Team Involve?

Less tooling than people expect and more convention. The work is setting up repository-level context so the agent understands the project, agreeing review standards, deciding what agents may and may not touch, integrating with existing CI, and training the team on where the tools help and where they do not.

The teams that get the most from these tools treat them as a new member who is fast, well-read, tireless, and occasionally confidently wrong — and who therefore needs the same code review everyone else gets.

Related: AI adoption and training · AI agent skills · AI and MCP security review.

What The Agent Can Actually See

A coding agent does not hold your repository in memory. It reads files on demand: it searches, opens what the search returned, and keeps that text in a finite context window shared with the conversation so far, the tool definitions, and the project instructions. Everything it knows about your code at a given moment is what it chose to read a few tool calls earlier.

The practical consequence is that what is easy to find gets read, and what is hard to find gets guessed at. Search quality, not model quality, is usually what separates an agent that edits the right file from one that reimplements a helper that already exists two directories over. Clear naming, a predictable directory layout, and a README that says where things live pay off harder here than in a codebase read only by people, because a developer who cannot find something asks a colleague, and an agent just keeps searching until it concludes the thing does not exist.

  • Keep generated code, vendored libraries, and build output out of search range. Ignore configuration is worth fixing before anything else, because every match that looks relevant and is not costs a read and can seed a wrong assumption.
  • Scope work in a monorepo to the package or service being changed, and say so explicitly, rather than pointing the agent at the repository root and hoping it infers the boundary.
  • Split a large piece of work into several scoped sessions with a written handoff between them, instead of one long session that compacts halfway through and loses its early reasoning.
  • Treat "I could not find where this is handled" as a finding about the codebase rather than a failure of the agent. It usually means the logic is spread across layers, or the name in the code is not the name the team uses for it.

What Belongs In Project Instructions

The instruction file is loaded at the start of every session, so its length is a standing cost on every task, and everything in it competes for attention with everything else in it. That argues for a short file carrying what cannot be derived by reading the code: the invariants, the reasons behind decisions that look wrong from the outside, the exact command that runs the tests, which parts of the tree are load bearing, and the deprecated pattern that still appears in older files and must not be copied forward. Conventions a formatter or a linter already enforces do not need to be in it, because the tool corrects them anyway.

The failure mode is drift. Instructions are prose about code that keeps changing, and when the two disagree the agent will generally believe the file it just read, so a stale instruction file produces confident behavior that matches neither the document nor the code. That is an argument for updating it in the same pull request that invalidates it, and for keeping it short enough that reviewing it is not its own project. Skills differ from the instruction file in one way that matters here: they are pulled in when relevant rather than loaded every session, so a skill can afford the length a step by step procedure actually needs.

  • Write down what surprised the last developer who joined. That is the same material an agent needs, and it is usually not in any existing document.
  • Name the commands exactly: test, lint, build, and any argument that is not the default. Ambiguity here produces an agent that invents a plausible command and then reports that the project is broken.
  • Record the things that are true but look wrong: the intentional duplication, the version pin nobody can lift yet, the module that must not be imported from anywhere else.
  • Keep per-directory instructions next to the code they describe, so that context arrives with the file rather than sitting in a long root file that is loaded whether or not the task touches that area.

How MCP Access Is Actually Scoped

An MCP server is a process that advertises a list of tools with typed inputs, and the agent calls them the way it calls a file read. Two things follow from that shape. Tool names, descriptions, and schemas are loaded into context before the agent does anything, so a server exposing forty operations spends part of the budget on every task whether the task needs it or not. And credentials sit in the server's configuration rather than in the conversation: the agent asks for issue 4412, and the server holds the token and decides whether that request is allowed.

Transport determines what you are actually auditing. A stdio server runs as a local subprocess on the developer's machine, with that machine's environment and file access, so its blast radius is the workstation. A remote server is reached over HTTP with its own authentication, often an OAuth grant per user, so access is visible and revocable centrally but the traffic leaves the machine. The two need different reviews, and a server that is reasonable as a local subprocess for one developer is not automatically reasonable as a shared remote endpoint for everyone.

  • Give each server the narrowest credential that works: a read-only database role, a token scoped to one repository, a service account with no administrative rights.
  • Separate read from write. A server that can read tickets and a server that can close them are different grants, and only one of them needs to sit behind an approval prompt.
  • Treat everything a server returns as data, never as instruction. Text in a ticket, a wiki page, or an uploaded document can be written to address the agent, and an agent that acts on it is doing what its author wanted rather than what you asked.
  • Count the tools before connecting another server. Connecting everything available makes the agent worse at choosing, because most of what it is choosing among is irrelevant to the task in front of it.

Permission Rules and Hooks, Concretely

Guardrails here are configuration, not instruction text. Two mechanisms do most of the work. Permission rules match a tool call before it runs and allow it, deny it, or hold it for a person. Hooks are commands the runtime executes at fixed points in the loop, and a post-call hook can run the formatter, the linter, or the type checker over what just changed and feed failures back while the context is still live, which is the difference between the agent correcting its own mistake and a reviewer finding it a day later.

There is a second-order effect worth settling before any of these rules get written. Every rule that requires approval trains the person approving it, and a prompt that fires forty times an hour gets approved unread, which is worse than no gate at all because it still looks like a gate. So the deny list should be short and specific, and the allow list wide enough that the prompts left over are worth a person's attention. Automation that runs a check is also strictly better than prose asking for it, since prose in an instruction file competes with everything else in that file. The rules below are the ones to decide first.

  • Deny writes outside the repository, and deny reads of credential stores, environment files, and the home directory, so an agent cannot pick up a token in the course of an unrelated task.
  • Allow the read-only commands outright: status, diff, log, listing files, running the test suite. These are most of the calls, and prompting on them buys nothing except habituation.
  • Require approval for anything that leaves the machine or changes shared state: pushes, package publishes, deploys, migrations against a shared database, and destructive commands of any kind.
  • Decide package installation deliberately. Installing a dependency the agent picked is a supply chain decision, and it belongs with the people who normally make those.

Running Agents In CI

What decides whether an agent can run unattended in CI is not model capability but whether the repository builds and tests from a clean checkout with no interactive prompts, no manual credential step, and no undocumented local tooling. Test suites that need a running database, a network connection to an internal service, or a hand-seeded fixture need a container or a documented setup path first. An agent in a CI job has nobody to ask.

The second constraint is what a non-interactive run may do with its result. There is no person in the loop mid-run, so every permission decision is made in advance, and the safe shape is one where the output is a proposal: a branch, a pull request, a comment on a diff. Two exposures come with the territory. CI runners hold real credentials, and an agent in that job inherits whatever the job has, so the job should carry the narrowest set that lets it work. And an agent triggered by an issue or a pull request comment is reading text written by whoever opened it, which on a public repository is anyone.

  • Failure triage: read a failing job's logs, identify which test broke and why, and post the diagnosis without changing anything.
  • Dependency work: take a version bump, run the suite, fix the compile breaks, and open a pull request for a person to read.
  • Advisory review passes, kept advisory rather than promoted to a required status check, because a required check that is usually noise becomes one more gate people learn to click through.

Frequently Asked Questions

Is this a product, or configuration of our own repositories?

It is configuration work on your repositories and your existing tooling. The deliverables are files: project instruction files, skill definitions, permission and hook configuration, MCP server configuration, and any CI job definitions that run an agent. Those artifacts are checked in and reviewed like source, so they live in the repository alongside the code they describe.

What has to already exist before this is worth doing?

Version control, a test suite whose result means something, and a code review process that agent output will go through. What makes a suite useful to an agent is less raw coverage than specific, fast failures: a run that takes forty minutes and reports only pass or fail gives the agent nothing to iterate against, while a quick test that names the broken behavior lets it correct itself before anyone sees the diff. If there is no review process at all today, that is the first piece of work, and it is not agent work.

Where does our code actually go when an agent runs?

The agent runs on your machine or in your CI, and the files it reads, the diffs it writes, and the output of the commands it runs are sent to a provider API as prompt content. That is the boundary a security review should focus on: the egress is to the model provider, and what crosses it is whatever the agent read. Provider terms differ on retention and on whether inputs are used for training, and enterprise terms generally differ from consumer ones, so that is a contract question to settle rather than something to infer from the tool. It also means the practical control is scope, since a file the agent cannot read is a file that does not cross that boundary.

How does the setup actually proceed?

Roughly in this order. Read the repository and write the project instructions with someone who knows the code. Then take one bounded, real task and run it end to end to see where the agent gets lost, because that is what exposes the gaps: missing documentation, ignore configuration, a test that cannot run locally. Then set permission rules and add hooks. MCP connections and CI come last, because both widen what the agent can reach, and widening is only useful once the narrow case works.

What do we have to provide or decide?

Repository access at a defined scope, and someone who can answer architecture questions. The decisions matter more than the access: which repositories are in scope, what the agent may run without asking, whether it may install packages, whether it runs in CI at all, and which internal systems it may reach over MCP. Most of these are positions your security team already holds for other automated callers, applied to a new one. They are worth settling before setup rather than during it, because each one changes the configuration.

If a change can be done by a codemod, should the agent do it by hand instead?

No. A transform that can be stated as a deterministic rule, such as an import path rewrite or a mechanical signature change, should be run as one, because the tool applies the same rule at every site and the diff is reviewable as a rule rather than as a thousand independent edits. The agent's work on that kind of task is writing the codemod, running it, and inspecting the sites where it did not apply cleanly. That is still the mechanical work being delegated, and it leaves an artifact you can rerun on the next branch that needs it.

How do we tell it is going wrong?

Two signals show up early, and both are visible in tooling you already have. The first is scope creep in the diffs: a test edited to match the code instead of the code edited to match the test, or a generated file changed instead of the source it comes from. The second is review latency collapsing, pull requests of several hundred lines approved in under a minute, which means the gate has become nominal.