Documentation / guides
Commit Boundary
Describe the event.StepDone commit boundary for a completed conceptual Harness Step.
event.StepDone is the durable commit record for a completed conceptual Step. It is emitted by the loop actor at the same boundary where the finalized Step group is appended to the loop’s committed history. A StepDone event is therefore an authoritative record, not an optimistic progress notification.
Public record
type StepDone struct {
enduring
loopScoped
Header
Messages content.AgenticMessages `json:"messages,omitempty"`
}
The Header.Coordinates identity contract is strict. A valid StepDone needs non-zero SessionID, LoopID, TurnID, StepID, and EventID; StepID without TurnID is invalid. event.ValidateEvent also requires the message-group shape described in Tool Calls and Results.
What commits
For a text-only Step, the commit candidate contains one assistant message. For a tool Step, it contains the assistant message followed by all tool-result messages. The actor performs these operations in order:
- stamp the StepDone event with its producer coordinates and EventID;
- preflight the durable context mutation;
- run the checked durable event boundary;
- append the candidate messages to committed loop history only after the boundary reports success; and
- acknowledge the parked Turn goroutine.
The history clone and the event payload are independent allocations. A consumer cannot mutate the live history by modifying StepDone.Messages, and the runtime cannot mutate the payload after it has been published.
%%{init: {"theme":"dark"}}%%
stateDiagram-v2
[*] --> Streaming
Streaming --> Materialized: EOF with usable output
Materialized --> ToolBatch: tool uses present
Materialized --> CommitCandidate: no tool uses
ToolBatch --> CommitCandidate: results appended
CommitCandidate --> DurableBoundary
DurableBoundary --> Committed: append succeeds
Committed --> StepDone
DurableBoundary --> Discarded: context canceled or append fails
Discarded --> TurnInterrupted: cancellation boundary
Discarded --> TurnFailed: non-cancellation boundary failure
StepDone --> [*]
Rollback scope
Rollback is step-granular, not whole-Turn. If the provider fails, the response is empty, a tool batch is canceled, or the commit handshake is canceled, the in-flight Step is discarded and no StepDone is emitted for it. Any earlier StepDone records in the same Turn remain committed. The enclosing Turn then publishes TurnFailed for a non-cancellation error or TurnInterrupted when the Turn context was canceled.
This is the important distinction:
| Observation | Meaning |
|---|---|
TokenDelta seen, no StepDone | Live output existed, but this Step did not reach the durable boundary. |
StepDone seen | The finalized group committed and is part of loop history. |
TurnFailed after earlier StepDone | Earlier Steps remain durable; only the current incomplete Step rolled back. |
TurnInterrupted during commit | The current group did not commit; already committed groups remain. |
Consumer pattern
package example
import (
"errors"
"fmt"
"github.com/looprig/harness/pkg/event"
)
func requireCommittedStep(ev event.Event) error {
step, ok := ev.(event.StepDone)
if !ok {
return fmt.Errorf("not a committed step: %T", ev)
}
if err := event.ValidateEvent(step); err != nil {
var invalid *event.InvalidEventError
if errors.As(err, &invalid) {
return fmt.Errorf("invalid StepDone field %s: %w", invalid.Field, err)
}
return err
}
return nil
}
Do not synthesize a missing StepDone from TokenDelta values. If you need replay or restore, consume the enduring event stream or journal. event.MarshalEvent has dedicated StepDone encoding and fails closed on malformed messages.