Documentation / guides
Define a Loop
Describe loop.Define, loop.Definition, and immutable loop configuration.
loop.Define is the only constructor for a public loop.Definition:
func Define(opts ...Option) (Definition, error)
The zero value of Definition is invalid. A successful result owns copies of
models, modes, tool-definition slices, delegates, context transports, and the
optional output schema. Reusing the same options to create a second definition
does not make the definitions share those mutable containers.
Definition options
Option is declared as type Option func(*definitionOptions) error; callers
normally use the exported option functions below.
| Option | Effect and validation |
|---|---|
WithName(identity.AgentName) | required nonblank registration name |
WithInference(inference.Client, model.Model) | required client and structurally valid model/key/effort |
WithSystem(string) | base system instructions |
WithDisplayName(string), WithDescription(string) | presentation metadata; description participates in Rig topology identity |
WithOutputSchema(inference.OutputSchema) | clones and validates a final structured-output policy |
WithTools(...tool.Definition) | additive declared factories; names must be nonblank and not reserved |
WithAccessGate(AccessGate) | fail-closed prepared-request gate; requires policy revision |
WithToolMiddlewares(...tool.ToolMiddleware) | additive middleware; nil entries are rejected and require policy revision |
WithToolLimits(ToolLimits) | singleton base limits; zero fields receive defaults |
WithDrainTimeout(time.Duration) | singleton nonnegative shutdown drain timeout; zero becomes five seconds |
WithEngine(Engine) | native or foreign engine marker; EngineAdapter is bind-time only and rejected here |
WithRuntimeContext(RuntimeContextProvider) | per-turn volatile blocks; nil is rejected and requires policy revision |
WithPolicyRevision(string) | stable identity for opaque policy collaborators |
WithDelegates(...identity.AgentName) | additive allowed child names |
WithDelegation(Delegation) | DelegationSyncOnly or DelegationManaged |
WithModes(...Mode) and WithInitialMode(ModeName) | declare named alternatives and choose the initial one |
WithContextCounter(contextcount.ContextCounter) | fixed complete-request counter |
WithInferenceCapability(contextcount.InferenceCapability) | fixed transport posture; required with a counter |
WithContextTransports(...ContextTransport) | complete admitted transport set; omitted means the base model’s one transport |
WithContextObservation(ContextObservationPolicy) | hard admission policy without compaction |
WithCompaction(CompactionPolicy) | manual and optional automatic compaction policy |
Options are not all interchangeable. Duplicate singleton options return
*loop.DefinitionError{Kind: loop.DefinitionDuplicateOption}. Context options
are checked as a group after all options have run, so option order cannot turn an
incomplete counter/capability/policy set into a valid definition.
Immutable result
The useful design-time accessors are:
func (d Definition) Name() identity.AgentName
func (d Definition) Description() string
func (d Definition) Engine() Engine
func (d Definition) Delegates() []identity.AgentName
func (d Definition) Modes() []Mode
func (d Definition) ToolRequirements() tool.Requirements
func (d Definition) InitialMode() ModeName
func (d Definition) FingerprintInitial() InitialFingerprint
func (d Definition) Delegation() Delegation
func (d Definition) PolicyRevision() string
func (d Definition) Bind(context.Context, tool.Bindings) (BoundDefinition, error)
Delegates and Modes are fresh slices. PolicyRevision is a deterministic
SHA-256 projection of execution behavior and opaque revisions. FingerprintInitial
resolves the initial model, effective system, and produced tool names without
building tool instances. Bind is where factories run and IDs are checked.
Validation order
%%{init: {"theme":"dark"}}%%
flowchart TD
A[Apply options] --> B[Required name, client, model]
B --> C[Tools, limits, engine, policy revision]
C --> D[Delegates and modes]
D --> E[Counter, capability, transport set]
E --> F[Observation or compaction policy]
F --> G[Output schema]
G --> H[Clone owned state]
H --> I[Return Definition]
Typical failures include DefinitionMissingName, DefinitionInvalidClient,
DefinitionInvalidModel, DefinitionInvalidTool, DefinitionMissingPolicyRevision,
DefinitionMissingInitialMode, DefinitionInvalidModeBinding,
DefinitionConflictingContextPolicy, and DefinitionInvalidOutputSchema.
Use errors.As instead of parsing error strings:
var de *loop.DefinitionError
if errors.As(err, &de) {
log.Printf("field=%s kind=%s", de.Field, de.Kind)
}