AI Agent Pipelines: Execution Boundaries Behind the Eight Stages
TECH INSIGHT / EXPLAINED
Splitting an agent loop is not mainly about making functions shorter. It creates boundaries that block tool execution after a truncated response and define what may be saved after cancellation.
Eight responsibilities, three execution zones
Context, history, and prompt prepare inputs, permissions, conversation, and instructions. Think, act, and observe repeat model calls, validated tool execution, and result collection. Memory and summarize handle persistence and summarization. This is one design, not a requirement for exactly eight classes. Long runs can also need intermediate checkpoints.
Check the token budget before the model call. If results grow, compact before the next think stage while preserving tool calls with their corresponding results. Keep source identifiers and versions so summarized material can be retrieved.
Return decisions instead of storing them on stages
A shared stage instance with mutable s.result can mix decisions between requests. Return a decision and allocate RunState per request. Shared dependencies must also be concurrency-safe. This is an interface design fragment.
type Decision int
const (
Next Decision = iota
RetryModel // skip tool execution for this iteration
Complete // preserve answer, then finalize
Abort
)
type Stage interface {
Name() string
Execute(context.Context, *RunState) (Decision, error)
}
// The returned decision belongs to this call, not a shared stage field.
// RunState is allocated separately for every request.Do not let incomplete output reach act
Validate the completion status, tool name, argument JSON and schema, and current user permissions. Never execute incomplete arguments. RetryModel skips act and observe for that iteration and returns to the model within a retry limit. Truncated plain text should also be marked incomplete or handled by an explicit continuation policy, rather than silently treated as complete.
For Complete, save the final answer into RunState before checkpointing and finalization, with no tool execution. Abort and errors stop new external actions. Persist a terminal status when iteration, token, cost, or time budgets are exhausted.
Bound cleanup after cancellation
Go's WithoutCancel detaches the parent's deadline as well as cancellation. Give cleanup its own short timeout so persistence cannot wait forever. This fragment requires Go 1.21 or later.
cleanupCtx, cancel := context.WithTimeout(
context.WithoutCancel(ctx), 3*time.Second,
)
defer cancel()
err := saveCheckpoint(cleanupCtx, state)Cleanup should not launch new tools or unbounded summarization. If checkpointing fails, distinguish persistence status and leave an operational record suitable for recovery.
Four paths worth testing
- Normal text: preserve the answer; zero tool calls.
- Truncated JSON: zero tool calls; bounded model retry.
- Disconnect after tool acceptance: reconcile by identifier instead of blindly repeating it.
- Cancellation: stop new work and bound checkpoint processing.
Adding hooks at these execution boundaries
References
Content and examples reviewed: 2026-09-29
댓글
댓글 쓰기