Documentation
¶
Index ¶
- Constants
- Variables
- type AgentDefinition
- type AgentRuntimeConfig
- type AssistantMessageCompletedPayload
- type AssistantMessageStartedPayload
- type AssistantToolCallPayload
- type Attachment
- type AttachmentRef
- type AttachmentStore
- type Attempt
- type AttemptStartedEvent
- type CompactRequest
- type CompactionEvent
- type CompactionPayload
- type Config
- type Conversation
- type ConversationCreatedPayload
- type ConversationStore
- type ConversationTree
- type Correlation
- type DeltaEvent
- type Dispatch
- type DispatchMessage
- type DispatchResult
- type Env
- type HarnessEvent
- type InboundKind
- type InstanceID
- type Interceptor
- type LeaseRenewal
- type MessagePayload
- type Observer
- type OpInfo
- type OpKind
- type OperationEndedEvent
- type OperationStartedEvent
- type OrphanPolicy
- type ParentRef
- type Record
- type RecordEnvelope
- type RecordKind
- type RecoveryEvent
- type ReducedEntry
- type Runtime
- func (rt *Runtime) Close() error
- func (rt *Runtime) Compact(ctx context.Context, req CompactRequest) error
- func (rt *Runtime) Dispatch(ctx context.Context, d Dispatch) (DispatchResult, error)
- func (rt *Runtime) FollowUp(ctx context.Context, req SteerRequest) error
- func (rt *Runtime) Handler() http.Handler
- func (rt *Runtime) Records(ctx context.Context, conversationID string, afterID string) ([]Record, error)
- func (rt *Runtime) Start(ctx context.Context) error
- func (rt *Runtime) Steer(ctx context.Context, req SteerRequest) error
- func (rt *Runtime) Wait(ctx context.Context, submissionID string) (SettledPayload, error)
- type SessionKey
- type SettledErrorCode
- type SettledPayload
- type SettledStatus
- type SignalMeta
- type SignalPayload
- type SpawnParent
- type SteerRequest
- type Store
- type SubagentLimits
- type SubagentPolicy
- type Submission
- type SubmissionAdmittedEvent
- type SubmissionClaim
- type SubmissionClaimedEvent
- type SubmissionRelease
- type SubmissionResumedEvent
- type SubmissionSettledEvent
- type SubmissionSpawnedEvent
- type SubmissionStatus
- type SubmissionStore
- type SubmissionWait
- type SubmissionWaitingEvent
- type TaskSpawnedPayload
- type TextDeltaPayload
- type ThinkingDeltaPayload
- type ToolCallEndedEvent
- type ToolCallStartedEvent
- type ToolCallUpdatedEvent
- type ToolOutcomePayload
- type TurnEndedEvent
- type TurnStartedEvent
- type UserMessagePayload
Constants ¶
const ( DefaultMaxAttempts = 10 DefaultSubmissionTimeout = time.Hour )
Durability budget defaults (architecture.md §4.2 invariant 7).
const DefaultResultRetries = 2
DefaultResultRetries is the feedback-retry budget when a Prompt requests a structured result and leaves ResultRetries at 0.
Variables ¶
var ( // ErrUnknownAgent reports a dispatch to an agent name with no registered // definition. ErrUnknownAgent = errors.New("unknown agent") // ErrRuntimeClosed reports an operation on a closed Runtime. ErrRuntimeClosed = errors.New("runtime is closed") // ErrNoRunInFlight reports a steer or follow-up aimed at a session with // no live run. Steering is live-only in v1 (ADR-0004); nothing is // persisted. ErrNoRunInFlight = errors.New("no run in flight for the session") // ErrSessionBusy reports a Compact aimed at a session whose run is in // flight; compaction is an idle-session operation. ErrSessionBusy = errors.New("session has a run in flight") )
Runtime-level sentinel errors.
var ( // ErrDispatchConflict reports a re-admission of an existing dispatch id // with a different payload. Identical replays are not an error — they // return the original submission. ErrDispatchConflict = errors.New("dispatch id already admitted with a different payload") // ErrSubmissionNotFound reports an unknown submission id. ErrSubmissionNotFound = errors.New("submission not found") // ErrConversationNotFound reports an unknown conversation. ErrConversationNotFound = errors.New("conversation not found") // ErrClaimLost reports a state CAS (claim, release, reserve, finalize, // lease renewal) that did not apply because the submission was not in the // expected state or owned by the expected attempt. ErrClaimLost = errors.New("submission claim lost") // ErrAttachmentNotFound reports an unknown attachment digest. ErrAttachmentNotFound = errors.New("attachment not found") // ErrUnsupportedSchema reports a store opened over a persisted schema // version this build does not support. ErrUnsupportedSchema = errors.New("unsupported store schema version") )
Store-level sentinel errors. Every implementation returns these (possibly wrapped) so callers can branch with errors.Is.
var ErrInvalidDispatch = errors.New("invalid dispatch")
ErrInvalidDispatch reports a dispatch rejected at admission; nothing entered the store.
Functions ¶
This section is empty.
Types ¶
type AgentDefinition ¶
type AgentDefinition struct {
// Description is routing metadata shown to parent models in the task
// tool schema (HARNESS-15).
Description string
Initialize func(ctx context.Context, id InstanceID, env Env) (AgentRuntimeConfig, error)
}
AgentDefinition is a named initializer registered in Runtime config (ADR-0009). Initialize runs on every claim, so per-instance dynamic setup — tenant prompts, per-user tools — is first-class.
type AgentRuntimeConfig ¶
type AgentRuntimeConfig struct {
Model string
ContextWindow int
MaxTokens int
Providers []llm.LLMProvider
SystemPrompt string
Tools []pi.RegisteredTool
Skills []pi.Skill
// ReserveTokens and KeepRecentTokens tune agent-core's compaction cut
// point; zero values use agent-core's defaults.
ReserveTokens int
KeepRecentTokens int
// SummarizationRetry configures agent-core's bounded retry of transient
// summarization failures during Compact (agent-core v0.7.0). The zero
// value disables retries; enabling it keeps a transient 429/5xx from
// failing a compaction outright. Retry lifecycle is surfaced to
// Observers as RecoveryEvents.
SummarizationRetry pi.SummarizationRetryPolicy
// MaxAttempts is the durability budget on execution tries, recomputed
// from durable history on every claim; 0 means DefaultMaxAttempts.
MaxAttempts int
// SubmissionTimeout bounds a submission's total lifetime from admission;
// 0 means DefaultSubmissionTimeout.
SubmissionTimeout time.Duration
}
AgentRuntimeConfig is the result of an AgentDefinition initializer: the complete, catalog-free declaration of how one agent instance runs (ADR-0007). Model is a "provider/model" ref resolved against Providers by name; ContextWindow is required and drives compaction thresholds.
type AssistantMessageCompletedPayload ¶
type AssistantMessageCompletedPayload struct {
Message MessagePayload `json:"message"`
}
AssistantMessageCompletedPayload is the payload of an assistant_message_completed record: the final message as agent-core appended it to the transcript.
type AssistantMessageStartedPayload ¶
type AssistantMessageStartedPayload struct {
Model string `json:"model"`
MessageType string `json:"messageType"`
}
AssistantMessageStartedPayload is the payload of an assistant_message_started record, announcing an assistant message of the given type from the given model.
type AssistantToolCallPayload ¶
type AssistantToolCallPayload struct {
CallID string `json:"callId"`
ToolName string `json:"toolName"`
Args json.RawMessage `json:"args,omitempty"`
ThoughtSignature []byte `json:"thoughtSignature,omitempty"`
}
AssistantToolCallPayload is the payload of an assistant_tool_call record. ThoughtSignature is the provider's opaque per-call signature (Gemini 3); turn recovery must replay it with the call or the provider rejects the recovered turn (HARNESS-11). Additive: absent for providers without one.
type Attachment ¶
type Attachment struct {
Ref AttachmentRef
Data []byte
}
Attachment is one out-of-line blob plus its ref. Records carry only the ref; the bytes live in the AttachmentStore keyed by content digest.
type AttachmentRef ¶
type AttachmentRef struct {
Digest string `json:"digest"`
MediaType string `json:"mediaType"`
Size int64 `json:"size"`
}
AttachmentRef points at bytes stored out-of-line in the AttachmentStore. It is part of the record schema from day one (ADR-0006) even though v1 has no ingestion path.
type AttachmentStore ¶
type AttachmentStore interface {
// PutAttachment stores data and returns its ref. The digest is
// "sha256:<hex>" over the raw bytes; putting identical bytes twice is
// idempotent and returns the same ref.
PutAttachment(ctx context.Context, mediaType string, data []byte) (AttachmentRef, error)
// GetAttachment returns the attachment by digest, or
// ErrAttachmentNotFound.
GetAttachment(ctx context.Context, digest string) (Attachment, error)
}
AttachmentStore is the digest-keyed blob half of the store contract. It is in the schema from day one (ADR-0006) so vision later is a feature, not a migration; v1 ships no ingestion path.
type Attempt ¶
type Attempt struct {
ID string `json:"id"`
SubmissionID string `json:"submissionId"`
OwnerID string `json:"ownerId"`
StartedAt time.Time `json:"startedAt"`
}
Attempt is the durable marker of one execution try. The marker is written before any work happens, so reconciliation can distinguish "started then died" from "never started"; budgets are recomputed from the marker history.
type AttemptStartedEvent ¶
type AttemptStartedEvent struct{ Correlation }
AttemptStartedEvent reports the durable attempt marker landing.
type CompactRequest ¶
type CompactRequest struct {
Agent string
Instance InstanceID
Session string // empty means "default"
}
CompactRequest addresses a session for the manual Compact operation.
type CompactionEvent ¶
type CompactionEvent struct {
Correlation
Reason string // "manual" | "overflow"
}
CompactionEvent reports a compaction landing (manual or recovery-driven).
type CompactionPayload ¶
type CompactionPayload struct {
Summary string `json:"summary"`
FirstKeptEntryID string `json:"firstKeptEntryId,omitempty"`
StartIdx int `json:"startIdx"`
EndIdx int `json:"endIdx"`
// Usage is the summarization usage from the agent's BranchSummary; nil
// when the provider reported none (AGENT-20 follow-through).
Usage *pi.Usage `json:"usage,omitempty"`
}
CompactionPayload is the payload of a compaction record: the summary text plus the re-parent point. StartIdx/EndIdx mirror agent-core's BranchSummary range so LoadBranchSummaries can round-trip it.
type Config ¶
type Config struct {
Agents map[string]AgentDefinition
Store Store
// Env is passed to every AgentDefinition initializer; nil means OSEnv().
Env Env
// Logger receives engine diagnostics; nil means slog.Default().
Logger *slog.Logger
// ClaimInterval is the coordinator's poll cadence between wake nudges;
// 0 means 250ms.
ClaimInterval time.Duration
// LeaseDuration bounds attempt ownership; heartbeats renew at a third of
// it. 0 means 30s.
LeaseDuration time.Duration
// DeltaFlushBytes flushes a pending delta batch once it reaches this
// size; 0 means 1024. Message boundaries always flush regardless.
DeltaFlushBytes int
// DeltaFlushInterval flushes a pending delta batch once its oldest
// fragment is this stale; 0 means 200ms.
DeltaFlushInterval time.Duration
// Observers receive ephemeral HarnessEvents synchronously (ADR-0008).
Observers []Observer
// Interceptors wrap every operation boundary in registration order
// (first is outermost).
Interceptors []Interceptor
// Subagents maps an agent definition name to the definitions it may
// spawn (HARNESS-15); an absent key means no task tool.
Subagents SubagentPolicy
// SubagentLimits bound durable subagent fan-out; zero values resolve to
// documented defaults at NewRuntime.
SubagentLimits SubagentLimits
}
Config carries everything NewRuntime needs: the named agent definitions, the store, and optional environment, logging, and engine-timing seams.
type Conversation ¶
type Conversation struct {
ID string `json:"id"`
Key SessionKey `json:"key"`
CreatedAt time.Time `json:"createdAt"`
}
Conversation is the stored identity of one session's conversation log.
type ConversationCreatedPayload ¶
type ConversationCreatedPayload struct {
Agent string `json:"agent"`
Instance InstanceID `json:"instance"`
Session string `json:"session"`
// ParentRef links a child conversation to the task_spawned record that
// created it (HARNESS-15); nil for root conversations.
ParentRef *ParentRef `json:"parentRef,omitempty"`
}
ConversationCreatedPayload is the payload of a conversation_created record.
type ConversationStore ¶
type ConversationStore interface {
// EnsureConversation returns the conversation for key, creating it with
// the supplied candidate (ID, CreatedAt) when absent. The bool reports
// whether this call created it.
EnsureConversation(ctx context.Context, candidate Conversation) (Conversation, bool, error)
// GetConversation returns the conversation for key, or
// ErrConversationNotFound.
GetConversation(ctx context.Context, key SessionKey) (Conversation, error)
// AppendRecords appends records to the conversation log in order.
AppendRecords(ctx context.Context, conversationID string, recs []Record) error
// ReadRecords returns records with IDs strictly greater than afterID in
// append order; afterID "" reads from the start.
ReadRecords(ctx context.Context, conversationID string, afterID string) ([]Record, error)
}
ConversationStore is the conversation-log half of the store contract: an append-only record log per conversation plus the session-key mapping.
type ConversationTree ¶
type ConversationTree struct {
// Entries holds every reduced entry in log order. Nothing is ever
// removed: compaction re-parents, it never deletes.
Entries []ReducedEntry
// LeafID is the ID of the active leaf entry; "" for an empty tree.
LeafID string
}
ConversationTree is the reduced, parent-linked projection of a conversation log. It is derived exclusively by Reduce and never stored.
func Reduce ¶
func Reduce(records []Record) ConversationTree
Reduce is the pure projection from a record log to a conversation tree. It is deterministic, and prefix-consistent: Reduce(log[:n]) contains exactly the first n records in order, and an entry's parent only ever changes when a later compaction record re-parents it.
Non-compaction records chain onto the current leaf. A compaction record carrying FirstKeptEntryID becomes a summary node at the root of the active branch: the kept entry re-parents onto it, and everything the summary covered remains reachable as an abandoned branch — history is never rewritten, only re-rooted.
func (ConversationTree) ActiveLeafPath ¶
func (t ConversationTree) ActiveLeafPath() []Record
ActiveLeafPath returns the records on the path from the active branch's root to the leaf, in order. This is what the projection adapter serves to agent-core.
type Correlation ¶
type Correlation struct {
SessionKey SessionKey
ConversationID string
SubmissionID string
AttemptID string
TurnID string
}
Correlation carries the same ids as record envelopes, so observer output lines up with the durable record of what happened.
type DeltaEvent ¶
type DeltaEvent struct {
Correlation
Kind RecordKind // assistant_text_delta or assistant_thinking_delta
Text string
}
DeltaEvent reports one streamed fragment (unbatched — observers see what the model emitted, not the flush policy).
type Dispatch ¶
type Dispatch struct {
Agent string
Instance InstanceID
Session string // empty means "default"
DispatchID string
Message DispatchMessage
// Parent, when set, marks the dispatch as a spawned child run
// (HARNESS-15); admission links the conversation and submission back to
// the parent run. The link is partially honored when the target session
// key already has a conversation (EnsureConversation's not-created path,
// e.g. an idempotent re-drive): no new conversation_created is written,
// so ParentRef is not re-asserted, while the submission still records
// ParentSubmissionID/ParentCallID/Depth.
Parent *SpawnParent
}
Dispatch is an inbound request to run work: admission, not execution. DispatchID is the idempotency key; when empty a fresh one is generated, which opts the caller out of idempotent replay.
type DispatchMessage ¶
type DispatchMessage struct {
Kind InboundKind `json:"kind"`
Body string `json:"body"`
Attachments []AttachmentRef `json:"attachments,omitempty"`
Signal *SignalMeta `json:"signal,omitempty"`
// ResultSchema, when set, is a JSON Schema the run's final answer must
// validate against; the validated JSON rides the submission_settled
// record.
ResultSchema json.RawMessage `json:"resultSchema,omitempty"`
// ResultRetries bounds the validate→feedback→retry loop; 0 means
// DefaultResultRetries.
ResultRetries int `json:"resultRetries,omitempty"`
}
DispatchMessage is the inbound payload of a dispatch: a discriminated user-or-signal union, plus the optional structured-result request. It is stored durably on the submission, so re-attempts and idempotency comparisons see the schema too.
func SignalMessage ¶
func SignalMessage(body string, meta SignalMeta) DispatchMessage
SignalMessage builds a signal-kind DispatchMessage.
func UserMessage ¶
func UserMessage(body string) DispatchMessage
UserMessage builds a user-kind DispatchMessage.
func (DispatchMessage) Validate ¶
func (m DispatchMessage) Validate() error
Validate checks the structural rules of the inbound union. It is called at admission; a failing message never enters the store.
type DispatchResult ¶
type DispatchResult struct {
SubmissionID string `json:"submissionId"`
ConversationID string `json:"conversationId"`
}
DispatchResult is the admission receipt: the durable submission created (or replayed) for the dispatch, and the conversation it targets.
type Env ¶
type Env interface {
// Secret returns the named secret, or "" when absent.
Secret(name string) string
}
Env is the injection seam for secrets and config lookup inside AgentDefinition initializers, keeping definitions unit-testable.
type HarnessEvent ¶
type HarnessEvent interface {
// contains filtered or unexported methods
}
HarnessEvent is the sealed union of ephemeral engine events delivered to Observers (ADR-0008). Distinct from canonical records (durable) and from agent-core's per-prompt events (which the engine consumes).
type InboundKind ¶
type InboundKind string
InboundKind discriminates the two DispatchMessage kinds (ADR-0005).
const ( InboundUser InboundKind = "user" InboundSignal InboundKind = "signal" )
The two inbound kinds. User is a direct 1:1 exchange with the agent's principal; Signal is one participant's activity in a multi-party conversation the agent participates in.
type InstanceID ¶
type InstanceID string
InstanceID identifies one durable agent instance, addressed /agents/{name}/{id}. Instances are materialized on first dispatch and exist only in the stores.
type Interceptor ¶
Interceptor is onion middleware wrapped around every operation boundary — submission attempt, session operation, model turn, tool execution — so trace context propagates through context.Context natively. Interceptors compose in registration order (the first registered is outermost); an interceptor that returns without calling next aborts the operation and the error is accounted like any attempt failure. This pair of seams is the whole observability surface: the future OTel adapter is built on Observer + Interceptor with no engine changes (ADR-0008).
type LeaseRenewal ¶
LeaseRenewal carries the parameters of a heartbeat: the owning attempt and its new lease expiry.
type MessagePayload ¶
type MessagePayload struct {
Role string `json:"role"`
Type string `json:"type"`
Body json.RawMessage `json:"body,omitempty"`
}
MessagePayload is the harness wire form of an agent-core message. The record schema owns its JSON shape; conversion to and from pi.Message happens at the projection boundary.
func (MessagePayload) ToPi ¶
func (m MessagePayload) ToPi() pi.Message
ToPi converts the wire form back into an agent-core message.
type Observer ¶
type Observer func(HarnessEvent)
Observer receives HarnessEvents synchronously. Observers are read-only and cheap; panics are logged and never affect execution (ADR-0008).
type OpInfo ¶
type OpInfo struct {
Kind OpKind
// Operation is "prompt" or "compact" at the OpOperation boundary.
Operation string
Correlation
// ToolName and CallID are set at the OpTool boundary.
ToolName string
CallID string
}
OpInfo describes the boundary an Interceptor wraps, with the same correlation ids as record envelopes.
type OperationEndedEvent ¶
type OperationEndedEvent struct {
Correlation
Operation string
Err string
}
OperationEndedEvent closes an OperationStartedEvent; Err is "" on success.
type OperationStartedEvent ¶
type OperationStartedEvent struct {
Correlation
Operation string
}
OperationStartedEvent and OperationEndedEvent bound one session operation ("prompt" or "compact").
type OrphanPolicy ¶ added in v0.6.0
type OrphanPolicy int
OrphanPolicy selects what happens to live children when a parent settles terminally (v1 offers only CancelChildren).
const ( // CancelChildren cancels a parent's live children when it settles. CancelChildren OrphanPolicy = iota )
type ParentRef ¶ added in v0.6.0
type ParentRef struct {
ConversationID string `json:"conversationId"`
SpawnRecordID string `json:"spawnRecordId"`
}
ParentRef is the upward link on a child conversation.
type Record ¶
type Record struct {
RecordEnvelope
Payload json.RawMessage `json:"payload,omitempty"`
}
Record is one append-only entry in the durable conversation log. Payload holds the kind-specific body as opaque JSON; use the typed payload accessors to decode it. The JSON encoding of Record is the SSE wire format.
func (Record) DecodePayload ¶
func (r Record) DecodePayload(dst interface{ payloadKind() RecordKind }) error
DecodePayload unmarshals the record payload into dst, which must be a pointer to the payload type matching the record kind.
type RecordEnvelope ¶
type RecordEnvelope struct {
ID string `json:"id"`
Kind RecordKind `json:"kind"`
ConversationID string `json:"conversationId"`
Session string `json:"session"`
SubmissionID string `json:"submissionId,omitempty"`
TurnID string `json:"turnId,omitempty"`
AttemptID string `json:"attemptId,omitempty"`
Time time.Time `json:"time"`
}
RecordEnvelope is the correlation header every canonical record carries. The record ID is a ULID and doubles as the SSE stream offset.
type RecordKind ¶
type RecordKind string
RecordKind identifies the type of a canonical record. The SSE wire format uses the kind as the event name.
const ( KindConversationCreated RecordKind = "conversation_created" KindUserMessage RecordKind = "user_message" KindSignal RecordKind = "signal" KindAssistantMessageStarted RecordKind = "assistant_message_started" KindAssistantTextDelta RecordKind = "assistant_text_delta" KindAssistantThinkingDelta RecordKind = "assistant_thinking_delta" KindAssistantToolCall RecordKind = "assistant_tool_call" KindToolOutcome RecordKind = "tool_outcome" KindAssistantMessageCompleted RecordKind = "assistant_message_completed" KindCompaction RecordKind = "compaction" KindSubmissionSettled RecordKind = "submission_settled" KindTaskSpawned RecordKind = "task_spawned" )
The full v1 record kind set. Later slices author the delta, signal, and compaction kinds; declaring them now pins the schema (ADR-0005/0006).
type RecoveryEvent ¶
type RecoveryEvent struct {
Correlation
// Decision is "overflow_compact_retry", "transient_backoff",
// "dangling_tool_call_reconciled", or one of the "summarization_retry_*"
// lifecycle decisions (scheduled / attempt_start / finished) relayed from
// agent-core's OnSummarizationRetry hook.
Decision string
Detail string
}
RecoveryEvent reports an engine recovery decision.
type ReducedEntry ¶
ReducedEntry is one node of the reduced conversation tree: a canonical record plus its parent link. ParentID is "" for a root entry.
type Runtime ¶
type Runtime struct {
// contains filtered or unexported fields
}
Runtime is the composed harness: agent definitions, store, coordinator, and transport. Construct with NewRuntime, then Start; mount Handler wherever the app wants it.
func NewRuntime ¶
NewRuntime validates cfg and builds a Runtime. The Runtime is inert until Start.
func (*Runtime) Close ¶
Close stops the coordinator and waits for in-flight work to wind down, bounded by a shutdown timeout. Idempotent.
func (*Runtime) Compact ¶
func (rt *Runtime) Compact(ctx context.Context, req CompactRequest) error
Compact runs the manual compaction operation on an idle session: the conversation is summarized via the agent's model and a compaction record lands in the log; the reducer re-parents subsequent prompts onto it.
func (*Runtime) Dispatch ¶
Dispatch admits one unit of work in-process — the same admission path the HTTP transport uses. It returns as soon as the submission is durable.
func (*Runtime) FollowUp ¶
func (rt *Runtime) FollowUp(ctx context.Context, req SteerRequest) error
FollowUp enqueues a message for after the in-flight prompt's current exchange, producing the follow-up exchange within the same submission. Live-only, like Steer.
func (*Runtime) Handler ¶
Handler returns the HTTP transport (ADR-0004). Auth and other middleware are the app's concern; mount this wherever the app wants.
func (*Runtime) Records ¶
func (rt *Runtime) Records(ctx context.Context, conversationID string, afterID string) ([]Record, error)
Records reads the conversation log from afterID (exclusive; "" reads from the start) — the same replay the SSE transport serves.
func (*Runtime) Start ¶
Start launches the coordinator. The supplied ctx bounds the coordinator's lifetime alongside Close.
func (*Runtime) Steer ¶
func (rt *Runtime) Steer(ctx context.Context, req SteerRequest) error
Steer injects a message into the session's in-flight run at agent-core's next safe point (post-tool-batch). Live-only passthrough in v1: with no run in flight it returns ErrNoRunInFlight and persists nothing.
type SessionKey ¶
type SessionKey struct {
Agent string `json:"agent"`
Instance InstanceID `json:"instance"`
Session string `json:"session"`
}
SessionKey addresses one session of one agent instance: agent name / instance id / session name.
func (SessionKey) String ¶
func (k SessionKey) String() string
String renders the key as "agent/instance/session".
type SettledErrorCode ¶
type SettledErrorCode string
SettledErrorCode classifies why a submission settled as failed, stable for programmatic branching; Error carries the human-readable detail.
const ( // SettledErrRunFailed is a terminal error from the agent run itself. SettledErrRunFailed SettledErrorCode = "run_failed" // SettledErrAttemptBudget means the max-attempts durability budget was // exhausted. SettledErrAttemptBudget SettledErrorCode = "attempt_budget_exhausted" // SettledErrTimeout means the submission outlived its durability timeout. SettledErrTimeout SettledErrorCode = "timeout_exceeded" // SettledErrIndeterminate means a crash interrupted settlement before the // terminal record landed; the run's outcome is unknown. SettledErrIndeterminate SettledErrorCode = "settlement_indeterminate" // SettledErrResultInvalid means the structured result never validated // against the requested schema within the feedback budget. SettledErrResultInvalid SettledErrorCode = "result_schema_invalid" // SettledErrCancelled means the submission was cancelled by the orphan // cascade: its parent settled terminally (HARNESS-15). SettledErrCancelled SettledErrorCode = "cancelled_by_parent" )
Failure classifications carried on submission_settled records.
type SettledPayload ¶
type SettledPayload struct {
Status SettledStatus `json:"status"`
Error string `json:"error,omitempty"`
ErrorCode SettledErrorCode `json:"errorCode,omitempty"`
Result json.RawMessage `json:"result,omitempty"`
}
SettledPayload is the payload of a submission_settled record. Result is present only when the prompt requested a structured result.
type SettledStatus ¶
type SettledStatus string
SettledStatus is the terminal outcome carried on a submission_settled record.
const ( SettledSucceeded SettledStatus = "succeeded" SettledFailed SettledStatus = "failed" )
Terminal outcomes of a submission.
type SignalMeta ¶
type SignalMeta struct {
Type string `json:"type"`
Sender map[string]string `json:"sender,omitempty"`
Tag string `json:"tag,omitempty"`
}
SignalMeta carries the signal-specific fields of a DispatchMessage: what kind of activity it was, who sent it, and an optional correlation tag.
type SignalPayload ¶
type SignalPayload struct {
Type string `json:"type"`
Body string `json:"body"`
Sender map[string]string `json:"sender,omitempty"`
Tag string `json:"tag,omitempty"`
}
SignalPayload is the payload of a signal record: one participant's activity in a multi-party conversation the agent participates in (ADR-0005). The sender attributes keep the participant distinguishable from the agent's principal.
type SpawnParent ¶ added in v0.6.0
type SpawnParent struct {
SubmissionID string
CallID string
ConversationID string
// SpawnRecordID is pre-generated by the task tool: it mints the
// spawn record's ULID before dispatching the child, and the
// task_spawned record it appends afterward reuses that same ID.
SpawnRecordID string
Depth int
}
SpawnParent identifies the parent run of a spawned dispatch (HARNESS-15). Set by the task tool; direct callers rarely need it.
type SteerRequest ¶
type SteerRequest struct {
Agent string
Instance InstanceID
Session string // empty means "default"
Body string
}
SteerRequest addresses a live run for Steer and FollowUp: the session key fields plus the message body.
type Store ¶
type Store interface {
SubmissionStore
ConversationStore
AttachmentStore
}
Store is the single narrow persistence contract every backend implements (ADR-0006): one tier, no SQL-only extensions. Every implementation must pass the exported conformance suite in package storetest.
type SubagentLimits ¶ added in v0.6.0
type SubagentLimits struct {
MaxChildrenPerRun int // default 8; excess task calls → immediate error result
MaxDepth int // default 1; the feature is off for agents with no SubagentPolicy entry
MaxWait time.Duration // default 0 = unbounded wait
OnParentTerminal OrphanPolicy // default CancelChildren
}
SubagentLimits bound durable subagent fan-out. Zero values resolve to documented defaults at NewRuntime.
type SubagentPolicy ¶ added in v0.6.0
SubagentPolicy maps an agent definition name to the set of definitions it may spawn via the injected task tool (HARNESS-15). Absent key: no task tool.
type Submission ¶
type Submission struct {
ID string `json:"id"`
SessionKey SessionKey `json:"sessionKey"`
ConversationID string `json:"conversationId"`
Status SubmissionStatus `json:"status"`
Input DispatchMessage `json:"input"`
AttemptCount int `json:"attemptCount"`
AttemptID string `json:"attemptId,omitempty"`
OwnerID string `json:"ownerId,omitempty"`
LeaseExpiresAt time.Time `json:"leaseExpiresAt,omitzero"`
// LastError is the most recent run error recorded when an attempt was
// released for retry. It survives re-claims so a budget-exhaustion
// settlement can name the underlying failure (HARNESS-12).
LastError string `json:"lastError,omitempty"`
CreatedAt time.Time `json:"createdAt"`
// ParentSubmissionID/ParentCallID link a child submission to the task
// call that spawned it (HARNESS-15); empty for root dispatches.
ParentSubmissionID string `json:"parentSubmissionId,omitempty"`
ParentCallID string `json:"parentCallId,omitempty"`
// Depth is the spawn depth (0 for root dispatches; child = parent+1).
Depth int `json:"depth,omitempty"`
// PendingResume marks a submission parked in waiting whose next drive
// must Resume (not Prompt) — set by WaitSubmission, kept by
// ResumeSubmission, consumed by the claim that re-drives it (the claimed
// row carries the flag; the stored row clears it).
PendingResume bool `json:"pendingResume,omitempty"`
// WaitUntil bounds the wait when SubagentLimits.MaxWait is set; zero = unbounded.
WaitUntil time.Time `json:"waitUntil,omitzero"`
// CancelRequested asks the owning coordinator to cancel the attempt at
// the next turn boundary (orphan cascade).
CancelRequested bool `json:"cancelRequested,omitempty"`
}
Submission is the durable record of one admitted dispatch — the unit of leasing, attempts, and settlement. Its ID is the dispatch id and therefore the idempotency key.
type SubmissionAdmittedEvent ¶
type SubmissionAdmittedEvent struct {
Correlation
Input DispatchMessage
}
SubmissionAdmittedEvent reports a durably admitted submission.
type SubmissionClaim ¶
type SubmissionClaim struct {
SubmissionID string
AttemptID string
OwnerID string
LeaseExpiresAt time.Time
}
SubmissionClaim carries the parameters of a claim CAS: the submission to move queued→running and the attempt taking ownership.
type SubmissionClaimedEvent ¶
type SubmissionClaimedEvent struct {
Correlation
OwnerID string
AttemptCount int
}
SubmissionClaimedEvent reports a claim CAS that took ownership.
type SubmissionRelease ¶
SubmissionRelease carries the parameters of a release CAS: the owning attempt giving the submission back to the queue, and optionally the run error that caused it. A non-empty LastError overwrites the submission's stored last error; empty preserves it (a shutdown or lease-reclaim release is not a model failure and must not erase the real one).
type SubmissionResumedEvent ¶ added in v0.6.0
type SubmissionResumedEvent struct{ Correlation }
SubmissionResumedEvent reports a waiting submission requeued by a wake.
type SubmissionSettledEvent ¶
type SubmissionSettledEvent struct {
Correlation
Payload SettledPayload
}
SubmissionSettledEvent reports terminal settlement.
type SubmissionSpawnedEvent ¶ added in v0.6.0
type SubmissionSpawnedEvent struct {
Correlation // the PARENT's correlation
ChildSubmissionID string
ChildConversationID string
Agent string
CallID string
}
SubmissionSpawnedEvent reports a durable child admission (HARNESS-15). May fire once per attempt for the same call (replay); dedupe on ChildSubmissionID.
type SubmissionStatus ¶
type SubmissionStatus string
SubmissionStatus is the durable lifecycle state of a submission: queued → running → waiting → running → terminalizing → settled.
const ( StatusQueued SubmissionStatus = "queued" StatusRunning SubmissionStatus = "running" StatusWaiting SubmissionStatus = "waiting" // suspended on child submissions; no lease held StatusTerminalizing SubmissionStatus = "terminalizing" StatusSettled SubmissionStatus = "settled" )
Submission lifecycle states.
type SubmissionStore ¶
type SubmissionStore interface {
// AdmitSubmission durably admits sub. Re-admitting the same ID with an
// identical Input returns the previously stored submission; a different
// Input returns ErrDispatchConflict.
AdmitSubmission(ctx context.Context, sub Submission) (Submission, error)
// GetSubmission returns the submission by id, or ErrSubmissionNotFound.
GetSubmission(ctx context.Context, id string) (Submission, error)
// ListRunnable returns, per session key, the oldest unsettled submission
// — and only when it is claimable (queued). A session whose head is
// running, terminalizing, or reserved is busy and contributes nothing.
ListRunnable(ctx context.Context) ([]Submission, error)
// ListByStatus returns every submission in the given status, in
// admission order. Reconciliation uses it to find interrupted work.
ListByStatus(ctx context.Context, status SubmissionStatus) ([]Submission, error)
// ClaimSubmission atomically moves the submission queued→running,
// recording the attempt id, owner, and lease expiry, and incrementing
// AttemptCount. It returns ErrClaimLost when the submission is not
// queued. The claim consumes PendingResume: the returned row carries it
// (the drive branches Resume vs Prompt on it) while the stored row
// clears it. A resume claim (PendingResume set) does NOT increment
// AttemptCount: a resume re-drives a parked parent, not a failed
// attempt, so it never consumes the failure-attempt budget (and
// transientBackoff, which keys off AttemptCount, only ever reflects
// real failures).
ClaimSubmission(ctx context.Context, claim SubmissionClaim) (Submission, error)
// StartAttempt durably records the attempt marker. It is written after a
// successful claim and before any work.
StartAttempt(ctx context.Context, attempt Attempt) error
// ListAttempts returns the attempt markers of a submission in start
// order.
ListAttempts(ctx context.Context, submissionID string) ([]Attempt, error)
// RenewLease extends the lease of a running submission. It returns
// ErrClaimLost when the submission is not running or is owned by a
// different attempt.
RenewLease(ctx context.Context, renewal LeaseRenewal) error
// ListExpiredLeases returns running submissions whose lease expired at or
// before now.
ListExpiredLeases(ctx context.Context, now time.Time) ([]Submission, error)
// ReleaseSubmission moves the submission running→queued so a fresh
// attempt can claim it, recording release.LastError when non-empty (see
// SubmissionRelease). It returns ErrClaimLost when the submission is
// not running or is owned by a different attempt.
ReleaseSubmission(ctx context.Context, release SubmissionRelease) error
// WaitSubmission CAS-transitions running→waiting, releasing the lease.
// ErrClaimLost when the attempt no longer owns the submission.
WaitSubmission(ctx context.Context, wait SubmissionWait) error
// ResumeSubmission CAS-transitions waiting→queued (a wake landed).
// PendingResume survives the requeue; the claim that re-drives the
// submission consumes it.
ResumeSubmission(ctx context.Context, submissionID string) error
// ListChildSubmissions returns submissions spawned by parentSubmissionID.
ListChildSubmissions(ctx context.Context, parentSubmissionID string) ([]Submission, error)
// ListExpiredWaits returns waiting submissions with WaitUntil before now.
ListExpiredWaits(ctx context.Context, now time.Time) ([]Submission, error)
// CancelSubmission transitions a queued or waiting submission straight to
// settled (no attempt ever completes it), recording reason into
// LastError, and reports wasRunning=false. A running submission instead
// gets CancelRequested=true and wasRunning=true with no status change —
// the owning coordinator cancels the run context and settles it. Cancel
// against a terminalizing or settled submission returns ErrClaimLost
// (already terminal).
CancelSubmission(ctx context.Context, submissionID, reason string) (wasRunning bool, err error)
// ReserveSettlement atomically moves the submission
// running→terminalizing — phase one of settlement. It returns
// ErrClaimLost when the submission is not running or is owned by a
// different attempt.
ReserveSettlement(ctx context.Context, submissionID, attemptID string) error
// FinalizeSettlement moves the submission terminalizing→settled — phase
// two. It is idempotent: finalizing an already-settled submission is a
// no-op, so a crash between the phases resolves cleanly on retry.
FinalizeSettlement(ctx context.Context, submissionID string) error
}
SubmissionStore is the durable submission half of the store contract. Implementations must make AdmitSubmission idempotent by submission ID and every state transition an atomic CAS on the expected prior state.
type SubmissionWait ¶ added in v0.6.0
type SubmissionWait struct {
SubmissionID string
AttemptID string
WaitUntil time.Time // zero = unbounded
}
SubmissionWait carries the parameters of a wait CAS: the submission to move running→waiting (HARNESS-15 suspension) and the optional wait bound.
type SubmissionWaitingEvent ¶ added in v0.6.0
type SubmissionWaitingEvent struct{ Correlation }
SubmissionWaitingEvent reports a submission suspending into waiting.
type TaskSpawnedPayload ¶ added in v0.6.0
type TaskSpawnedPayload struct {
CallID string `json:"callId"`
Agent string `json:"agent"`
ChildInstance string `json:"childInstance"`
ChildConversationID string `json:"childConversationId"`
ChildSubmissionID string `json:"childSubmissionId"`
Prompt string `json:"prompt"`
}
TaskSpawnedPayload is the payload of a task_spawned record: a parent run admitted a durable child submission for the named task call (HARNESS-15).
type TextDeltaPayload ¶
type TextDeltaPayload struct {
Text string `json:"text"`
}
TextDeltaPayload is the payload of an assistant_text_delta record: one batched fragment of streamed assistant text.
type ThinkingDeltaPayload ¶
type ThinkingDeltaPayload struct {
Text string `json:"text"`
}
ThinkingDeltaPayload is the payload of an assistant_thinking_delta record: one batched fragment of streamed assistant thinking.
type ToolCallEndedEvent ¶
type ToolCallEndedEvent struct {
Correlation
CallID string
ToolName string
IsError bool
}
ToolCallEndedEvent closes a ToolCallStartedEvent.
type ToolCallStartedEvent ¶
type ToolCallStartedEvent struct {
Correlation
CallID string
ToolName string
}
ToolCallStartedEvent and ToolCallEndedEvent bound one tool execution.
type ToolCallUpdatedEvent ¶ added in v0.3.0
type ToolCallUpdatedEvent struct {
Correlation
CallID string
ToolName string
Result pi.ToolResult
}
ToolCallUpdatedEvent reports a partial-result snapshot from a running tool. Ephemeral: observer-only, never recorded.
type ToolOutcomePayload ¶
type ToolOutcomePayload struct {
CallID string `json:"callId"`
ToolName string `json:"toolName"`
Content string `json:"content,omitempty"`
Data json.RawMessage `json:"data,omitempty"`
IsError bool `json:"isError,omitempty"`
}
ToolOutcomePayload is the payload of a tool_outcome record. It carries the full pi.ToolResult in wire form, correlated to its assistant_tool_call by CallID.
type TurnEndedEvent ¶
type TurnEndedEvent struct {
Correlation
Turn int
}
TurnEndedEvent closes a TurnStartedEvent.
type TurnStartedEvent ¶
type TurnStartedEvent struct {
Correlation
Turn int
}
TurnStartedEvent and TurnEndedEvent bound one pi.Agent LLM round-trip.
type UserMessagePayload ¶
type UserMessagePayload struct {
Body string `json:"body"`
Attachments []AttachmentRef `json:"attachments,omitempty"`
}
UserMessagePayload is the payload of a user_message record.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
basic
command
Command basic is the runnable end-to-end example for resolute-harness-go: one agent definition with per-instance setup, a SQLite store, a logging Observer, a timing Interceptor, and one real tool, served over HTTP.
|
Command basic is the runnable end-to-end example for resolute-harness-go: one agent definition with per-instance setup, a SQLite store, a logging Observer, a timing Interceptor, and one real tool, served over HTTP. |
|
chat
command
Command chat is the browser example for resolute-harness-go: a single Go binary serving an embedded HTML chat page over the harness's own HTTP surface — no npm, no build step, no external assets.
|
Command chat is the browser example for resolute-harness-go: a single Go binary serving an embedded HTML chat page over the harness's own HTTP surface — no npm, no build step, no external assets. |
|
coder
command
Command coder is the coding-assistant example for resolute-harness-go: one agent wired to the four built-in execution tools (read, write, edit, bash) from resolute-agent-core-go's tools package, rooted at a workspace directory, with a stdout observer that narrates tool activity — including a running bash command's partial output — as it happens.
|
Command coder is the coding-assistant example for resolute-harness-go: one agent wired to the four built-in execution tools (read, write, edit, bash) from resolute-agent-core-go's tools package, rooted at a workspace directory, with a stdout observer that narrates tool activity — including a running bash command's partial output — as it happens. |
|
github-bot
command
Command github-bot is the channel example for resolute-harness-go: verified GitHub webhook ingress translated into signal dispatches, with delivery-id idempotency and one narrow application-owned tool that posts the agent's reply back to the issue.
|
Command github-bot is the channel example for resolute-harness-go: verified GitHub webhook ingress translated into signal dispatches, with delivery-id idempotency and one narrow application-owned tool that posts the agent's reply back to the issue. |
|
multitenant
command
Command multitenant is the concurrency-model example for resolute-harness-go: one agent definition serving many tenants, where the instance id picks the tenant (per-instance system prompts via Initialize) and sessions inside an instance give independent, durably ordered conversations.
|
Command multitenant is the concurrency-model example for resolute-harness-go: one agent definition serving many tenants, where the instance id picks the tenant (per-instance system prompts via Initialize) and sessions inside an instance give independent, durably ordered conversations. |
|
scheduler
command
Command scheduler is the time-driven example for resolute-harness-go: an in-process ticker fires scheduled signal dispatches into a durable conversation, and deterministic per-window dispatch ids make the schedule idempotent — a killed-and-restarted process re-fires the current window's dispatch and the store deduplicates it, so nothing runs twice.
|
Command scheduler is the time-driven example for resolute-harness-go: an in-process ticker fires scheduled signal dispatches into a durable conversation, and deterministic per-window dispatch ids make the schedule idempotent — a killed-and-restarted process re-fires the current window's dispatch and the store deduplicates it, so nothing runs twice. |
|
triage
command
Command triage is the structured-results example for resolute-harness-go: a bug-triage endpoint where the dispatch carries a resultSchema, the harness validates the run's final answer against it, and the corrective retry loop is visible in the record stream.
|
Command triage is the structured-results example for resolute-harness-go: a bug-triage endpoint where the dispatch carries a resultSchema, the harness validates the run's final answer against it, and the corrective retry loop is visible in the record stream. |
|
Package memory provides the in-memory Store used by tests and embedded runs.
|
Package memory provides the in-memory Store used by tests and embedded runs. |
|
Package sqlite provides the batteries-included durable Store (modernc.org/sqlite — pure Go, no cgo, per ADR-0006).
|
Package sqlite provides the batteries-included durable Store (modernc.org/sqlite — pure Go, no cgo, per ADR-0006). |
|
Package storetest is the exported conformance suite for the harness store contract (ADR-0006).
|
Package storetest is the exported conformance suite for the harness store contract (ADR-0006). |