The Boundary Model

Pawel Zimoch · ~9 min read · Essay 05

Coding assistants evolved into coding agents gradually. First they completed single turns—write this function, explain this code. Then they gained tools—read files, run commands, see errors. Then they started iterating—try something, see it fail, adjust, try again. Now they run complex multi-step workflows with minimal supervision.

This progression wasn't just models getting better. It happened because someone built the structure that made each stage possible. Anthropic built tools for navigating files. They structured error messages to be actionable. They gave the agent ways to check its work—run the code, see the output, understand what went wrong.

That structure is the interface. It's what lets an agent try, fail, understand why, and try again. Without it, failure is opaque. With it, failure is information.

For coding, that interface already exists. For your domain—expense approvals, customer support, inventory management—it doesn't. You have to build it.

This essay is about what that process looks like. Not designing a complete system upfront, but building the interface incrementally as you learn what your domain actually needs.

Two Kinds of Workflows

Before diving into the process, a distinction matters.

Employee-initiated workflows start when someone on your team wants to do something. They open a tool, ask an agent for help, review the output, approve or adjust. The human is there because they started the work.

Customer-initiated or event-driven workflows start externally. A customer sends a message. A webhook fires. An order arrives. The system must respond—and there's no human who initiated it.

The temptation with customer-initiated workflows is to replace the human entirely. Customer sends message, agent responds, done. But this almost never works out of the gate. The agent makes mistakes. Customers get frustrated. Trust erodes.

The better path: humans stay in the loop initially, even for customer-initiated work. Maybe through voice, maybe through chat, maybe reviewing before responses go out. The automation doesn't remove humans—it makes them more effective. One person supervising five agent conversations instead of handling five conversations directly.

Both workflow types require building structure. The difference is psychological. In employee-initiated work, human presence feels natural—they wanted to do something. In customer-initiated work, the human presence can feel like overhead, something to eliminate. Resist that temptation. The human is how you learn what structure to build.

Stage 1: Translation

Start with the agent as translator. It reads, interprets, gathers information, proposes actions. You approve everything.

In an expense workflow: the agent looks at a receipt, extracts the amount and vendor, guesses a category, drafts a decision. You review. Approve, reject, or correct.

In customer support: the agent reads the incoming message, pulls up customer history, drafts a response. You review before it sends.

At this stage, the interface is informal. Natural language in, natural language out. The agent proposes; you decide.

Agent autonomy: none. Every action needs approval.

What you're learning: What operations actually exist in your domain. What the agent keeps proposing. What you keep approving. Where it gets confused.

This stage feels slow. That's fine. You're building understanding, not automation.

Stage 2: Discrete Outputs

Patterns emerge from your approvals. The agent's proposals cluster into categories. "This is always one of: approve, reject, escalate, request more information."

Make outputs discrete. Instead of free-form recommendations, the agent must choose from defined options.

Decision = APPROVE | REJECT | ESCALATE | REQUEST_INFO
Category = MEALS | TRAVEL | SOFTWARE | SUPPLIES | OTHER
Priority = LOW | MEDIUM | HIGH | URGENT

This seems like a small change. It's not. Discrete outputs let you measure. "The agent said APPROVE—was that right?" becomes a question with an answer. You can track accuracy by category. You can see where the agent struggles.

The interface now has vocabulary—the nouns and verbs of your domain. Not operations yet, just the words.

Agent autonomy: still none. You're still approving. But now you're approving structured decisions, not prose.

What you're building: the vocabulary. What things are called. What categories exist. This is domain modeling, done empirically rather than theoretically.

Stage 3: Validation Gates

Your approvals have patterns. "Under $100 and category is meals or supplies—I always approve these." "Customer asking about order status—I always send the tracking link."

Turn patterns into validation rules. These become the first real operations in your interface.

auto_approve(expense)
  preconditions:
    - amount < 100
    - category in [MEALS, SUPPLIES]
    - receipt attached
  effects:
    - expense.status = APPROVED

Now the agent can execute this operation without your approval—if preconditions are met. Preconditions not met? Still comes to you.

This is the first automated boundary. Cases inside the boundary don't need you. Cases outside still do.

Agent autonomy: executes validated operations independently. You handle everything else.

What you're building: the first operations with preconditions and effects. The beginning of a real interface. Each operation encodes something you learned: "these cases are safe to automate."

Stage 4: Retry Capability

The agent starts hitting boundaries. It tries an operation, fails, but doesn't know why. The error says "operation failed." Not helpful.

Structure your errors. Make them specific enough that the agent can adjust.

errors:
  AMOUNT_EXCEEDS_AUTO_APPROVE_LIMIT
  CATEGORY_REQUIRES_MANAGER_REVIEW
  MISSING_RECEIPT
  VENDOR_NOT_IN_APPROVED_LIST

Add tools that let the agent get context it needs.

tools:
  get_expense_policy(category) -> Policy
  get_employee_history(employee_id) -> RecentExpenses
  check_vendor_status(vendor) -> VendorInfo

Now the agent can try, fail, understand why, query for more information, and try again. This is what makes multi-step workflows possible.

Agent autonomy: can run workflows with multiple steps. Can recover from failures within the boundary.

What you're building: the feedback loop. Errors that inform rather than block. Tools that provide context. This is what Claude Code has for coding—actionable error messages, ability to check file contents, ability to run and see output. You're building the equivalent for your domain.

Stage 5: Expand the Boundary

With retry capability working, you can expand what's inside the boundary.

Add more operations:

request_receipt(expense, message) -> Expense
escalate_to_manager(expense, reason) -> Expense
reject_with_explanation(expense, reason) -> Expense

Add more valid categories, more state transitions, more preconditions. Each addition comes from observation: "I keep handling this case manually, and there's a pattern."

The interface grows to match your domain. Not all at once—operation by operation, each one encoding something you learned.

Agent autonomy: handles most routine cases. You handle edges, exceptions, novel situations.

What you're building: coverage. The interface expands to cover more of the territory. But you're still learning—UNKNOWN cases still come to you, and patterns in UNKNOWN tell you where to expand next.

Stage 6: Scale Supervision

The interface is mature enough that routine work flows through without you. You're not approving every expense or every customer response. You're handling escalations, reviewing samples, adjusting rules when patterns shift.

One person can now supervise multiple agents. Not because agents are fully autonomous—they're not—but because the interface handles the routine. Human attention goes to what actually needs judgment.

Agent autonomy: near-autonomous for well-understood cases. Escalates what doesn't fit.

What you've built: a language your agents operate in. Operations they can invoke. Validation that catches errors. Errors that enable retry. Escape hatches for uncertainty. This is the interface that makes reliable automation possible.

The Interface Is Crystallized Supervision

The interface you end up with isn't designed from first principles. It's crystallized from supervision.

Every validation rule started as something you caught. "This shouldn't auto-approve—amount is too high." Now there's a precondition.

Every error type started as confusion you clarified. "Why did it fail?" "Because the vendor isn't approved." Now there's a specific error.

Every tool started as information you provided. "Check if they've submitted similar expenses recently." Now there's a query the agent can run.

The interface encodes your judgment. That's why building it requires going through the stages—you can't encode judgment you haven't exercised.

Why Customer-Initiated Workflows Are Harder

This progression is easier to see in employee-initiated work. You're there, you're supervising, building the interface feels natural.

Customer-initiated workflows create pressure to skip stages. "We need to automate support. Let's deploy an agent." But without the interface, the agent hallucinates categories, takes invalid actions, responds confidently and incorrectly.

The progression still applies. Start with agents assisting human support reps—reading history, drafting responses, gathering context. The human approves before anything reaches the customer. Yes, this means humans are still in the loop. That's the point. You're learning what the interface needs to be.

Over time, patterns emerge. Common responses. Routine cases. These become validated operations. The agent handles them directly. The human handles the rest. Supervision ratio improves gradually, not all at once.

The structure that enables autonomous customer-facing agents is the same structure: discrete outputs, validated operations, retry capability, escape hatches. You just build it more carefully, because mistakes reach customers.

What You're Actually Building

Through this progression, you're building a domain-specific language. Not in the formal sense—you're probably not writing a parser. But in the practical sense: a constrained set of operations the agent can invoke, with validation that catches errors before they cause harm.

Claude Code has this for coding. File operations. Shell commands. Error handling. The ability to run code and see output. That's the interface that makes coding agents work.

For your domain, you need the equivalent:

This is the interface. Building it is how you make progress. Not by deploying agents and hoping, but by supervising agents and encoding what you learn.


For why structure enables reliability, see The Structure Problem.

For what the interface components are, see Building the Interface.