# Chapter 8 · How the workflow runs

Machine edition of https://agentc.consulting/agent-enhanced-development/chapter-8/how-the-workflow-runs
Part of Agent-Enhanced Development: https://agentc.consulting/agent-enhanced-development.md
Source: chapter 07 of the conventions repository, https://github.com/AgentC-Consulting/aed-conventions/blob/main/07_how_the_workflow_runs.md

## The moment

The model is running on your own hardware, in your own house, and you are
sitting in front of it feeding it one small ask at a time. Add a class. Now make
it take the invoice. Now do the thirty-day thing. Now email them. Write, save,
retry: the rhythm you learned from a compiler, and the rhythm that made you
good at this job before any of this existed.

It is also, in the conventions' own words, "the least productive way to work
with an agent enhanced development process."

This chapter replaces that rhythm with a picture. One blueprint of a single run:
what you hand over, when you hand it over, what the agent does while you are not
in the room, and what is waiting for you when you come back. Nothing here asks
you to prompt faster. It asks you to hand over more at once, and then to leave.

## The blueprint: one run, end to end

One run, in six stages, from the evening you plan it to the morning you read it.
Stages 1, 2, 3 and 6 are yours; stages 4 and 5 belong to the agent; the one
hand-over sits between stage 3 and stage 4.

1. **You plan, in detail, in your own language.** Not a prompt, a plan. What
   the feature is for, what the company's policy actually is, which cases are
   exceptions, what "done" means. The process rewards this: "with an AI agent
   enhancing our development process, we are rewarded for planning in detail,
   and using our natural language."
2. **You batch the feature requests.** The unit of handoff is a batch, not a
   step: "writing and building feature requests in large batches and letting the
   AI run over many features." A batch is written to be run without you in the
   room, so every sentence in it has to survive being read literally.
3. **You hand the batch over once.** One crossing instead of a hundred. The
   whole plan lands inside one context, where the model can see the second
   feature while it writes the first.
4. **The agent drives.** "The agent should be driving the majority of the
   development, and you should be able to walk away and do something else." This
   is the stage that feels wrong the first few times, because nothing is asking
   you for a decision. That is the point.
5. **The run takes the time it needs, and the tests are inside the
   deliverable.** "It'll spend the time it needs until it succeeds at building a
   thorough feature, including your tests." You do not time-box it, and you do
   not ask for the specs afterward; they were part of what you asked for.
6. **You come back to something reviewable.** Finished features and their
   specs, named the way chapters 2 through 7 ask, so the first pass over them is
   a reading pass and not an excavation.

The shape of the day follows from that: "It's a great way to end a day of
planning, and then let your laptop sit for a time while the agent runs." And
that is why this is the local-model chapter. The machine you already paid for is
idle every night you are asleep. "You can plan your time so that your agent is
building your app while you're typically away from your computer, this way
you're maximizing your local hardware availability while getting the benefits."

## The chapter command

A batch is only as good as what the model has read before it starts. Nobody is
awake in the middle of the night to explain what a process manager is, so the
conventions have to be in the context before the batch is. The whole set of
conventions is published as one file, in reading order, pinned to a tag:

```bash
curl -sL https://raw.githubusercontent.com/AgentC-Consulting/aed-conventions/v1.1.0-rc.1/dist/aed-v1.1.0-rc.1.md
```

Copy that line, run it where your local model can read the output, and hand the
batch over after it. The repository's own instruction to agents is to "read the
spine in order — 01 first, because it explains why the rest exists," and this
file is already in that order. It exists for exactly this case: "if you can only
afford one file, fetch `dist/aed-v1.1.0-rc.1.md` — it is every convention in
reading order."

Pinned to the tag, not to `main`: "Pin to the tag, not to `main`." An unattended
run should be working from a fixed set of conventions. If the rules can move
while you are asleep, you cannot review the result in the morning against
anything.

## The rules this chapter settles

- Small steps and rapid iteration are the habit you brought with you, and here
  they are the wrong one: "this is actually the least productive way to work
  with an agent enhanced development process."
- The temptation has a name: using the agent "for the quick iterative feedback
  like we currently get from a 'write, save, retry' development process."
- What the process pays you for instead is planning: "we are rewarded for
  planning in detail, and using our natural language."
- The unit of handoff is a batch, not a step: "writing and building feature
  requests in large batches and letting the AI run over many features."
- The agent holds the keyboard: "the agent should be driving the majority of the
  development, and you should be able to walk away and do something else."
- A planning day ends with a handoff: "it's a great way to end a day of
  planning, and then let your laptop sit for a time while the agent runs."
- The run is not time-boxed by you, and tests ship with the feature: "it'll
  spend the time it needs until it succeeds at building a thorough feature,
  including your tests."
- The point of running locally is the hours you are not there: you are
  "maximizing your local hardware availability while getting the benefits."
- Plain statement of intent is still the standard when nobody is watching:
  "prefer the form that reads like a plain statement of intent. Reach for
  shorthand only when it makes the intent *clearer*, never just shorter."
- Read the spine in order, and pin to the tag rather than to `main`.

## Why it matters to the agent

A model reads through a token window, which chapter 1 covers in detail. A batch
handed over at once puts the whole plan inside that window: the nightly sweep is
visible while the fee is being written, so the two are built to fit. A hundred
small prompts give the model a hundred partial views and no plan at all. Each
one arrives after the last one has scrolled out of reach, and the only place the
plan ever existed was in your head.

Unattended makes it sharper. There is nobody awake to re-explain a name, so
every name has to carry its own meaning on the first pass. That is why chapters
2 through 7 come before this one: the naming, the process managers, the feature
stories, and the control flow are what make a run survive the absence of its
author. The conventions' test for every line the agent writes is the same test you
would apply at the review in the morning: "does a reader who has never seen
this code understand the intent on first pass? If they would have to mentally
execute it, expand it."

The repository publishes one measurement of that effect, and states its limits
itself.
In a 2026-07-07 run, Claude Haiku answered comprehension probes on ten pairs of
Crystal snippets, blind, with a blind grader: the AED variants scored 60 of 60
and the conventional compressed variants 54 of 60, with the gap concentrated in
defect-finding and intent rather than mechanical edits. The report calls that a
directional signal consistent with the hypothesis, not proof of it: one run,
snippet scale, one small model. Take it as what it is, and note which way it
points for a model working alone all night.

## Before and after

The write-save-retry day, one small ask at a time. Four separate asks leave a
class that half exists, with the plan still living in your head and nothing
written where documentation is read. The TODO comments are the tell: they are
the plan, and they never got written down anywhere the agent could run.

The first file below is what four asks left behind. The second is what one batch
returned.

```crystal
# "add a class that charges a late fee"
# "now make it take the invoice"
# "now add the 30 day thing"
# "now email them"
class Billing::ApplyLateFee
  property invoice : Invoice

  def perform
    charge_the_late_fee
    # TODO: grace period
    # TODO: notify
    # TODO: what about a canceled subscription?
    # TODO: spec
  end

  private def charge_the_late_fee
    invoice.charge(invoice.amount * 0.05, kind: :late_fee)
  end
end
```

Now the same work as one batch, handed over at the end of a planning day, in the
owner's own sentences:

> When an invoice is more than its grace period past due and the customer still
> has an active subscription, charge a late fee of five percent and tell the
> customer. Sweep every overdue invoice nightly. Cover both with specs.

You walk away. The local model runs over the whole batch and returns the process
manager, the sweep that drives it, and their specs, every name already in AED
form.

```crystal
# Applies a late fee to an invoice that has gone past its grace period, then tells the customer.
class Billing::ApplyLateFee
  # -- What this needs --

  # The invoice being charged. It knows its customer, its amount, and its due date.
  property invoice : Invoice

  # How many days past the due date the invoice is today.
  property how_many_days_late : Int32 = 0

  # -- Company policy --

  # Days past due before any fee applies.
  property grace_period_in_days : Int32 = 30

  # The fee, as a share of the amount owed.
  property late_fee_rate : Float64 = 0.05

  # -- How it runs --

  def perform
    stop_unless_the_invoice_is_overdue
    stop_unless_the_customer_has_an_active_subscription
    charge_the_late_fee
    tell_the_customer
  end

  # Nothing happens inside the grace period.
  private def stop_unless_the_invoice_is_overdue
    return if how_many_days_late < grace_period_in_days
  end

  # A customer who has already left is not charged for staying.
  private def stop_unless_the_customer_has_an_active_subscription
    return if invoice.customer.currently_active_subscription.nil?
  end

  # The fee is a share of the amount owed, charged to the same invoice.
  private def charge_the_late_fee
    invoice.charge(invoice.amount * late_fee_rate, kind: :late_fee)
  end

  # The customer gets the notice by email.
  private def tell_the_customer
    CustomerMail.late_fee(invoice).deliver
  end
end

# Charges the late fee on every invoice that has gone past its grace period tonight.
class Billing::ApplyLateFeeToEveryOverdueInvoice
  # -- What this needs --

  # Every invoice that is past due as of this run.
  property list_of_all_overdue_invoices : Array(Invoice)

  # -- How it runs --

  def perform
    apply_the_late_fee_to_each_overdue_invoice
  end

  # One invoice at a time, each through the same process manager.
  private def apply_the_late_fee_to_each_overdue_invoice
    list_of_all_overdue_invoices.each do |invoice|
      Billing::ApplyLateFee.new(
        invoice: invoice,
        how_many_days_late: invoice.how_many_days_past_due
      ).perform
    end
  end
end
```

## What else came back in the same batch

The spec came with it, because the batch asked for it and the run does not stop
until it passes. One case for each sentence the owner wrote: inside the grace
period, past it with an active subscription, and the canceled subscription the
four-ask version left as a TODO.

```crystal
describe Billing::ApplyLateFee do
  it "charges nothing inside the grace period" do
    invoice = build_an_invoice(amount: 100.0)

    Billing::ApplyLateFee.new(invoice: invoice, how_many_days_late: 12).perform

    invoice.list_of_all_charges.should be_empty
  end

  it "charges five percent once the grace period has passed" do
    invoice = build_an_invoice(amount: 100.0, with_an_active_subscription: true)

    Billing::ApplyLateFee.new(invoice: invoice, how_many_days_late: 31).perform

    invoice.list_of_all_charges.first.amount.should eq(5.0)
    CustomerMail.list_of_all_deliveries.size.should eq(1)
  end

  it "charges nothing when the subscription has been canceled" do
    invoice = build_an_invoice(amount: 100.0, with_an_active_subscription: false)

    Billing::ApplyLateFee.new(invoice: invoice, how_many_days_late: 31).perform

    invoice.list_of_all_charges.should be_empty
  end
end
```

The difference between the two is not how well the model writes. It is how the
work was asked for. The first was asked for four times and never planned; the
second was planned once and asked for once, and the machine did the rest of it
while the lights were off.

## Next

Next: Chapter 9 · Adopt it in ten minutes (the same handoff, made permanent:
the conventions installed where your agent reads them every time, not just
tonight).
