Observability Best Practices for Complex Systems
A system may produce an answer and then discover that the answer is incomplete.
Where a Straight-Line Flow Breaks Down
The applications built so far are fairly simple. A query arrives, the system performs its steps in a fixed order, and a response leaves the system. Nothing in that design goes back to an earlier step. Every query moves forward along one path and then stops.
Real tasks often do not fit a single forward pass. A system may produce an answer and then discover that the answer is incomplete. The design question is how to let the flow of an application bend: revisit earlier steps, split work into parallel branches, and choose different paths depending on what has happened so far. Those capabilities are what agentic patterns provide, and they are the subject of this article.
What do you think happens?
A system produces an answer, then judges that the task is not yet accomplished. What happens next in a looping flow?
Reveal answer
The system performs another retrieval to gather more information, and the original response together with the newly retrieved context is passed into the model again.
A straight-line flow would stop at the first answer. A loop treats the generated response as something that can be fed back in as input for further work.
What a Loop Feeds Back
An application flow with a loop is one in which the system can return to steps it has already run. The key ingredient is that a generated response does not have to be treated as the final output. It can be fed back into the system, where it becomes an input for further work.
The source gives a concrete case. After the system generates an output, it may judge that the task has not yet been accomplished. It then performs another retrieval to gather more information. The original response, together with the newly retrieved context, is passed into the same model or into a different one. That return path is the loop: the output of one pass becomes part of the input to the next pass.
Read the diagram as a route rather than a list. The decision node is where control branches. When the answer is no, control goes to the retrieval step and then returns to the model with more material. When the answer is yes, the flow exits. The source also allows the return pass to use a different model, because the combined response and context may go into either the same model or a different one.
Tracing the Passes State by State
The easiest way to understand a loop is to watch what the input to the model looks like on each pass. Each pass starts with whatever the previous pass left behind. The diagram below tracks that growth using a generic scenario: a request whose first answer is incomplete.
Notice what changed between the first and second passes. The loop did not restart from scratch. The earlier response survived and was combined with fresh retrieved material, so each iteration builds on the previous one. This is why a loop can improve an answer that a single pass left incomplete.
Counting Passes Through a Looping Flow
A generic request receives an answer on its first pass. The decision node says the task is not accomplished on passes one and two, and accomplished on pass three. How many retrievals run, and what does pass three receive?
- 1Pass 1
The model produces an output. The decision node says no, so a retrieval runs and its material is attached to the output.
- 2Pass 2
The model receives the earlier output plus the new material. The decision node says no again, so another retrieval runs and more material is attached.
- 3Pass 3
The model receives the earlier output plus both sets of retrieved material. The decision node says yes, so control exits the loop.
Two retrievals run. Pass three is the final model pass, and its input contains the outputs and retrieved context accumulated from the earlier passes.
Branches and Parallel Work
Loops are one of three flow features the source names: loops, parallel execution, and conditional branching. The source names all three as part of the same family of flow designs. It does not walk through a detailed example of the other two, so the central case to master is the loop, and the other two are understood as ways a flow can depart from a single line of steps.
Write Actions and Changing the Environment
So far the model's output has only been something the application reads, perhaps to decide whether to loop. A second capability is that a model's output can be used to invoke write actions. A write action is an action that changes the environment outside the model itself. The source gives three examples: composing an email, placing an order, and initializing a bank transfer.
The defining feature of a write action is that it does not merely produce text. It allows a system to make changes to its environment directly. The model's output names an action, and the application carries that action out in the external environment.
The contrast in the diagram is the important part. A read-only retrieval returns text that the model can use as context, and nothing outside the system is altered. A write action leaves the system and changes something in the environment. If the model's decision was wrong, the error is no longer contained in a generated sentence; it has already been acted on.
The Risk of Granting Write Access
Common mistake Treating a model's output as only text to display
What it looks likeA flow lets a model's output trigger an action such as placing an order, and the designer assumes the output is only shown to a user.
Why it failsA write action changes the environment directly, so the output has consequences beyond the screen.
Do this insteadTreat any output that can invoke a write action as a decision that changes state, and review how it reaches the external system.
Common mistake Assuming a loop always produces a better answer
What it looks likeA loop runs more passes and retrieves more material, so the designer assumes the final output must be correct.
Why it failsEach pass builds on the previous one, so an early error can be carried forward into later passes.
Do this insteadCheck what each pass receives and produces, instead of assuming the final output is correct because more work was done.
Common mistake Granting write access to a model without deciding which actions it may invoke
Why Complex Flows Are Harder to Debug
After you add loops, branches, and write actions, the architecture has usually grown quite complex. The source makes a point that is easy to overlook: complex systems can solve more tasks, but they also introduce more failure modes. Each additional loop, branch, or external action is another place where something can go wrong.
Debugging becomes harder because a failure may depend on which path the flow took, how many times a loop ran, or what context was retrieved on a particular pass. The source attributes this difficulty to the many potential points of failure. The diagram below shows the order in which components can interact during one request, which is the sequence a trace would need to reveal.
Practice: Trace a Request Through a Loop
A generic request passes through a model pass, a retrieval, and a second model pass. The decision node then exits the loop, and no write action runs. Describe in order what the second model pass receives, and say which component a trace should check first if the final answer is wrong.
Hints
- Think about what the first model output becomes on the next pass.
- A trace shows the order of passes, so check what context each pass received.
Key Takeaways
- A simple application flow runs one forward pass; agentic patterns let the flow loop, branch, and run work in parallel.
- In a loop, a generated response is fed back into the system, often after a retrieval, so each pass builds on the previous one.
- A write action changes the environment outside the model, such as composing an email, placing an order, or initializing a bank transfer, and it raises risk significantly, so access must be granted with care.
- Complex architectures introduce more failure modes, and failures can depend on the path taken or the number of loop passes, which is why observability matters.