How We Do Agentic Development

How We Do Agentic Development

The mechanics, not the marketing. How AI agents ship production code inside a real engineering discipline.

This page is for engineers: how JFDI does agentic development, not why we believe in it. For the philosophy, read the Agentic Development Manifesto.

Agentic development at JFDI (agentic software development under real engineering discipline) is a practice refined over eighteen months of agentic delivery across hundreds of projects and on the order of ten thousand commits. In that window, effectively all of our new code has been AI-generated: not hand-written and occasionally assisted, but produced by agents working under engineering control. Those agents operate as participants in our codebases, subject to the same boundaries, tests, and review as every human contributor.

Context Engineering, Not Prompt Engineering

Almost all of an agent’s quality comes from the context it is given: the tools it can call, the schemas it must satisfy, the libraries it builds on, the type contracts it has to honour, the build graph it can see, and the project conventions encoded around it. We engineer those inputs so the agent works from accurate ground truth rather than a plausible guess. Everything below is one of them.

Why Volume and Discipline Belong Together

A modern hard drive packs bits so densely that read errors aren’t an edge case; they’re constant and unavoidable. It’s viable anyway because error correction runs fast and in layers, turning a noisy raw signal into reliable storage. The density isn’t a problem to eliminate; it’s the point, and correction is what makes it safe. Agentic development works the same way: code is generated in large volume, faster than a human could review line by line, so mistakes are constant too. What makes it production-grade is not pretending the agent is infallible, but surrounding its output with fast, layered correction (type contracts, the reuse index, blocking test and boundary gates, schema validation, independent review) that corrals a high-volume stream of generated code into a pre-engineered shape before a human ever sees it. The speed is what makes it worthwhile; the guardrails are what make the speed safe.

Instrumented Practice

We instrument our own delivery: every AI-assisted change is attributed, with the exact model version stamped into the commit trailer, so contribution is a matter of record, not estimate.

~100% AI-Generated

Across eighteen months, effectively all of our new code has been agent-generated, not hand-written.

~10,000 Commits

of agentic delivery over those eighteen months: production work, not a pilot.

Hundreds of Projects

across our estate built and maintained with agents as the primary authors.

Tests Gate Every Change

Affected-only test runs block an agent from finishing until they pass.

The Library Base Is a Guardrail

JFDI’s agents work inside a mature library base: a large body of internal packages, strongly typed, with established APIs and conventions, each backed by its own test suite and already running in production across our services. That substrate constrains the agent mechanically, in ways a prompt cannot:

  • Types and APIs bound the solution space. Strict typing and well-defined library signatures mean an agent’s output has to satisfy real contracts to compile at all, so it converges on the established way of doing something rather than inventing a divergent one.
  • Composition over generation. The reuse hook surfaces existing functions before the agent writes new code, so the high-value output is a typed call into a tested package, not a fresh reimplementation of logic that already exists and is already covered.
  • Less novel code to review. Building from hardened components shrinks the volume of new, unproven code per change, and new, unproven code is exactly where AI-generated defects and technical debt concentrate. The practical payoff is lower long-term maintenance cost and fewer defects to chase later.

Why one build graph matters

A single dependency-aware build graph gives an agent visibility it cannot get from an isolated file: which projects depend on the code it is about to change, the existing implementations and type contracts it should reuse, the test suites that cover them, and the architectural boundaries it must not cross. Dependency rules are machine-enforced across the graph, so an agent that reaches across a forbidden boundary fails the build rather than quietly coupling two systems. The graph also scopes every change to the affected projects only: the basis for the fast per-change test gate below.

Platform-Native Tooling

We give agents direct, validated access to platform APIs through purpose-built Model Context Protocol (MCP) servers, rather than letting a model reconstruct those APIs from training data and guess. Each server exposes typed tools, each with its own input schema. Instead of describing a platform in a prompt, the agent calls tools that talk to the real system, return real schemas, and reject invalid input before any code is generated.

  • Typed tool surface. Agents invoke platform operations as validated tools (create, generate, inspect, promote) rather than emitting free-text guesses about API shape.
  • Dual MCP + CLI surface. The same tooling runs interactively for an agent and headlessly from CI, enabling unattended, identity-scoped migrations and promotions.
  • Inspect before mutate. Agents read current state and dry-run a change set against the live platform’s validation rules; a destructive apply requires an explicit opt-in flag, so nothing mutates by accident.

Knowledge That Compounds

Two persistent layers carry hard-won knowledge across context resets and across the team.

Indexed code memory

A code-entity index (functions, components, hooks, types, interfaces, classes, and exported constants) is built straight from the source tree, drawing keywords from documentation comments and from splitting camelCase and PascalCase identifiers. It persists between sessions and reindexes only changed files. Before an agent writes new code, a hook intercepts it and requires a search of the index first, so existing, proven implementations surface for reuse instead of being silently reinvented: reuse as an enforced workflow step, not a matter of the agent remembering to look.

Structured planning artefacts

Work is captured as durable, phase-structured planning documents (discuss, plan, execute, verify) committed alongside the code. When an engineer or agent picks up a task mid-stream, the full history of decisions, dead ends, and rationale travels with it. An anti-pattern discovered in one phase prevents the same mistake three phases later, without anyone needing to remember it. For a client, that means the project’s context lives in the repository rather than in one person’s head: less key-person risk, and a cleaner hand-over.

Observable and Auditable

Every change lands through version control carrying its model attribution, the committed plan, and the verification record that drove it, so for any change we can reconstruct what was intended, what the agent changed, which model produced it, and which checks it passed. Where an agent applies changes to a live platform, the apply step writes a redacted, secret-stripped record of the change set and its outcome, so privileged actions are recoverable for review. Intent, change, attribution, validation, and review decision all live next to the code, not in a vendor session that vanishes when the tab closes.

Pipeline Evaluation

Gates decide whether a change is safe to ship; evaluation tells us whether the workflow itself is improving. We measure the agentic pipeline, tracking signals such as build-success rate, how often agent-produced changes are accepted versus sent back at review, defect and regression escape rates, and time from intent to merged change. A dedicated end-to-end scenario suite drives an agent through a complete, working slice (data model, API, reusable component, admin page) against a live environment with explicit pass criteria, and run-to-run comparison flags drift when a model, prompt, or tool change moves the result. Headline delivery impact is summarised on our Agentic AI Development page; those outcomes are measured against a baseline, not asserted.

Automated Quality Gates

Generated work passes through automated gates before a human ever reviews it.

Blocking Test Gate

A hook fires when an agent tries to end its turn, runs the tests affected by the change, and blocks completion if any fail. Broken work cannot reach review.

Enforced Boundaries

Architectural module boundaries are machine-checked. Dependency rules and dead-code detection fail the build on violation, keeping the graph clean as it grows.

Typecheck · Lint · Build

Strict type checking, linting, and full builds run in CI on the affected projects: the same chain for agent-authored and human-authored changes.

Second-Model Review

Opt-in per pull request via a label, a second model from a different vendor performs an independent code review: a deliberately different perspective before human sign-off.

Schema-Driven Generation

A schema is the single source of truth for generation. We define JSON schemas that simultaneously drive tool input validation, output validation, and the guidance given to the model: one contract used to shape generation, strip invalid properties, and verify the result. Artefacts are validated against real platform constraints as they are produced, not after the fact, so output that does not conform to the schema is rejected at the boundary, long before it reaches a human reviewer.

Identity, Least Privilege, and Approval

When an agent acts against a platform it does so under an authenticated, verified identity: sessions are keyed per host and user, and the tooling refuses to act if no valid identity is captured or if it is ambiguous. Access is governed by explicit permission levels rather than all-or-nothing trust, so an agent can be scoped to read where it has no business writing. Privileged and destructive actions sit behind hard gates:

  • Least privilege. Permissions are granted per resource and per operation; read and write are distinct, and access can be explicitly denied. An agent operates with the narrowest rights its task needs.
  • Approval before mutation. A live, destructive apply is refused unless it follows a dry-run and carries an explicit confirmation token that matches the exact change set proposed, so an agent cannot mutate production on a whim, and platform-owned resources are protected outright.
  • Secret redaction. Tokens, cookies, signed URLs, and other secrets are stripped before anything is written to a record or surfaced to a reviewer, so the audit trail never leaks credentials.
  • Harness-enforced guardrails. Beyond platform permissions, the local agent harness blocks disallowed commands outright — limits enforced on the agent, not merely requested of it.

Where Agents Still Get It Wrong

We are not claiming agents don’t fail. They fail in specific, recurring ways, and the discipline above exists precisely because they do. The honest list, and the control that catches each:

  • Architectural misunderstanding. An agent reaches across a boundary it shouldn’t, or couples two systems that should stay separate. Caught by machine-enforced dependency rules in the build graph: a forbidden edge fails the build, not review.
  • Duplicate implementation. An agent reinvents logic that already exists in a tested package. Caught by the reuse hook, which forces a search of the code-entity index before new code is written.
  • Performance and correctness regressions. A change that compiles but breaks behaviour. Caught by the affected-only test gate that blocks an agent from finishing until the tests covering its change pass.
  • Domain misunderstanding. The hardest class, and the one tooling does not fully solve. An agent can satisfy every type contract and still misread what the business actually needs. This is why the merge decision, and accountability for it, stays with a human engineer who understands the domain. We have learned to spend human judgement here rather than on mechanical checks.

The pattern is deliberate: the failure modes a machine can catch, a machine catches before review; the one it can’t, domain judgement, is exactly where we keep a human in the loop.

Failure Is Expected

The system assumes things go wrong. Live changes carry an automatically generated inverse change set, so an apply can be rolled back rather than hand-unpicked. Concurrency conflicts are retried under a bounded budget instead of failing outright, and known recoverable error states trigger a defined heal path. Migrations run through backup, restore, and transfer steps that are identity- and confirmation-gated, and partial failures are surfaced as explicit buckets (recovered, skipped, mismatched), so a half-applied change is never reported as a success. When validation fails, the rule is simple and enforced: revise the plan, do not apply. A failed gate routes work back to a human rather than forward to production.

Multi-Model and Tool-Agnostic

The parts that carry our engineering (MCP tool definitions, JSON schemas, quality-gate hooks, and agent configuration) are expressed independently of any provider’s API, so a model can be substituted without rewriting the workflow around it. One model leads day-to-day delivery; the second-model review gate deliberately calls a different vendor’s model so the reviewer does not share the author’s blind spots. Tool schemas are portable across model APIs, which is what makes that substitution cheap rather than a rebuild.

Specialised Roles

Work moves through distinct, specialised roles rather than one general-purpose assistant: a planning role that turns a goal into a discussed, structured plan; an execution role that implements it against the live tooling and gates; a verification role that checks the result against the plan’s stated criteria; and an independent review role, deliberately a different model, that critiques the change before a human signs off. Each role has a narrow remit and its own context, which keeps the agent focused and makes the hand-offs between them auditable.

Reproducible by Construction

The way we run agents is itself version-controlled. Agent instructions, skills, tool definitions, MCP server configuration, quality-gate hooks, and boundary rules all live in the repository alongside the code they govern, so the same committed context produces the same behaviour for any engineer or agent that checks the repository out. Changing how an agent works goes through review like any other change.

Human-Led at Defined Checkpoints

Agents handle scaffolding, platform-specific incantations, repetitive transformation, and first drafts; generated work reaches a human only after it has passed the test gate, the boundary and dead-code checks, schema validation, and any second-model review. The human reviewer sees pre-validated work and holds the authority to reject it; the merge decision, and accountability for it, is theirs. Front-loading the mechanical checks means human judgement is spent on architecture and trade-offs, not on catching broken builds.

This is the engineering behind the Agentic Development Manifesto and the capability described on our Agentic AI Development service page.

JFDI’s Agentic Development Methodology

JFDI uses autonomous and semi-autonomous AI agents across hundreds of TypeScript projects spanning our estate. Agents operate through MCP tools, indexed code memory, structured planning artefacts, JSON-schema-defined interfaces and automated quality gates. Agent actions are attributable, observable and auditable. Identity-scoped permissions, approval workflows and human review govern production changes. Agent instructions, tools and workflows are version-controlled alongside application code.

See It On Your Own Work

The most honest way to evaluate a process is to watch it run against a real problem. A small, bounded pilot on a single scoped item from your backlog tells you far more than any page can. You’d see the workflow described above on your own code, and the artefacts that go with it: the structured plan, the generated change, the test and gate results, the second-model review, and a walkthrough of how it was built. We’re happy to talk through what a pilot like that would involve.

Talk through how a pilot would work

Tell us about a scoped task and we’ll walk you through how we’d run it (the tooling, the gates, and the review artefacts you’d get back) so you can judge the process on your own terms.