Make the Agent Initialize Before Every Work Session

Read20 min · Plan → Implement → Verify → Evolve · Updated 2026-09-15

You end this lesson with: An initialization routine the agent runs before touching any code.

Chapters

  1. Two Fundamentally Different Kinds of Work
    01
  2. The Rule and Its Condition
    02
  3. Initialization Lifecycle
    03
  4. What Happens When You Mix Them
    04
  5. Core Concepts
    05
  6. How to Do Initialization Right
    06
view

Practice project: Project 03. Multi-session continuity

Lecture 06. Make the Agent Initialize Before Every Work Session

You start a new agent session and tell it "add a search feature." It jumps straight into coding, admirable enthusiasm. After 20 minutes it discovers the test framework isn't configured properly, spends another 10 minutes fixing that, then finds the database migration script format is wrong, more fiddling. The search feature does get added in the end, but the whole session was inefficient. Most of the time went to "figuring out how this project works" rather than writing the search feature itself.

The better approach: before letting the agent start working, use a separate phase to get the base environment ready, run verification commands through, and understand the project structure. Initialization work should not be crammed together with feature implementation, they are two fundamentally different kinds of tasks.

This lecture discusses why initialization must be a separate phase, not mixed in with implementation.

Two Fundamentally Different Kinds of Work

Initialization and implementation have completely different optimization targets. The implementation phase aims to maximize the quantity and quality of verified features. The initialization phase aims to maximize the reliability and efficiency of all subsequent implementation.

When you mix initialization and implementation, the agent faces a multi-objective optimization problem: it has to simultaneously build infrastructure and write feature code. Without explicit priority setting, the agent naturally gravitates toward writing code (because that's directly visible output) while sacrificing infrastructure (because its value only shows up in subsequent sessions). The result: infrastructure doesn't get built solidly, and the reliability of the feature code suffers as well.

The Rule and Its Condition

Run a dedicated initialization session before starting any feature when a fresh clone of the repo fails one or more of the four startup-readiness conditions from the checklist above: can start, can test, can see progress, can pick up next steps. Otherwise, skip initialization and start the task directly, an already-initialized repo doesn't need a second init pass just because a new session opened it.

The condition is checkable in under a minute, not a judgment call: run the setup command, run the test command, and look for a startup-readiness checklist and a task-breakdown file in the repo. Any one of the four missing or failing is your Y.

Signal in the repoDedicated init phase needed?
make setup && make test fails, or runs with zero tests executedYes, nothing here is verified yet
No startup-readiness checklist or task-breakdown file existsYes, the first session's job is to write them
All four conditions hold, and a clean init commit already exists in historyNo, begin implementation directly
A small addition to an already-initialized project (checklist current, example test passing)No, treat it as ordinary implementation, don't re-run init from scratch

Initialization Lifecycle

diagram
drawing

What Happens When You Mix Them

The most direct problem: infrastructure doesn't get built solidly. The agent spends most of its effort on feature code and only a sliver of attention casually setting up infrastructure. The test framework is configured but never verified, lint rules are set but too loose, no progress file created. These defects aren't obvious in the first session (because the agent still remembers what it did), but they surface in the second session: the new agent doesn't know how to run the project, how to test, or where things stand.

A more hidden cost is "unverified accumulation." Feature code written before the test framework is properly configured, when you finally go back to add tests, you might discover the design itself was flawed. Had you known earlier, you would have implemented it differently. The more code written up front, the more has to be torn down and redone later.

Context budget is being wasted too. Initialization work (configuring environments, setting up tests, understanding project structure) consumes a large chunk of the budget, leaving less for actual feature implementation. The result: the first session only completes half the features, and the second session still has to start from scratch understanding the project. Budget was spent on initialization, but initialization wasn't done well either, the worst of both worlds.

The most easily overlooked problem is implicit assumption landmines. Decisions the agent makes during initialization (which test framework, how to organize directories, dependency management), if not explicitly recorded, subsequent sessions may make contradictory choices. The first session chose Vitest as the test framework, but the second session's agent doesn't know and introduces Jest. Two test frameworks coexist, and maintenance costs double.

Anthropic's guidance on long-running agents recommends separating initialization from implementation as an explicit phase. The economics are simple even without a benchmark: initialization cost is paid once, while every later session pays the price of a missing or broken foundation, so the up-front time is typically recovered within the first few sessions.

OpenAI's harness engineering article also emphasizes the repository-as-system-of-record principle: establish clear operational structure from the very first run, or every new session has to re-infer project conventions.

Core Concepts

  • Initialization Phase: The first phase in the agent's lifecycle, it only establishes the prerequisites for subsequent implementation, with no feature development. Its output is infrastructure, not business code.
  • Startup Readiness Checklist: The conditions under which a project can be unambiguously operated by a fresh agent session: can start, can test, can see progress, can pick up next steps. Four conditions, all required.
  • From Scratch vs From Template: Starting from scratch means the agent must infer project structure on its own from an empty directory; starting from a template means infrastructure is already in place. Starting from a template far outperforms starting from scratch.
  • Always Ready to Hand Off: The project is in a state at any given moment where a fresh agent can take over. No verbal explanation needed, just looking at the repo contents is enough to continue working.
  • Time from Start to First Passing Test: The time from project start until the first feature point passes verification. This is the core metric for measuring initialization efficiency.
  • Success Rate of Subsequent Sessions: The proportion of subsequent sessions that can successfully execute tasks without relying on implicit knowledge. This is the best measure of initialization quality.

How to Do Initialization Right

Treat initialization as a dedicated phase. The first session does only initialization, no business feature code at all. Initialization produces:

1. Runnable environment. The project starts, dependencies are installed, no environment issues.

2. Verifiable test framework. At least one example test passes, proving the test framework itself is properly configured.

3. Startup readiness checklist document. A clear document telling subsequent sessions:

markdown
# Startup Readiness Checklist

## Start Commands

- Install dependencies: `make setup`
- Start dev server: `make dev`
- Run tests: `make test`
- Full verification: `make check`

## Current State

- All dependencies installed and locked
- Test framework configured (Vitest + React Testing Library)
- Example test passing (1/1)
- Lint rules configured (ESLint + Prettier)

## Project Structure

- src/ — Source code
- src/components/ — React components
- src/api/ — API client
- tests/ — Test files

4. Task breakdown. Split the entire project into an ordered task list, each task with clear acceptance criteria:

markdown
# Task Breakdown

## Task 1: User Authentication Basics

- Implement JWT auth middleware
- Add login/register endpoints
- Acceptance: pytest tests/test_auth.py all passing

## Task 2: User Profile Page

- Implement user profile CRUD
- Add profile edit form
- Acceptance: pytest tests/test_profile.py all passing

## Task 3: Search Feature

- ...

4b. The product-scale feature list. The breakdown above covers the first sessions; the list covers the whole product. Expand the user's request into a complete feature list — every end-to-end capability the product needs (tens of items for a small product, not three), each written as something a user can do and verify, each carrying its own verification steps:

json
{ "category": "auth",
  "description": "Users can sign up with email and password",
  "verification": ["open /signup", "fill the form, submit", "receive the confirmation email", "log in with the new account"],
  "passes": false }

Order it so foundational features come first, mark every item failing, and treat it as the fullest map of "what done looks like" the project will ever get — written while the request is freshest. One harness, two openings: the same agent with the same rules and tools starts every session; only the first window's opening instruction differs (build the environment and this list; every later window reads them and picks the highest-priority failing item).

5. Git commit as checkpoint. After initialization completes, commit a clean checkpoint. All subsequent work starts from this checkpoint.

Starting from a template: Don't start from an empty directory. Use a project template (create-react-app, fastapi-template, etc.) to preset standard directory structure, dependency configuration, and test framework. Bake common initialization steps into the template, leaving only project-specific initialization work.

Initialization completion criteria: Not "how much code was written," but whether the startup readiness checklist's four conditions are all met: can start, can test, can see progress, can pick up next steps. Use this checklist to validate initialization:

markdown
## Initialization Acceptance Checklist

- [ ] `make setup` succeeds from scratch
- [ ] `make test` has at least one passing test
- [ ] A new agent session can answer "how to run" and "how to test" from repo contents alone
- [ ] Task breakdown file exists with at least 3 tasks
- [ ] Everything committed to git

Trace It: Mixed vs. Dedicated Init

Session 1 of a React frontend project: the agent creates scaffolding AND implements the first feature at the same time, in one pass.

Predict before reading on: the repo has runnable code by session end. What's missing, and what does session 2 look like?

Trace it against the four startup-readiness conditions above: scaffolding-plus-feature-in-one-pass optimizes for "ship something now," not "make the next session cheap", so the things that only initialization produces (documented start/test commands, a progress file, a task breakdown) never get made. Session 2 opens and has to infer project structure, test framework, and build process from the code itself, the same rebuild tax as any missing-persistence lecture, just paid on infrastructure instead of decisions.

Now run session 1 as dedicated initialization only: template scaffolding, test framework configured and proven with one passing example, startup-readiness checklist and task breakdown committed. Session 2 starts directly from the task list, no inference, no rebuild.

Faded case

Skip to the open case if this is familiar. A different team starts session 1 of a CLI tool for internal ops scripts. They know the rebuild-tax lesson from the trace above, so they resist writing feature code first and open a dedicated initialization session: npm init, install commander and vitest, wire a Makefile with setup/test/check targets, and write one passing smoke test. Forty minutes in, with the checklist still open, the agent commits and calls initialization done. No task breakdown file exists yet, and the "current state" section of the startup-readiness doc still reads "TODO."

Session 2 opens cold. Decide: does this repo pass the four startup-readiness conditions, and if not, which one is missing, and what does session 2 have to spend time on that dedicated initialization was supposed to save it from?

Open case

Open your own project and run the four startup-readiness conditions against it cold, no memory of how it got built. Can a fresh agent session install dependencies and start the dev server using only what's committed? Is there one test that actually passes, not just a configured runner? Can it tell, from repo contents alone, what's already done? Can it find the next task without you in the room? Any "no" is the same rebuild tax the trace and the faded case above already showed you, just waiting to happen on your own repo instead of a hypothetical one. Exercise 1 below turns this same check into a full checklist you can keep, if you want more structure than a gut-check.

Key Takeaways

  • Initialization and implementation have different optimization targets, mixing them only drags both down.
  • Initialization's output isn't business code, it's infrastructure: runnable environment, verifiable tests, startup readiness checklist, task breakdown.
  • Validate initialization with the startup readiness checklist's four conditions: can start, can test, can see progress, can pick up next steps.
  • Starting from a template beats starting from scratch. Use project templates to preset standardized infrastructure.
  • Time invested in initialization is fully recovered in the next 3-4 sessions. This isn't extra cost, it's upfront investment.

Example Files

Copy-ready course examples referenced in this lecture.

init-check.ts

A runnable prerequisite checker, verifies Node version, package.json, installed dependencies, TypeScript toolchain, tsconfig, and directory structure, reporting per-check what silently breaks later if it's missing.

ts
/**
 * init-check.ts
 *
 * Programmatically checks initialization prerequisites:
 *   - Node.js version
 *   - Dependencies installed (node_modules exists)
 *   - Data directory exists
 *   - Config files present
 *
 * Simulates running with and without an explicit init phase,
 * showing how missing prerequisites cause silent failures later.
 *
 * Run: npx tsx docs/lectures/lecture-06-why-initialization-needs-its-own-phase/code/init-check.ts
 */

import * as fs from "node:fs";
import * as path from "node:path";
import * as childProcess from "node:child_process";

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

interface CheckItem {
  name: string;
  category: string;
  check: () => { pass: boolean; detail: string };
  impactIfMissing: string;
}

interface CheckResult {
  name: string;
  category: string;
  passed: boolean;
  detail: string;
  impactIfMissing: string;
}

// ---------------------------------------------------------------------------
// Checks
// ---------------------------------------------------------------------------

function createChecks(targetDir: string): CheckItem[] {
  return [
    {
      name: "Node.js version >= 18",
      category: "Runtime",
      check: () => {
        try {
          const version = process.version; // e.g. "v20.11.0"
          const major = parseInt(version.replace("v", "").split(".")[0], 10);
          return {
            pass: major >= 18,
            detail: `Detected: ${version} (need >= v18)`,
          };
        } catch {
          return { pass: false, detail: "Could not detect Node.js version" };
        }
      },
      impactIfMissing: "TypeScript features and built-in APIs unavailable",
    },
    {
      name: "package.json exists",
      category: "Config",
      check: () => {
        const p = path.join(targetDir, "package.json");
        const exists = fs.existsSync(p);
        return {
          pass: exists,
          detail: exists ? `Found: ${p}` : "Not found in target directory",
        };
      },
      impactIfMissing: "Cannot install dependencies or run scripts",
    },
    {
      name: "Dependencies installed (node_modules)",
      category: "Dependencies",
      check: () => {
        const p = path.join(targetDir, "node_modules");
        const exists = fs.existsSync(p);
        return {
          pass: exists,
          detail: exists ? `Found: ${p}` : "node_modules/ not found -- run npm install",
        };
      },
      impactIfMissing: "All imports fail at runtime",
    },
    {
      name: "TypeScript available",
      category: "Toolchain",
      check: () => {
        try {
          const result = childProcess.execSync("npx tsc --version", {
            encoding: "utf-8",
            timeout: 10000,
            stdio: ["pipe", "pipe", "pipe"],
          }).trim();
          return { pass: true, detail: `Detected: ${result}` };
        } catch {
          return { pass: false, detail: "TypeScript not available via npx" };
        }
      },
      impactIfMissing: "Cannot compile TypeScript files",
    },
    {
      name: "tsconfig.json exists",
      category: "Config",
      check: () => {
        const p = path.join(targetDir, "tsconfig.json");
        const exists = fs.existsSync(p);
        return {
          pass: exists,
          detail: exists ? `Found: ${p}` : "Not found",
        };
      },
      impactIfMissing: "TypeScript compiler uses defaults, may not match project needs",
    },
    {
      name: "Source directory exists",
      category: "Structure",
// … trimmed for the lecture — the pattern continues in the same shape

init.sh

The skeleton of a clock-in script, fail-fast flags, dependency install, and a marked slot for project-specific startup steps (starting the dev server and running the smoke check belong in that slot); every session runs this before touching code.

bash
#!/usr/bin/env bash
set -euo pipefail

echo "[init] installing dependencies"
npm install

echo "[init] starting the docs site is optional"
echo "[init] use npm run docs:dev for course docs"

echo "[init] project-specific startup would go here"

initializer-output-checklist.md

Six questions that audit what the init phase actually produced — startup command, verification command, first progress artifact, stable first commit, complete feature list, and a visible feature surface for later runs.

markdown
# Initializer Output Checklist

- Is there a canonical startup command?
- Is there a canonical verification command?
- Is there a first progress artifact?
- Is there a stable first commit?
- Is there a complete feature list — every item still failing, each with its verify steps?
- Is there a visible feature surface for later runs?

What You Have Now

An initialization routine the agent runs before touching any code.

Write the routine down as explicit steps, what to read, what to verify, what to refuse to start without, and make it the first thing every session executes. Initialization that lives in your head is initialization the agent doesn't have.

Save it as harness/init.sh; the lab's checker looks for that file at that path.

Further Reading

Exercises

  1. Startup readiness checklist design: Write a complete startup readiness checklist for a project you're developing. Then open a completely fresh agent session, show it only repo contents (no verbal context at all), and have it try to start the project, run tests, and understand current progress. Record every problem it encounters, each one corresponds to a missing clause in your startup readiness checklist.

  2. Comparison experiment: Pick a moderately complex new project. Approach A: let the agent initialize and do first implementation simultaneously. Approach B: spend one session on dedicated initialization, start implementation in session 2. After 4 sessions, compare time from start to first passing test, rebuild cost, and feature completion rate.

  3. Initialization acceptance checklist: Design an initialization acceptance checklist for your project. Have a fresh agent session execute each checklist item and record which pass and which fail. The failing items are where your harness needs strengthening.

Check your understanding


Reading is free — your progress isn't being saved

Nothing you did on this page is recorded. Paid students get saved progress and verified completions, recorded quiz answers, the spaced-repetition review queue, labs, and a certificate for each course they finish.

30-day money-back guarantee. One-time payment — lifetime access and updates.