Field note · architecture
When Should an AI Workflow Split Into Subworkflows?
A deterministic fault-injection test shows the first exception branch that breaks causal reconstruction, plus a trace rubric for deciding what to split.

I built a small workflow with a model plan, a tool call, a validation gate, retries, human escalation, and a state update. Then I added exception paths one at a time.
The first three branches stayed explainable. The handoff branch did not. Both reviewer passes could reconstruct 6 of 6 required fields before the handoff, then only 3 of 6 after it was added.
That is the failure to look for. The workflow can still complete its happy path while its exception path has stopped carrying a complete explanation.
What does exception accumulation actually remove?
It removes a single causal path from failure to ownership. Each new exception can add a boundary, a policy, a state transition, a retry, or a new owner. If the runtime record does not carry those changes together, the reader sees events but cannot tell which decision caused the next one.
This is different from having many steps. A long workflow can remain explainable if every step preserves the same causal envelope. A short workflow can become opaque when a retry, handoff, or recovery worker starts a new partial story.
The six questions in my test were:
| Reviewer question | What the trace must expose |
|---|---|
| What started the exception path? | Triggering condition |
| Which boundary owned the failure? | Responsible boundary |
| Which rule was applied? | Policy or decision ID |
| What changed in workflow state? | State before and after |
| What did the system do next? | Recovery action |
| Who owns the unresolved work? | Final owner |
OpenAI describes agents as systems that use a model to manage workflow execution and tools to interact with external systems, with the ability to halt or transfer control when a failure occurs (OpenAI's agent guide). That transfer is the important boundary here. Once work leaves the orchestrator, the trace must say what left, why, under which policy, and who accepted it.
When I taught product managers who moved from writing specs to building and shipping, the failure was usually not the model. It was that nobody could say what done meant. The same problem appears here in a more technical form: nobody can say what recovered means, who owns it, or which state proves it.
What did the fault-injection test show?
The first traceability failure appeared when the human-handoff path was added. The later state-recovery path remained just as weak. The result came from six deterministic runs in fixture version 1.0.0, not from a production incident or a model benchmark.
| Run | Exception path added | Failure injected at | Reviewer A | Reviewer B | Finding |
|---|---|---|---|---|---|
| S0 | None | None | 6/6 | 6/6 | Happy path reconstructable |
| S1 | Planning retry | Planning | 6/6 | 6/6 | Retry remains attributable |
| S2 | Tool retry | Tool | 6/6 | 6/6 | Tool boundary remains attributable |
| S3 | Validation repair | Validation | 6/6 | 6/6 | Repair remains attributable |
| S4 | Human escalation | Handoff | 3/6 | 3/6 | First traceability failure |
| S5 | State recovery | State recovery | 3/6 | 3/6 | Causal link still missing |
The test adds one path per run, so the result is easy to locate. Nothing failed at the planning retry, tool retry, or validation repair. The score dropped at the first branch that changed ownership.
That does not mean human escalation is always the breaking point. It means this fixture had complete event fields for local retries and incomplete fields at the handoff. Your first failure may appear at a different boundary. The method is meant to find it.

Which trace fields must survive every exception branch?
Every exception event should carry the same small envelope, even when the recovery code is different. The envelope below is enough to make a reviewer test the path without opening implementation code.
{
"seq": 5,
"type": "validation_failed",
"boundary": "validation_gate",
"trigger_condition": "required_field_missing",
"policy": "validation_repair_once",
"state_before": "tool_result_ready",
"state_after": "validation_retry",
"recovery_action": "request_model_repair",
"final_owner": "orchestrator"
}
The field names are not a vendor standard. They are the smallest contract I used to ask the same six questions across all six runs.
This design lines up with the broader architecture guidance. Microsoft recommends instrumenting agent operations and handoffs, testing individual interfaces and the whole workflow, and persisting external state so long-running work can resume after interruption (Microsoft's AI agent orchestration guidance). AWS treats observability as a concern that spans layers, rather than a concern owned by only one component (AWS's enterprise agentic architecture guidance).
The trace should preserve observable behavior, not private model reasoning. You need the selected tool, validation result, policy decision, state transition, recovery action, and owner. You do not need to copy an entire customer record or a model's hidden reasoning into the trace.
Where does an AI workflow first become impossible to explain?
In this fixture, it became impossible to explain at the handoff event because the event recorded that review was needed, but not why, under which policy, or who finally owned the work.
Here is the raw failing event:
{
"seq": 5,
"type": "human_handoff",
"boundary": "orchestrator",
"reason": "needs_review",
"state_before": "validated",
"state_after": "review_pending",
"recovery_action": "enqueue_for_human_review",
"final_owner": null
}
The next event made the ambiguity worse:
{
"seq": 6,
"type": "workflow_closed",
"boundary": "orchestrator",
"trigger_condition": "handoff_queued",
"policy": "close_after_handoff",
"state_before": "review_pending",
"state_after": "escalated",
"recovery_action": "await_external_owner",
"final_owner": null
}
A reader can identify the orchestrator boundary, the state change, and the queue action. They cannot identify the original trigger, the handoff policy, or the final owner. “Needs review” is a reason label, not a causal condition. “Await external owner” is a recovery instruction, not an owner.
SHIELDA makes a related distinction in research terms: execution exceptions should be connected to reasoning-phase root causes, and recovery needs structured handling for local action, flow control, and state recovery (the SHIELDA paper). My fixture is smaller. It tests whether a human can see that connection in one runtime record.
Should you simplify, isolate, or split the next exception?
Use the first failed trace as a design decision, not as a reason to add another handler immediately.
| What the reviewer finds | Decision | What to do |
|---|---|---|
| All six fields are visible | Keep the branch | Add the next fault injection using the same envelope |
| One or more fields disappear | Freeze new exception logic | Repair the event contract, then rerun the existing matrix |
| Work moves to a human queue | Isolate the handoff | Add a handoff ID, origin event ID, queue owner, acceptance state, and closure event |
| Recovery crosses a durable store or worker | Split state reconciliation | Persist checkpoint identity, source-of-truth version, state transition, and final owner |
| The path duplicates a retry or deterministic gate | Simplify or delete it | Put the behavior in the existing boundary and rerun the test |
The Google Cloud architecture guidance makes a similar architectural point from another angle: choose patterns using workload characteristics such as complexity and human involvement, revisit the choice as requirements change, and prefer simpler non-agentic solutions for predictable structured work when they fit (Google Cloud's design-pattern guidance).
My worked decision is therefore: keep S1 through S3 in the same workflow, isolate S4 as an explicit review subworkflow, and do not add S5 until the handoff has a causal link and an owner. If state recovery still starts a new trace, split reconciliation from the business workflow instead of adding another opaque branch.
This is not a universal “three branches means split” rule. The observed boundary is the first reviewer guess. If the missing field can be repaired without changing ownership, repair the trace. If the branch creates a new owner or state authority, give it a boundary that can be traced.
How do you repair the trace before adding another branch?
Run the check on your workflow in this order:
- Freeze the current version. Record the workflow version, trace schema version, scenario definitions, and the source-of-truth state store.
- Run the happy path. Confirm that the trace identifies the task, the boundaries, the state transitions, and the final owner before you inject a failure.
- Add one exception path. Inject one representative failure at planning, tool execution, validation, handoff, or recovery. Do not add a second branch in the same run.
- Review the trace blind to implementation. Ask two reviewers to identify the six fields from the trace alone. Preserve disagreements instead of averaging them away.
- Decide before coding again. Keep a complete branch, repair an incomplete envelope, isolate a new owner, split a new state authority, or delete a duplicate policy. Then rerun every earlier scenario.
For a handoff, the repaired event needs at least this information:
{
"type": "human_handoff",
"trigger_condition": "validation_failed_after_repair",
"policy": "escalate_after_repair_budget",
"origin_event_id": "evt-004",
"handoff_id": "handoff-005",
"state_before": "validation_retry",
"state_after": "review_pending",
"recovery_action": "enqueue_for_human_review",
"final_owner": "billing-review-queue"
}
The exact IDs will differ in your system. The point is that a later reviewer should not have to infer ownership from a queue name, or infer cause from the fact that a handoff happened.
What should you test next?
Start with the exception that changes ownership or state authority. That is where the explanation usually crosses a boundary. Link the result to your AI workflow architecture parent guide, then compare the runtime record with the more general practices in AI agent production monitoring and replaying a failed multi-agent workflow.
If you already have production traces, the next useful exercise is to sample one failure from each exception boundary and run the same six-field review. The workflow trace dataset guide can help turn those records into repeatable cases.
I would not add another recovery branch until two people can answer the six questions from the current trace. If they cannot, the architecture is already asking for explanation that the runtime record does not contain.
Questions people ask next
What is the minimum trace an AI workflow exception needs?
Record the triggering condition, responsible boundary, applied policy, state before and after, recovery action, and final owner. If one is missing, a reviewer has to infer part of the recovery path.
Should every AI workflow exception become a new agent or branch?
No. First check whether the case is a deterministic validation or an existing retry. Add a branch only when it represents a distinct policy and recovery owner that the trace can preserve.
When should an AI workflow split state recovery into another component?
Split it when recovery crosses a durable state boundary or worker and the original trace cannot link the cause, checkpoint, state transition, and final owner in one reviewable record.