Thoughtware

An agent is mostly ordinary code

An agent is not a model with tools. It is largely deterministic control flow in which judgment is concentrated in named cognitive units and known work in Skills.

9 min read

Cover for An agent is mostly ordinary code

An engineer opens the Meal Planning repo expecting magic. They find a state object, a loop function, permission checks, budget counters, and a list of named dependencies. cognitive units appear as imported packages with contracts. Skills appear as callable capabilities with procedure tests. The generative model sits inside specific calls, not around the whole product. That surprise is the point.

Helpful context: What is an agent defines goal ownership. Deterministic code beside cognition owns exact gates and side effects. The model is not the system resists substrate-centred design.

What stays deterministic

Popular speech treats an agent as "a model with tools." That description names substrate and reach. It does not name architecture. It encourages teams to hide transitions, gates, and pursuit state inside prompts nobody can review in a design meeting. Thoughtware agents are mostly ordinary software: state machines, policies, budgets, adapters, with cognition invoked through contracts. The loop should be boring. The judgments and procedures should be pointable.

Schemas, validation, permissions, tool execution, hard policy gates, idempotent side effects, and transition bookkeeping belong in code. cognitive units may propose. Code decides what is allowed to happen in the world and which loop transition is taken after a result arrives. Working state updates, budget accounting, and stop checks are ordinary engineering. They should be inspectable without reading a prompt. When those responsibilities hide inside one generative call, the agent becomes an unnamed compound again. See not a composite cognitive units.

ResponsibilityBelongs in code because
Loop transitionsThe path must be readable and logged
Authority gatesPermissions are not model opinions
Working stateDurable pursuit state is not a transcript
Budget and stopTermination must not depend on vibes

Take allergy enforcement in the Meal Companion. Endorsed cashew allergy lives in knowledge. Rejection happens in deterministic validation regardless of which engine drafted candidate meals. That rule should survive a vendor swap without re-reading prompt archaeology. The agent loop calls cognitive units for open judgments. It does not ask the model whether allergies matter this week.

What stays cognitive

Interpretation, comparison, planning proposals, criticism, and other open judgments live in cognitive units with contracts and evaluation suites. Known multi-step capabilities live in Skills. The agent chooses which cognitive unit or Skill to call and what to do with the result. The division is practical. Engineers already know how to test code paths, log transitions, and enforce permissions. Thoughtware adds named judgment boundaries so cognition remains substitutable and evaluable. When every decision hides in one call, you lose both advantages.

Invoice intake follows the same shape at enterprise scale. A goal-owning module pursues queue clearance with review and escalation. Extraction Skills perform retrieve, validate, persist. Field-level cognitive units decide interpretations. None of that requires a vendor "agent framework." It requires readable control flow with named dependencies.

Meal Companion pseudo-structure

The following sketch is intentionally ordinary. No magic rectangle surrounds the product.

MealPlanningAgent
  goal: accepted_weekly_dinner_plan
  working_state: { week, plan_version, accepted_meals, gaps, budget }
  loop:
    plan, act, observe, review, revise
  calls:
    Skills.ComposeWeeklyPlan
    cognitiveUnits.JudgeWeekdayPracticality
    cognitiveUnits.RecommendMealSubstitution
  gates:
    code.validate_schema
    code.enforce_allergies
    code.require_purchase_approval
  stop_when: minimum_sufficient_loop_met | escalate | ask

Each line has an owner in code review. CritiquePlan returns weaknesses as a cognitive unit result. The agent decides patch versus replan versus ask. That transition is pursuit policy, not generation. See where the cognitive unit ends and the agent begins. When the same sufficient path keeps appearing, name it as a Skill and invoke the settled procedure. The loop applies to remaining uncertainty, not work the system already knows how to perform. See when a trajectory becomes a Skill.

Why boring loops win

Exciting demos hide loops inside monolithic prompts because demos optimize for first impression. Production systems optimize for incident response, regression evidence, and staff turnover. The engineer who joins six months later should read the loop in an afternoon. Ordinary code also makes cognitive orchestration inspectable: read state, call a dependency, run exact guards, choose a review transition, write state transactionally. Each step has an address in logs and evaluation, separate from chat history.

The loop should be boring. The judgments should be pointable.

Boring does not mean simplistic. A mature Meal Planning Agent may compose many Skills, several libraries, and a dozen cognitive units. The complexity lives in named boundaries with suites, not in emergent behaviour from one sprawling instruction. The pattern mirrors decades of good service design. Business rules do not live inside the database driver. UI event handlers do not replace domain logic. Third-party SDKs sit behind interfaces. Agents follow the same discipline. Cognition is material called through contracts. Control flow, authority, and persistence stay in code you can diff.

Pipeline, Skill, and agent

A fixed left-to-right path with no loop is a pipeline. When that path is a named capability with a contract and procedure evaluation, package it as a Skill. An acting Skill still is not an agent. Side effects inside a known procedure do not create goal ownership. See acting is not agency. Promote to an agent when case shape requires discovery, revision, and designed stopping. The Meal Companion needs an agent because critique may require local patch, full replan, or a targeted question depending on evidence. A stable invoice extraction path may remain a Skill indefinitely.

Even when cognitive units or Skills propose writes, code enforces grants. The Meal Planning Agent may propose a shopping list. Purchase still waits on approval. That pattern repeats for calendar writes, memory updates, and organisational actions. Ordinary code holds the gate. Cognition holds the proposal.

Testing ordinary loops

Ordinary loops are testable in ways prompt soups are not. You can cognitive unit-test transition tables, simulate guard failures, and assert working state updates without calling a live model. Integration tests invoke cognitive units with fixtures while keeping pursuit policy stable. That testability is why Thoughtware pushes control flow into code early. Demos optimize for first-run delight. Production optimizes for regression evidence when Tuesday practicality shifts after a checkpoint upgrade. Named cognitive units make that regression local. Ordinary loop code makes the transition that fired visible in logs.

No vendor agent framework is required for the architecture described here. Frameworks may help with adapters and telemetry. They should not replace explicit goal objects, working state schemas, or review transition tables. When a framework hides the loop inside opaque runtime magic, you inherit the same incident archaeology prompt-only designs produce. Treat frameworks as libraries beneath ordinary control flow, not as definitions of agenthood. The practical test is whether a new engineer can open the agent definition and draw the loop on a whiteboard within an hour without consulting prompt files. See the model is not the system for the same discipline applied to engines.

What to do next

The reassuring engineering picture starts here: an agent is a state object plus loop function plus named dependencies plus authority gates. Sketch the agent that way before selecting a framework. Move permissions, schema validation, and stop checks out of prompts into code. List every open judgment as a named cognitive units with a contract. Package settled multi-step work as Skills the loop invokes instead of rediscovering. When an incident arrives, ask where the transition was decided. If the answer is "the model felt it was time," the architecture still has demo-era debt to pay down.

See the agent loop, deterministic code, and five things called agent.

Read next: Agents own goals, not every judgment.