agentruntime

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 10, 2026 License: MIT Imports: 26 Imported by: 0

README

agent-go

CI Go Reference

Status: agent-go is pre-1.0. The public API may change between minor versions while the runtime contracts are refined.

agent-go is an embeddable Go runtime for agents built on the OpenAI Responses API. It owns the model/tool loop while the host application keeps control of authorization, approvals, persistence, side effects, verification, and domain behavior through explicit interfaces.

The project is intended for applications that need production-oriented tool execution semantics without adopting an HTTP server, database, queue, UI, or product framework from the runtime.

Why agent-go

  • Embed a complete streaming model/tool loop in an existing Go application.
  • Expose JSON Schema-validated operation contracts to the model through an in-process MCP server.
  • Keep policy, human approval, execution, and independent verification under host control.
  • Resume approvals and stateful conversations without giving the model authority over persisted state.
  • Protect writes with durable plans, idempotent execution records, session leases, fencing, and reconciliation.
  • Observe the runtime through structured events without coupling it to an application transport or storage implementation.

agent-go deliberately does not provide application handlers, database implementations, queue workers, built-in domain tools, billing rules, product prompts, or a remote MCP client.

Architecture and trust boundaries

flowchart LR
    Host["Host application"] --> Runtime["agent-go Runtime"]
    Runtime <--> Model["OpenAI Responses API"]
    Runtime --> MCP["In-process MCP tool catalog"]
    MCP --> Policy["Host policy"]
    Policy -->|allow| Execute["Host executor"]
    Policy -->|require approval| Approve["Host approval"]
    Approve --> Execute
    Execute -->|when required| Verify["Host verifier"]
    Runtime <--> Runs["RunStore"]
    Runtime <--> Executions["ExecutionStore"]
    Executions --> Reconcile["OperationReconciler"]

MCP discovery only exposes operation contracts to the model; it never grants permission. Every operation is evaluated by host policy before execution. A confirmation-required write cannot complete successfully without a positive verifier result.

Runtime owns Host application owns
Model iteration and OpenAI event mapping API keys, model selection, and product instructions
In-process MCP discovery and JSON Schema validation Authorization and capability policy
Approval pause/resume orchestration Approval UI and approval decisions
Transcript, lease, plan, and execution state transitions Durable RunStore and ExecutionStore implementations
Verification and reconciliation orchestration Side effects, receipts, verification logic, and reconciliation decisions
Context-window and attachment protocols Domain data, attachment resolution, and trusted external context

Core concepts

Type Purpose
Model / OpenAIModel Streams model output into the runtime's provider-neutral event contracts.
OperationRegistry / Operation Defines immutable operation names, schemas, effects, capabilities, and confirmation requirements.
OperationPolicy Allows, denies, or routes each proposed operation through approval.
OperationExecutor Performs the host-owned side effect or read and returns schema-validated output.
Approver / ApprovalResumer Requests approval and resumes a previously paused run.
ResultVerifier Independently confirms the result of confirmation-required operations.
RunStore Persists sessions and serializes stateful runs with renewable, generation-fenced leases.
ExecutionStore Persists sealed write plans, idempotent execution records, and append-only transitions.
OperationReconciler Settles uncertain persisted writes without starting a model run.
ContextWindowConfig / EventSink Controls transcript compaction and observes structured runtime events.

Install

go get github.com/ly95/agent-go@latest

The module requires Go 1.26 or newer.

Quick start

Set the credentials and model used by the OpenAI Responses API:

export OPENAI_API_KEY="..."
export OPENAI_MODEL="your-model-name"

Then create and run a stateless agent:

package main

import (
	"context"
	"fmt"
	"os"

	agentruntime "github.com/ly95/agent-go"
)

func main() {
	model, err := agentruntime.NewOpenAIModel(agentruntime.OpenAIModelConfig{
		APIKey:  os.Getenv("OPENAI_API_KEY"),
		BaseURL: "https://api.openai.com/v1",
		Model:   os.Getenv("OPENAI_MODEL"),
	})
	if err != nil {
		panic(err)
	}

	runtime, err := agentruntime.NewRuntime(agentruntime.RuntimeConfig{Model: model})
	if err != nil {
		panic(err)
	}

	result, err := runtime.Run(context.Background(), agentruntime.Input{
		User: "Explain why the sky is blue in one paragraph.",
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(result.Output)
}

Operation requirements

The runtime validates required dependencies when it is constructed:

Configuration Required host dependencies
No registered operations Model only
Any registered operation OperationPolicy and OperationExecutor
Any write operation ExecutionStore in addition to policy and executor
ConfirmationRequired operation ResultVerifier; approval flows also use Approver and ApprovalResumer
Stateful session RunStore

Hosts should use stable, tenant-scoped idempotency keys for retried requests, build approval previews that reveal only safe structured data, and implement the execution-attempt fence atomically with the external write. Reconcile unresolved write records before allowing unrelated conversation state to hide them.

Examples

Runnable examples live in examples:

Example Demonstrates
basic A stateless agent without tools
mcp A read-only operation exposed through the runtime's in-process MCP server
skill A reusable host-side Skill composition pattern

The examples intentionally keep their side effects read-only. Production write operations require the durable execution, approval, and verification boundaries described above.

Compatibility and guarantees

  • OpenAIModel targets the OpenAI Responses API. BaseURL is configurable, but compatibility with non-OpenAI implementations is not guaranteed.
  • MCP support is currently an in-process operation-discovery boundary, not a client for arbitrary remote MCP servers.
  • Invalid configuration, unsupported provider output, missing resources, and ambiguous execution outcomes fail explicitly.
  • The runtime does not silently retry, downgrade, truncate, or substitute a caller choice.
  • Operation contracts are frozen when the runtime is constructed; persisted write plans and execution transitions are treated as immutable history.

Development

go test ./...
go vet ./...

See CONTRIBUTING.md before proposing changes. Report vulnerabilities according to SECURITY.md, not through a public issue.

License

agent-go is available under the MIT License.

Documentation

Overview

Package agentruntime provides a business-neutral agent runtime.

The runtime treats the LLM as the control loop and discovers executable tools through MCP. MCP discovery never grants permission: host applications inject policy, approval, operation execution, and independent result-verification boundaries. Hosts decide whether a write requires confirmation; confirmed writes cannot complete without a successful verifier result. RunStore serializes stateful session runs with expiring, renewable, generation-fenced leases. ExecutionStore seals idempotent write plans and keeps append-only execution transition history, including executed results awaiting verification. The package deliberately contains no application business behavior; hosts supply capabilities through narrow interfaces.

Index

Constants

View Source
const MaxModelTextAttachmentBytes = 200_000
View Source
const MaxResultArtifactSessionSummaryBytes = 8 * 1024

MaxResultArtifactSessionSummaryBytes bounds one host-provided artifact projection and the complete historical record Runtime persists from it.

Variables

View Source
var (
	ErrInvalidModelOutput         = errors.New("agent: invalid model output")
	ErrOperationNotFound          = errors.New("agent: operation not found")
	ErrOperationDenied            = errors.New("agent: operation denied")
	ErrExecutionStoreRequired     = errors.New("agent: execution store is required")
	ErrOperationExecutionNotFound = errors.New("agent: operation execution not found")
	ErrOperationPlanChanged       = errors.New("agent: operation plan changed during retry")
	ErrOperationAttemptLost       = errors.New("agent: operation execution attempt lost ownership")
	ErrInvalidExecutionTransition = errors.New("agent: invalid operation execution transition")
	ErrInvalidReconciliation      = errors.New("agent: invalid operation reconciliation")
	ErrIdempotencyKeyRequired     = errors.New("agent: idempotency key is required")
	ErrIdempotencyScopeRequired   = errors.New("agent: idempotency scope is required for stateless writes")
	ErrOperationNotApplied        = errors.New("agent: operation was definitely not applied")
	ErrOperationOutcomeUnknown    = errors.New("agent: operation outcome is unknown")
	ErrApprovalRequired           = errors.New("agent: operation approval required")
	ErrApprovalPending            = errors.New("agent: operation approval pending")
	ErrApprovalDenied             = errors.New("agent: operation approval denied")
	ErrVerifierRequired           = errors.New("agent: result verifier required")
	ErrVerificationFailed         = errors.New("agent: result verification failed")
	ErrMaxIterations              = errors.New("agent: max iterations reached")
	ErrSessionNotFound            = errors.New("agent: session not found")
	ErrSessionConflict            = errors.New("agent: session revision conflict")
	ErrSessionBusy                = errors.New("agent: session already has an active run")
	ErrSessionLeaseLost           = errors.New("agent: session lease ownership lost")
	ErrSessionStoreNeeded         = errors.New("agent: session store is required")
	ErrContextLimitExceeded       = errors.New("agent: context limit exceeded")
	ErrContextCompactionFailed    = errors.New("agent: context compaction failed")
	ErrImageAttachmentUnavailable = errors.New("agent: image attachment unavailable")
	ErrInsufficientCredits        = errors.New("agent: insufficient credits")
	ErrRunInterrupted             = errors.New("agent: run interrupted")
	ErrRunCancelled               = errors.New("agent: run cancelled")
)

Functions

func MarkOperationNotApplied

func MarkOperationNotApplied(cause error) error

MarkOperationNotApplied lets a write executor prove that it failed before reaching its side-effect commit boundary. Runtime may safely make that execution retryable without entering ambiguous-outcome recovery.

func RenderTextAttachment

func RenderTextAttachment(attachment ModelInputAttachment) (string, error)

func ValidateImageAttachment

func ValidateImageAttachment(attachment ModelInputAttachment) error

func ValidateModelInputAttachment

func ValidateModelInputAttachment(attachment ModelInputAttachment) error

Types

type AcquireExecutionRequest

type AcquireExecutionRequest struct {
	Execution  OperationExecutionRecord
	Transition OperationExecutionTransition
}

func (AcquireExecutionRequest) Validate

func (request AcquireExecutionRequest) Validate() error

type AcquireExecutionResult

type AcquireExecutionResult struct {
	Execution   OperationExecutionRecord
	Disposition ExecutionAcquireDisposition
}

type ApprovalDecision

type ApprovalDecision struct {
	ID       string `json:"id,omitempty"`
	Approved bool   `json:"approved"`
	Pending  bool   `json:"pending,omitempty"`
	Reason   string `json:"reason,omitempty"`
}

type ApprovalRequest

type ApprovalRequest struct {
	Operation   OperationRequest
	Reason      string
	ResponseID  string
	ModelOutput []ModelOutputItem
	Preview     json.RawMessage
}

type ApprovalResume

type ApprovalResume struct {
	ID          string
	ExecutionID string
	Operation   string
	Call        ToolCall
	ResponseID  string
	ModelOutput []ModelOutputItem
	Preview     json.RawMessage
	Pending     bool
	Approved    bool
	Reason      string
}

type ApprovalResumer

type ApprovalResumer interface {
	ResumeApproval(ctx context.Context, runID string) (*ApprovalResume, error)
}

type Approver

type Approver interface {
	RequestApproval(ctx context.Context, req ApprovalRequest) (ApprovalDecision, error)
}

type ApproverFunc

type ApproverFunc func(ctx context.Context, req ApprovalRequest) (ApprovalDecision, error)

func (ApproverFunc) RequestApproval

func (f ApproverFunc) RequestApproval(ctx context.Context, req ApprovalRequest) (ApprovalDecision, error)

type BeginRunRequest

type BeginRunRequest struct {
	Run      RunRecord
	LeaseID  string
	LeaseTTL time.Duration
}

type BeginRunResult

type BeginRunResult struct {
	Handle  RunHandle
	Session *SessionState
}

type ConfirmationMode

type ConfirmationMode string
const (
	ConfirmationNone     ConfirmationMode = "none"
	ConfirmationRequired ConfirmationMode = "required"
)

type ConfirmationSpec

type ConfirmationSpec struct {
	Mode        ConfirmationMode `json:"mode"`
	Description string           `json:"description,omitempty"`
}

type ContextCheckpoint

type ContextCheckpoint struct {
	Version               int            `json:"version"`
	Summary               ContextSummary `json:"summary"`
	CompactedItemCount    int            `json:"compacted_item_count"`
	SourceSessionRevision uint64         `json:"source_session_revision"`
	UpdatedAt             time.Time      `json:"updated_at"`
}

type ContextCompactionRequest

type ContextCompactionRequest struct {
	Checkpoint            *ContextCheckpoint `json:"checkpoint,omitempty"`
	Items                 []ModelInputItem   `json:"items"`
	SourceSessionRevision uint64             `json:"source_session_revision"`
	MaxCheckpointTokens   int                `json:"max_checkpoint_tokens"`
}

type ContextCompactor

type ContextCompactor interface {
	Compact(ctx context.Context, request ContextCompactionRequest) (ContextSummary, error)
}

ContextCompactor replaces an older transcript prefix and any prior checkpoint with one structured summary. Implementations may use any host-selected model.

type ContextSummary

type ContextSummary struct {
	Summary     string   `json:"summary"`
	Facts       []string `json:"facts,omitempty"`
	Decisions   []string `json:"decisions,omitempty"`
	Constraints []string `json:"constraints,omitempty"`
	OpenItems   []string `json:"open_items,omitempty"`
}

type ContextWindowConfig

type ContextWindowConfig struct {
	MaxContextTokens        int
	ReservedOutputTokens    int
	CompactionTriggerTokens int
	CompactionTargetTokens  int
	MaxCheckpointTokens     int
	PreserveRecentTurns     int
	TokenCounter            TokenCounter
	ContextCompactor        ContextCompactor
}

ContextWindowConfig enables explicit model-input accounting and compaction. Every field is required when RuntimeConfig.ContextWindow is non-nil.

type Event

type Event struct {
	Type            EventType         `json:"type"`
	RunID           string            `json:"run_id"`
	SessionID       string            `json:"session_id,omitempty"`
	MCPServer       string            `json:"mcp_server,omitempty"`
	MCPVersion      string            `json:"mcp_version,omitempty"`
	MCPProtocol     string            `json:"mcp_protocol,omitempty"`
	MCPToolCount    int               `json:"mcp_tool_count,omitempty"`
	Operation       string            `json:"operation,omitempty"`
	ModelCallID     string            `json:"model_call_id,omitempty"`
	RequestID       string            `json:"request_id,omitempty"`
	PlanBatch       uint64            `json:"plan_batch"`
	CallID          string            `json:"call_id,omitempty"`
	ExecutionID     string            `json:"execution_id,omitempty"`
	ApprovalID      string            `json:"approval_id,omitempty"`
	ApprovalPreview json.RawMessage   `json:"approval_preview,omitempty"`
	AttemptID       string            `json:"attempt_id,omitempty"`
	ResponseID      string            `json:"response_id,omitempty"`
	Text            string            `json:"text,omitempty"`
	InputTokens     int               `json:"input_tokens,omitempty"`
	CompactedItems  int               `json:"compacted_items,omitempty"`
	Chunk           *ModelStreamEvent `json:"chunk,omitempty"`
	// Data is trusted audit payload and never crosses the default JSON boundary.
	Data      json.RawMessage `json:"-"`
	ErrorCode string          `json:"error_code,omitempty"`
	Error     string          `json:"-"`
}

type EventSink

type EventSink func(Event)

type EventType

type EventType string
const (
	EventRunStarted                 EventType = "run_started"
	EventModelStarted               EventType = "model_started"
	EventModelStreamChunk           EventType = "model_stream_chunk"
	EventModelCompleted             EventType = "model_completed"
	EventModelFailed                EventType = "model_failed"
	EventContextCompactionStarted   EventType = "context_compaction_started"
	EventContextCompactionCompleted EventType = "context_compaction_completed"
	EventContextCompactionFailed    EventType = "context_compaction_failed"
	EventMCPConnected               EventType = "mcp_connected"
	EventOperationPlanReserved      EventType = "operation_plan_reserved"
	EventOperationPlanRejected      EventType = "operation_plan_rejected"
	EventOperationPlanSealed        EventType = "operation_plan_sealed"
	EventOperationRequested         EventType = "operation_requested"
	EventOperationStarted           EventType = "operation_started"
	EventOperationCompleted         EventType = "operation_completed"
	EventOperationCancelled         EventType = "operation_cancelled"
	EventOperationFailed            EventType = "operation_failed"
	EventVerificationStarted        EventType = "verification_started"
	EventVerificationCompleted      EventType = "verification_completed"
	EventVerificationFailed         EventType = "verification_failed"
	EventApprovalRequested          EventType = "approval_requested"
	EventApprovalCompleted          EventType = "approval_completed"
	EventApprovalFailed             EventType = "approval_failed"
	EventRunWaitingUser             EventType = "run_waiting_user"
	EventRunCompleted               EventType = "run_completed"
	EventRunFailed                  EventType = "run_failed"
	EventRunInterrupted             EventType = "run_interrupted"
	EventRunCancelled               EventType = "run_cancelled"
)

type ExecutionAcquireDisposition

type ExecutionAcquireDisposition string
const (
	ExecutionAcquired ExecutionAcquireDisposition = "acquired"
	ExecutionReplay   ExecutionAcquireDisposition = "replay"
	ExecutionBlocked  ExecutionAcquireDisposition = "blocked"
)

type ExecutionStore

type ExecutionStore interface {
	ReservePlanBatch(ctx context.Context, batch OperationPlanBatch) (PlanBatchReservation, error)
	SealPlan(ctx context.Context, seal OperationPlanSeal) (PlanSealResult, error)
	AcquireExecution(ctx context.Context, request AcquireExecutionRequest) (AcquireExecutionResult, error)
	ValidateExecutionAttempt(ctx context.Context, executionID, attemptID string) error
	TransitionExecution(ctx context.Context, transition OperationExecutionTransition) (OperationExecutionRecord, error)
	GetExecution(ctx context.Context, executionID string) (OperationExecutionRecord, error)
	ListExecutionTransitions(ctx context.Context, executionID string) ([]OperationExecutionTransition, error)
}

ExecutionStore owns durable write plans and write-operation state. ReservePlanBatch preserves the first batch at each index and rejects new batches after SealPlan. AcquireExecution and TransitionExecution atomically update the current record and append an immutable transition. ValidateExecutionAttempt rejects owners fenced by reconciliation or retry; write executors must still perform the same check atomically with their external side effect.

type FinishRunRequest

type FinishRunRequest struct {
	Handle          RunHandle
	Run             RunRecord
	Session         *SessionState
	PendingApproval *PendingApprovalCommit
}

type ImageAttachmentResolver

type ImageAttachmentResolver interface {
	// Retryable infrastructure failures must wrap ErrRunInterrupted. Confirmed
	// expiry or deletion must wrap ErrImageAttachmentUnavailable.
	ResolveImageAttachment(ctx context.Context, attachment ModelInputAttachment) (ModelInputAttachment, error)
}

type ImageAttachmentResolverFunc

type ImageAttachmentResolverFunc func(context.Context, ModelInputAttachment) (ModelInputAttachment, error)

func (ImageAttachmentResolverFunc) ResolveImageAttachment

func (f ImageAttachmentResolverFunc) ResolveImageAttachment(ctx context.Context, attachment ModelInputAttachment) (ModelInputAttachment, error)

type Input

type Input struct {
	// RunID is an optional trusted host-assigned identifier. Durable hosts that
	// enqueue work before execution use it to keep the HTTP, queue, store, and
	// event identities aligned. It is intentionally excluded from JSON input so
	// callers cannot smuggle an arbitrary run identity through an API payload.
	RunID     string `json:"-"`
	User      string `json:"user"`
	SessionID string `json:"session_id,omitempty"`
	// IdempotencyKey identifies one logical user request. Callers must reuse it
	// when retrying a request that may execute write operations.
	IdempotencyKey string `json:"idempotency_key,omitempty"`
	// IdempotencyScope isolates stateless write keys by trusted tenant or
	// principal. It is required for write operations without a SessionID.
	IdempotencyScope string                 `json:"idempotency_scope,omitempty"`
	Attachments      []ModelInputAttachment `json:"attachments,omitempty"`
	Metadata         map[string]any         `json:"metadata,omitempty"`
	// ImageAttachmentResolver is a trusted, Run-scoped dependency used to
	// materialize transient URLs for historical image attachments. It is never
	// accepted from callers or persisted with the Run input.
	ImageAttachmentResolver ImageAttachmentResolver `json:"-"`
	// TrustedContext is host-authored, current external state that must be
	// available to the model for this Run but must not be accepted from API
	// callers or persisted as a user-authored transcript message.
	TrustedContext string `json:"-"`
}

type ItemRecord

type ItemRecord struct {
	ID             string
	RunID          string
	SessionID      string
	Type           ItemType
	ModelCallID    string
	ResponseID     string
	ProviderItemID string
	RequestID      string
	PlanBatch      uint64
	CallID         string
	ExecutionID    string
	AttemptID      string
	Name           string
	Data           json.RawMessage
	Error          string
	CreatedAt      time.Time
}

type ItemType

type ItemType string
const (
	ItemTypeUserMessage       ItemType = "user_message"
	ItemTypeModelRequest      ItemType = "model_request"
	ItemTypeModelResponse     ItemType = "model_response"
	ItemTypeOperationPlan     ItemType = "operation_plan"
	ItemTypeOperationCall     ItemType = "operation_call"
	ItemTypeOperationResult   ItemType = "operation_result"
	ItemTypeVerification      ItemType = "verification"
	ItemTypeApproval          ItemType = "approval"
	ItemTypeError             ItemType = "error"
	ItemTypeContextCheckpoint ItemType = "context_checkpoint"
)

type MCPServerInfo

type MCPServerInfo struct {
	Name            string
	Version         string
	ProtocolVersion string
}

type Model

type Model interface {
	Complete(ctx context.Context, req ModelRequest) (*ModelResponse, error)
}

Model executes one native model turn. Input is the complete local transcript; implementations must not depend on provider-side response storage. Requests and their slices are immutable for the duration of Complete.

type ModelInputAttachment

type ModelInputAttachment struct {
	Kind       ModelInputAttachmentKind `json:"kind"`
	ID         string                   `json:"id"`
	Filename   string                   `json:"filename"`
	MIMEType   string                   `json:"mime_type"`
	StorageKey string                   `json:"storage_key,omitempty"`
	ExpiresAt  time.Time                `json:"expires_at,omitzero"`
	// URL is materialized for one model request and must never be persisted in
	// a Session transcript. Durable hosts provide StorageKey and ExpiresAt so a
	// later Run can resolve a fresh URL or explicitly retire unavailable history.
	URL string `json:"-"`
	// CurrentRun is set by Runtime on the current user turn. Persisted history
	// always clears it so unavailable history can be handled without weakening
	// fail-fast semantics for the user's current attachment choice.
	CurrentRun bool   `json:"-"`
	Text       string `json:"text,omitempty"`
}

func NormalizeModelInputAttachment

func NormalizeModelInputAttachment(attachment ModelInputAttachment) ModelInputAttachment

type ModelInputAttachmentKind

type ModelInputAttachmentKind string
const (
	ModelInputAttachmentImage ModelInputAttachmentKind = "image"
	ModelInputAttachmentText  ModelInputAttachmentKind = "text"
)

type ModelInputItem

type ModelInputItem struct {
	Type        ModelInputItemType     `json:"type"`
	Text        string                 `json:"text,omitempty"`
	Attachments []ModelInputAttachment `json:"attachments,omitempty"`
	OutputType  ModelOutputItemType    `json:"output_type,omitempty"`
	Raw         json.RawMessage        `json:"raw,omitempty"`
	CallID      string                 `json:"call_id,omitempty"`
	Output      json.RawMessage        `json:"output,omitempty"`
}

type ModelInputItemType

type ModelInputItemType string
const (
	ModelInputUserMessage     ModelInputItemType = "user_message"
	ModelInputAssistantOutput ModelInputItemType = "assistant_output"
	ModelInputToolResult      ModelInputItemType = "tool_result"
)

type ModelOutputItem

type ModelOutputItem struct {
	ID   string              `json:"id,omitempty"`
	Type ModelOutputItemType `json:"type"`
	Text string              `json:"text,omitempty"`
	Call *ToolCall           `json:"call,omitempty"`
	Raw  json.RawMessage     `json:"raw,omitempty"`
}

type ModelOutputItemType

type ModelOutputItemType string
const (
	ModelOutputMessage      ModelOutputItemType = "message"
	ModelOutputReasoning    ModelOutputItemType = "reasoning"
	ModelOutputFunctionCall ModelOutputItemType = "function_call"
)

type ModelRequest

type ModelRequest struct {
	Instructions string           `json:"instructions"`
	Input        []ModelInputItem `json:"input"`
	Tools        []ToolDefinition `json:"tools,omitempty"`
	// ModelCallID is assigned by Runtime immediately before Complete. Model
	// decorators may use it for idempotent metering or provider attribution;
	// transports must not serialize it into the provider request.
	ModelCallID string `json:"-"`
	// DisableReasoning asks adapters with an explicit thinking mode to turn it
	// off for this call. Runtime uses it only for the single corrective retry
	// after a reasoning-only response.
	DisableReasoning bool `json:"disable_reasoning,omitempty"`
	// ToolSetID is reserved for Runtime's content hash. Direct model callers
	// should leave it empty; OpenAIModel rejects IDs that do not match Tools.
	ToolSetID  string          `json:"tool_set_id,omitempty"`
	StreamSink ModelStreamSink `json:"-"`
}

type ModelResponse

type ModelResponse struct {
	ID           string            `json:"id"`
	OutputText   string            `json:"output_text,omitempty"`
	Refusal      string            `json:"refusal,omitempty"`
	Items        []ModelOutputItem `json:"items"`
	FinishReason string            `json:"finish_reason,omitempty"`
	HadReasoning bool              `json:"had_reasoning,omitempty"`
	Usage        Usage             `json:"usage"`
}

type ModelStreamEvent

type ModelStreamEvent struct {
	Type           ModelStreamEventType `json:"type"`
	ProviderType   string               `json:"provider_type,omitempty"`
	ModelCallID    string               `json:"model_call_id,omitempty"`
	SequenceNumber *int64               `json:"sequence_number,omitempty"`
	ItemID         string               `json:"item_id,omitempty"`
	OutputIndex    *int64               `json:"output_index,omitempty"`
	ResponseID     string               `json:"response_id,omitempty"`
	CallID         string               `json:"call_id,omitempty"`
	Name           string               `json:"name,omitempty"`
	Phase          string               `json:"phase,omitempty"`
	Delta          string               `json:"delta,omitempty"`
	Arguments      string               `json:"arguments,omitempty"`
	ErrorCode      string               `json:"error_code,omitempty"`
	ErrorMessage   string               `json:"-"`
	RawJSON        string               `json:"-"`
}

func (ModelStreamEvent) MarshalJSON

func (e ModelStreamEvent) MarshalJSON() ([]byte, error)

MarshalJSON defines the public event boundary. Provider raw payloads and incremental tool arguments remain available to trusted in-process sinks but are not exposed by adapters that directly encode Event as JSON.

type ModelStreamEventType

type ModelStreamEventType string
const (
	ModelStreamResponseStarted       ModelStreamEventType = "response_started"
	ModelStreamItemAdded             ModelStreamEventType = "item_added"
	ModelStreamReasoningSummaryDelta ModelStreamEventType = "reasoning_summary_delta"
	ModelStreamCommentaryDelta       ModelStreamEventType = "commentary_delta"
	ModelStreamTextDelta             ModelStreamEventType = "text_delta"
	ModelStreamRefusalDelta          ModelStreamEventType = "refusal_delta"
	ModelStreamToolArgumentsDelta    ModelStreamEventType = "tool_arguments_delta"
	ModelStreamToolArgumentsDone     ModelStreamEventType = "tool_arguments_done"
	ModelStreamItemDone              ModelStreamEventType = "item_done"
	ModelStreamResponseDone          ModelStreamEventType = "response_done"
	ModelStreamError                 ModelStreamEventType = "error"
)

type ModelStreamSink

type ModelStreamSink func(ModelStreamEvent)

ModelStreamSink observes ordered transport chunks and completion boundaries. Callbacks run synchronously and provide backpressure. Implementations must not mutate event data after invoking the callback. A completed ModelResponse remains authoritative: tool argument chunks are never executable input.

type OpenAIModel

type OpenAIModel struct {
	// contains filtered or unexported fields
}

func NewOpenAIModel

func NewOpenAIModel(cfg OpenAIModelConfig) (*OpenAIModel, error)

func (*OpenAIModel) Complete

func (m *OpenAIModel) Complete(ctx context.Context, req ModelRequest) (*ModelResponse, error)

type OpenAIModelConfig

type OpenAIModelConfig struct {
	APIKey    string
	BaseURL   string
	Model     string
	UserAgent string
	Reasoning *OpenAIReasoningConfig
}

type OpenAIReasoningConfig

type OpenAIReasoningConfig struct {
	Effort  OpenAIReasoningEffort
	Summary OpenAIReasoningSummary
}

type OpenAIReasoningEffort

type OpenAIReasoningEffort string
const (
	OpenAIReasoningEffortNone    OpenAIReasoningEffort = "none"
	OpenAIReasoningEffortMinimal OpenAIReasoningEffort = "minimal"
	OpenAIReasoningEffortLow     OpenAIReasoningEffort = "low"
	OpenAIReasoningEffortMedium  OpenAIReasoningEffort = "medium"
	OpenAIReasoningEffortHigh    OpenAIReasoningEffort = "high"
	OpenAIReasoningEffortXHigh   OpenAIReasoningEffort = "xhigh"
)

type OpenAIReasoningSummary

type OpenAIReasoningSummary string
const (
	OpenAIReasoningSummaryNone     OpenAIReasoningSummary = "none"
	OpenAIReasoningSummaryAuto     OpenAIReasoningSummary = "auto"
	OpenAIReasoningSummaryConcise  OpenAIReasoningSummary = "concise"
	OpenAIReasoningSummaryDetailed OpenAIReasoningSummary = "detailed"
)

type Operation

type Operation struct {
	Name string
	// PreviousNames are accepted only when replaying persisted model transcript
	// items after an operation rename. They are never registered as executable
	// operation names or exposed as current tools to the model.
	PreviousNames []string
	Description   string
	InputSchema   json.RawMessage
	OutputSchema  json.RawMessage
	// NormalizeInput canonicalizes schema-validated arguments before execution
	// IDs, durable plans, approval previews, and executions are created. It must
	// not mutate its input and its result is validated again.
	NormalizeInput func(arguments any) (any, error)
	Effect         OperationEffect
	Capabilities   []string
	Confirmation   ConfirmationSpec
	// ApprovalPreview builds a safe, operation-specific JSON object from
	// schema-validated arguments. Raw arguments never cross the browser trust
	// boundary; writes that require confirmation must provide one so a policy
	// can safely route them through approval.
	ApprovalPreview func(arguments any) (json.RawMessage, error)
	// Terminal ends the current agent turn after this operation completes
	// successfully, or after every call in an allowed homogeneous terminal batch
	// completes. The executor must return FinalResponse for each call.
	Terminal bool
	// TerminalBatchLimit permits 2..N homogeneous calls to this terminal write
	// operation in one model turn. Zero preserves the default single-call rule.
	// Runtime still plans, fences, executes, validates, and persists every call
	// independently before completing the turn with their combined artifacts.
	TerminalBatchLimit int
}

type OperationEffect

type OperationEffect string
const (
	OperationEffectRead  OperationEffect = "read"
	OperationEffectWrite OperationEffect = "write"
	// MaxTerminalBatchLimit bounds one model turn so a malformed response cannot
	// fan out an unbounded number of otherwise valid terminal writes.
	MaxTerminalBatchLimit = 10
)

type OperationExecutionRecord

type OperationExecutionRecord struct {
	ID               string
	IdempotencyKey   string
	IdempotencyScope string
	RunID            string
	SessionID        string
	CallID           string
	AttemptID        string
	Name             string
	Arguments        json.RawMessage
	Status           OperationExecutionStatus
	Result           OperationResult
	Verification     *VerificationResult
	Error            string
	CreatedAt        time.Time
	UpdatedAt        time.Time
}

type OperationExecutionStatus

type OperationExecutionStatus string
const (
	OperationExecutionStarted        OperationExecutionStatus = "started"
	OperationExecutionExecuted       OperationExecutionStatus = "executed"
	OperationExecutionCompleted      OperationExecutionStatus = "completed"
	OperationExecutionUnknown        OperationExecutionStatus = "unknown"
	OperationExecutionRetryable      OperationExecutionStatus = "retryable"
	OperationExecutionRecoveryFailed OperationExecutionStatus = "recovery_failed"
)

type OperationExecutionTransition

type OperationExecutionTransition struct {
	ID           string
	ExecutionID  string
	AttemptID    string
	RunID        string
	CallID       string
	Actor        string
	Message      string
	From         OperationExecutionStatus
	To           OperationExecutionStatus
	Result       OperationResult
	Verification *VerificationResult
	Evidence     json.RawMessage
	CreatedAt    time.Time
}

func (OperationExecutionTransition) Validate

func (transition OperationExecutionTransition) Validate() error

type OperationExecutor

type OperationExecutor interface {
	Execute(ctx context.Context, req OperationRequest) (OperationResult, error)
}

type OperationExecutorFunc

type OperationExecutorFunc func(ctx context.Context, req OperationRequest) (OperationResult, error)

func (OperationExecutorFunc) Execute

type OperationPlanBatch

type OperationPlanBatch struct {
	RequestID        string
	SessionID        string
	IdempotencyKey   string
	IdempotencyScope string
	Index            uint64
	Steps            []OperationPlanStep
	CreatedAt        time.Time
}

type OperationPlanSeal

type OperationPlanSeal struct {
	RequestID        string
	SessionID        string
	IdempotencyKey   string
	IdempotencyScope string
	BatchCount       uint64
	SealedAt         time.Time
}

type OperationPlanStep

type OperationPlanStep struct {
	ExecutionID string
	Name        string
	Arguments   json.RawMessage
}

type OperationPolicy

type OperationPolicy interface {
	Evaluate(ctx context.Context, req OperationRequest) (PolicyDecision, error)
}

type OperationPolicyFunc

type OperationPolicyFunc func(ctx context.Context, req OperationRequest) (PolicyDecision, error)

func (OperationPolicyFunc) Evaluate

type OperationReconciler

type OperationReconciler struct {
	// contains filtered or unexported fields
}

OperationReconciler settles persisted operation executions without creating a model adapter or starting an Agent Run. Hosts use it before credentials, attachments, runtime-version checks, and terminal Run handling so an unresolved write cannot be stranded by unrelated conversation state.

func NewOperationReconciler

func NewOperationReconciler(
	operations *OperationRegistry,
	executions ExecutionStore,
) (*OperationReconciler, error)

func (*OperationReconciler) ReconcileOperation

func (r *OperationReconciler) ReconcileOperation(ctx context.Context, request ReconcileOperationRequest) error

type OperationReconciliationAction

type OperationReconciliationAction string
const (
	OperationReconciliationRetry    OperationReconciliationAction = "retry"
	OperationReconciliationComplete OperationReconciliationAction = "complete"
	OperationReconciliationFail     OperationReconciliationAction = "fail"
)

type OperationRegistry

type OperationRegistry struct {
	// contains filtered or unexported fields
}

func NewOperationRegistry

func NewOperationRegistry() *OperationRegistry

func (*OperationRegistry) BuildApprovalPreview

func (r *OperationRegistry) BuildApprovalPreview(name string, arguments any) (json.RawMessage, error)

func (*OperationRegistry) DecodeInput

func (r *OperationRegistry) DecodeInput(name string, input json.RawMessage) (any, error)

func (*OperationRegistry) DecodeOutput

func (r *OperationRegistry) DecodeOutput(name string, output json.RawMessage) (any, error)

func (*OperationRegistry) Freeze

func (r *OperationRegistry) Freeze() error

func (*OperationRegistry) Get

func (r *OperationRegistry) Get(name string) (Operation, bool)

func (*OperationRegistry) NormalizeInput

func (r *OperationRegistry) NormalizeInput(name string, arguments any) (any, error)

func (*OperationRegistry) Provides

func (r *OperationRegistry) Provides(requirement string) bool

func (*OperationRegistry) Register

func (r *OperationRegistry) Register(op Operation) error

func (*OperationRegistry) Summaries

func (r *OperationRegistry) Summaries() []OperationSummary

func (*OperationRegistry) ValidateInput

func (r *OperationRegistry) ValidateInput(name string, input json.RawMessage) error

func (*OperationRegistry) ValidateOutput

func (r *OperationRegistry) ValidateOutput(name string, output json.RawMessage) error

type OperationRequest

type OperationRequest struct {
	RunID     string
	SessionID string
	// ExecutionID is stable for one write operation in the persisted request
	// plan, or for one terminal read operation that produces a durable artifact.
	// Write executors must enforce it at their own side-effect boundary.
	ExecutionID string
	// AttemptID fences the current execution owner. Executors that coordinate
	// retries must reject stale attempts before mutating state.
	AttemptID string
	// SessionLease is the fencing token for the session owner. Write executors
	// must validate its generation atomically at their side-effect boundary.
	SessionLease SessionLeaseFence
	Input        Input
	Operation    OperationSummary
	Call         ToolCall
	// Arguments may contain nil for properties that are optional in InputSchema:
	// strict tool schemas encode omission as an explicit JSON null.
	Arguments any
}

type OperationResult

type OperationResult struct {
	Output        json.RawMessage  `json:"output"`
	Receipt       json.RawMessage  `json:"receipt,omitempty"`
	FinalResponse string           `json:"final_response,omitempty"`
	Artifacts     []ResultArtifact `json:"artifacts,omitempty"`
	// Continue lets a terminal read operation return a successful,
	// schema-validated correction result to the model without completing the
	// Run. It is only valid when no final response, receipt, or artifacts were
	// produced.
	Continue bool `json:"continue,omitempty"`
}

type OperationSummary

type OperationSummary struct {
	Name               string           `json:"name"`
	PreviousNames      []string         `json:"-"`
	Description        string           `json:"description,omitempty"`
	InputSchema        json.RawMessage  `json:"input_schema"`
	OutputSchema       json.RawMessage  `json:"output_schema"`
	Effect             OperationEffect  `json:"effect"`
	Capabilities       []string         `json:"capabilities,omitempty"`
	Confirmation       ConfirmationSpec `json:"confirmation"`
	Terminal           bool             `json:"terminal,omitempty"`
	TerminalBatchLimit int              `json:"terminal_batch_limit,omitempty"`
}

type PendingApprovalCommit

type PendingApprovalCommit struct {
	Request  ApprovalRequest
	Decision ApprovalDecision
	Audit    ItemRecord
}

PendingApprovalCommit carries the approval request and its audit item into the RunStore-owned FinishRun transaction. Stores must create or validate the pending approval and append Audit atomically with the waiting_user Run transition; an error must leave none of those mutations visible.

type PlanBatchReservation

type PlanBatchReservation struct {
	Batch   OperationPlanBatch
	Created bool
}

type PlanSealResult

type PlanSealResult struct {
	Seal    OperationPlanSeal
	Created bool
}

type PolicyAction

type PolicyAction string
const (
	PolicyAllow           PolicyAction = "allow"
	PolicyDeny            PolicyAction = "deny"
	PolicyRequireApproval PolicyAction = "require_approval"
)

type PolicyDecision

type PolicyDecision struct {
	Action PolicyAction
	Reason string
}

type ReconcileOperationRequest

type ReconcileOperationRequest struct {
	ExecutionID       string
	ExpectedAttemptID string
	Action            OperationReconciliationAction
	Result            OperationResult
	Actor             string
	Message           string
	Evidence          json.RawMessage
}

type RenewRunLeaseRequest

type RenewRunLeaseRequest struct {
	Handle   RunHandle
	LeaseTTL time.Duration
}

type Result

type Result struct {
	RunID          string
	SessionID      string
	Status         RunStatus
	LastResponseID string
	Output         string
}

type ResultArtifact

type ResultArtifact struct {
	Type           string          `json:"type"`
	Data           json.RawMessage `json:"data"`
	InternalData   json.RawMessage `json:"internal_data,omitempty"`
	SessionSummary json.RawMessage `json:"session_summary,omitempty"`
}

ResultArtifact carries a domain-neutral terminal result to the host. Data is safe for the model transcript and host protocol; InternalData is retained only on the terminal RunRecord so the host can materialize private state. SessionSummary is a bounded host-authored projection used only when Runtime persists future model context. Runtime events, operation-result items, and tool results always receive a public-only copy without either private field.

type ResultVerifier

type ResultVerifier interface {
	Verify(ctx context.Context, req VerificationRequest) (VerificationResult, error)
}

type ResultVerifierFunc

type ResultVerifierFunc func(ctx context.Context, req VerificationRequest) (VerificationResult, error)

func (ResultVerifierFunc) Verify

type RunHandle

type RunHandle struct {
	RunID           string
	SessionID       string
	LeaseID         string
	LeaseGeneration uint64
	LeaseDeadline   time.Time
	SessionRevision uint64
}

RunHandle proves ownership of the session lease acquired by BeginRun. The store, not Runtime, owns lease recovery for abandoned runs.

type RunRecord

type RunRecord struct {
	ID        string
	SessionID string
	Status    RunStatus
	Input     Input
	Result    string
	Artifacts []ResultArtifact
	ErrorCode string
	Error     string
	CreatedAt time.Time
	UpdatedAt time.Time
}

type RunStatus

type RunStatus string
const (
	RunStatusRunning     RunStatus = "running"
	RunStatusWaitingUser RunStatus = "waiting_user"
	RunStatusCompleted   RunStatus = "completed"
	RunStatusFailed      RunStatus = "failed"
	RunStatusInterrupted RunStatus = "interrupted"
	RunStatusCancelled   RunStatus = "cancelled"
)

type RunStore

type RunStore interface {
	BeginRun(ctx context.Context, request BeginRunRequest) (BeginRunResult, error)
	RenewRunLease(ctx context.Context, request RenewRunLeaseRequest) (RunHandle, error)
	ValidateRunLease(ctx context.Context, handle RunHandle) (RunHandle, error)
	AppendItem(ctx context.Context, item ItemRecord) error
	FinishRun(ctx context.Context, request FinishRunRequest) error
}

RunStore owns the transaction boundary for a run and its session. BeginRun atomically creates the running run and acquires the session lease. Stores must permit a new run to fence an expired lease, assign a monotonically increasing lease generation, and return the store-owned deadline in the handle. RenewRunLease extends only a live matching generation. ValidateRunLease lets Runtime reject a stale owner immediately before a write side effect. FinishRun atomically terminalizes or pauses the run, commits the next session snapshot when supplied, and releases the lease. Lease renewal remains active while FinishRun executes, so stores must validate the live owner fields and deadline; the request handle's observed LeaseDeadline may lag a renewal. When PendingApproval is supplied, FinishRun must also atomically persist that approval and its audit item. A waiting run and a failed run whose session could not be validated may pass a nil Session; the store must then leave the existing snapshot unchanged. An error from either method must leave no mutation.

type Runtime

type Runtime struct {
	// contains filtered or unexported fields
}

func NewRuntime

func NewRuntime(cfg RuntimeConfig) (*Runtime, error)

func (*Runtime) ReconcileOperation

func (r *Runtime) ReconcileOperation(ctx context.Context, request ReconcileOperationRequest) error

ReconcileOperation records a trusted reconciler decision for an unresolved write. Runtime validates completed output against the registered operation schema before the execution store atomically changes state and appends history.

func (*Runtime) Run

func (r *Runtime) Run(ctx context.Context, input Input) (*Result, error)

type RuntimeConfig

type RuntimeConfig struct {
	Model           Model
	Operations      *OperationRegistry
	MCPInstructions string
	Policy          OperationPolicy
	Executor        OperationExecutor
	Verifier        ResultVerifier
	Approver        Approver
	ApprovalResumer ApprovalResumer
	RunStore        RunStore
	Executions      ExecutionStore
	EventSink       EventSink
	ContextWindow   *ContextWindowConfig

	MaxIterations        int
	SessionLeaseTTL      time.Duration
	LeaseRenewalInterval time.Duration
	CleanupTimeout       time.Duration
	Now                  func() time.Time
	NewID                func() string
}

type SessionLeaseFence

type SessionLeaseFence struct {
	RunID           string
	SessionID       string
	LeaseID         string
	Generation      uint64
	Deadline        time.Time
	SessionRevision uint64
}

type SessionState

type SessionState struct {
	ID             string
	Revision       uint64
	Transcript     []ModelInputItem
	Checkpoint     *ContextCheckpoint
	SeenCallIDs    []string
	LastResponseID string
	LastRunID      string
	LastError      string
	CreatedAt      time.Time
	UpdatedAt      time.Time
}

type TokenCounter

type TokenCounter interface {
	CountModelRequest(ctx context.Context, request ModelRequest) (int, error)
	CountText(ctx context.Context, text string) (int, error)
}

TokenCounter provides model-specific, exact token accounting. Runtime passes the complete request, including instructions, tools, checkpoint, and transcript.

type ToolCall

type ToolCall struct {
	ID    string          `json:"id"`
	Name  string          `json:"name"`
	Input json.RawMessage `json:"input"`
}

type ToolDefinition

type ToolDefinition struct {
	Name          string          `json:"name"`
	PreviousNames []string        `json:"-"`
	Description   string          `json:"description,omitempty"`
	InputSchema   json.RawMessage `json:"input_schema"`
}

type Usage

type Usage struct {
	InputTokens  int `json:"input_tokens"`
	OutputTokens int `json:"output_tokens"`
	TotalTokens  int `json:"total_tokens"`
}

type VerificationRequest

type VerificationRequest struct {
	Operation OperationRequest
	Result    OperationResult
	Output    any
}

type VerificationResult

type VerificationResult struct {
	Confirmed bool            `json:"confirmed"`
	Message   string          `json:"message,omitempty"`
	Evidence  json.RawMessage `json:"evidence,omitempty"`
}

Directories

Path Synopsis
examples
basic command
mcp command
skill command
skill/textskill
Package textskill demonstrates a reusable Skill as a host-side composition of instructions, operation contracts, and execution behavior.
Package textskill demonstrates a reusable Skill as a host-side composition of instructions, operation contracts, and execution behavior.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL