Help us shape the future of Go! Take the 2026 Go Developer Survey

runtime

package
v1.153.0 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: Apache-2.0 Imports: 78 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ErrorCodeModelError             = "model_error"
	ErrorCodeRateLimited            = "rate_limited"
	ErrorCodeContextExceeded        = "context_exceeded"  // OverflowKindTokens
	ErrorCodeRequestTooLarge        = "request_too_large" // OverflowKindWire
	ErrorCodeMediaTooLarge          = "media_too_large"   // OverflowKindMedia
	ErrorCodeToolFailed             = "tool_failed"
	ErrorCodeHookBlocked            = "hook_blocked"
	ErrorCodeLoopDetected           = "loop_detected"
	ErrorCodeStructuredOutputFailed = "structured_output_failed"
	ErrorCodeRoutingFailed          = "routing_failed"
)

ErrorCode constants classify errors so external consumers (boards, dashboards) can react programmatically without parsing free-form messages.

The three overflow codes (ErrorCodeContextExceeded, ErrorCodeRequestTooLarge, ErrorCodeMediaTooLarge) mirror modelerrors.OverflowKind and let clients render distinct, actionable messages for each shape (token-count overflow, wire-level body cap, media-size rejection) instead of one generic "context window exceeded".

View Source
const (
	CompactionOutcomeApplied = "applied"
	CompactionOutcomeSkipped = "skipped"
	CompactionOutcomeFailed  = "failed"
)

Outcome values carried by a "completed" SessionCompactionEvent.

View Source
const (
	// TurnEndReasonNormal — the model finished the turn cleanly and the
	// run loop is about to break out (no further iterations).
	TurnEndReasonNormal = "normal"
	// TurnEndReasonError — the model call failed and the runtime is
	// shutting down the run (handleStreamError returned non-retry).
	TurnEndReasonError = "error"
	// TurnEndReasonCanceled — the turn ended because the stream context
	// was cancelled (e.g. user Ctrl+C). Includes deferred firing on
	// any return path while ctx is done.
	TurnEndReasonCanceled = "canceled"
)

Reason values reported in hooks.Input.Reason when hooks.EventTurnEnd fires. The same values (including the exported trio below, plus hook_blocked/loop_detected/budget_exceeded) are also reported verbatim in runtime.StreamStoppedEvent.Reason — loop.go passes its turnEndReason* classification straight through to StreamStopped. The runtime guarantees that turn_end runs once per turn that fired turn_start, no matter how the turn exited; the reason classifies which exit path the runtime took.

View Source
const (
	ApprovalDecisionAllow    = "allow"
	ApprovalDecisionDeny     = "deny"
	ApprovalDecisionCanceled = "canceled"

	ApprovalSourceYolo                    = "yolo"
	ApprovalSourceSessionPermissionsAllow = "session_permissions_allow"
	ApprovalSourceSessionPermissionsDeny  = "session_permissions_deny"
	ApprovalSourceTeamPermissionsAllow    = "team_permissions_allow"
	ApprovalSourceTeamPermissionsDeny     = "team_permissions_deny"
	ApprovalSourcePreToolUseHookAllow     = "pre_tool_use_hook_allow"
	ApprovalSourcePreToolUseHookDeny      = "pre_tool_use_hook_deny"
	ApprovalSourceToolInputTransformDeny  = toolexec.ApprovalSourceToolInputTransformDeny
	ApprovalSourceToolGuardDeny           = toolexec.ApprovalSourceToolGuardDeny
	ApprovalSourceReadOnlyHint            = "readonly_hint"
	ApprovalSourceModeBalanced            = "mode_balanced"
	ApprovalSourceModeRestricted          = "mode_restricted"
	ApprovalSourceModeStrict              = "mode_strict"
	ApprovalSourceModeLegacy              = "mode_legacy"
	ApprovalSourceUserApproved            = "user_approved"
	ApprovalSourceUserApprovedBalanced    = "user_approved_balanced"
	ApprovalSourceUserApprovedAutonomous  = "user_approved_autonomous"
	ApprovalSourceUserApprovedTool        = "user_approved_tool"
	ApprovalSourceUserRejected            = "user_rejected"
	ApprovalSourceContextCanceled         = "context_canceled"
)

Verdicts and sources for hooks.EventOnToolApprovalDecision. Constants instead of literals so the contract between executeWithApproval and the hook protocol is discoverable from the runtime side and a typo trips a compile error.

View Source
const (
	// ResumeTypeApprove approves the single pending tool call.
	ResumeTypeApprove = toolexec.ResumeTypeApprove
	// ResumeTypeApproveBalanced approves the pending call and flips
	// the session to [session.SafetyPolicyBalanced] so subsequent
	// classifier-safe calls auto-approve.
	ResumeTypeApproveBalanced = toolexec.ResumeTypeApproveBalanced
	// ResumeTypeApproveAutonomous approves the pending call and flips
	// the session to [session.SafetyPolicyAutonomous] so every
	// subsequent call auto-approves (custom deny/ask rules still win).
	ResumeTypeApproveAutonomous = toolexec.ResumeTypeApproveAutonomous
	// ResumeTypeApproveTool approves the pending call and every future
	// call to the same tool name within the session.
	ResumeTypeApproveTool = toolexec.ResumeTypeApproveTool
	// ResumeTypeReject rejects the pending tool call.
	ResumeTypeReject = toolexec.ResumeTypeReject
)
View Source
const (
	// Deprecated: use [ResumeTypeApproveAutonomous].
	ResumeTypeApproveSession = toolexec.ResumeTypeApproveSession
	// Deprecated: use [ResumeTypeApproveBalanced].
	ResumeTypeApproveSafe = toolexec.ResumeTypeApproveSafe
	// Deprecated: use [ResumeTypeApproveBalanced].
	ResumeTypeApproveSafer = toolexec.ResumeTypeApproveSafer
)

Legacy resume verbs, accepted and normalized for older callers.

View Source
const BuiltinCacheResponse = "cache_response"

BuiltinCacheResponse is the name of the builtin stop hook that persists an agent's response into its configured response cache. It is auto-injected by [LocalRuntime.hooksExec] when the agent has a cache configured, mirroring the way builtins.AddDate et al. are auto-injected from agent flags via builtins.ApplyAgentDefaults.

View Source
const BuiltinStripGeneratedMedia = "strip_generated_media"

BuiltinStripGeneratedMedia is the name of the runtime-shipped before_llm_call message transform that removes assistant-authored, model-generated media (materialized as a session artifact — see chat.DocumentSource.ArtifactPath) from outgoing provider history, keeping the surrounding text.

Without the default no-resend policy, every subsequent turn would re-encode and resend the same generated image bytes to the provider on every follow-up request, burning context budget for content the model already produced and the user already has. It runs unconditionally, independent of the model's capabilities — unlike BuiltinStripUnsupportedModalities, which only strips media the current model cannot accept.

User-attached documents (InlineData/InlineText) are never touched: only parts carrying an ArtifactPath — which is exclusively set for runtime-materialized, provider-generated media — are removed.

It is registered to run BEFORE BuiltinStripUnsupportedModalities (see the registration order in runtime.go's New) so that a capability-less or unknown model never gets a chance to strip the same media part first, bypassing the placeholder logic below and leaving a media-only assistant turn with nothing at all.

View Source
const BuiltinStripUnsupportedModalities = "strip_unsupported_modalities"

BuiltinStripUnsupportedModalities is the name of the runtime-shipped before_llm_call message transform that drops image, audio, and video content from the outgoing messages when the resolved capabilities of the agent's current model don't cover that media kind. It's the runtime-shipped peer of BuiltinCacheResponse (a stop hook) — the constant exists mostly for log filtering and diagnostics.

Sending unsupported media produces hard provider errors (HTTP 400 from OpenAI, "image input is not supported" from Anthropic text variants, etc.); promoting the strip into a registered transform replaced an inline branch in runStreamLoop and opened the door to a family of message-mutating transforms (redactors, scrubbers, ...).

View Source
const StreamStopReasonMaxIterations = "max_iterations"

StreamStopReasonMaxIterations identifies a stream stopped at its iteration limit.

Variables

View Source
var (
	// ErrSteerQueueFull indicates that no more steering messages can be queued.
	ErrSteerQueueFull = errors.New("steer queue full")
	// ErrFollowUpQueueFull indicates that no more follow-up messages can be queued.
	ErrFollowUpQueueFull = errors.New("follow-up queue full")
)
View Source
var ErrHarnessNotRegistered = errors.New("harness agents need a driver: call runtime.RegisterHarness(codingharness.Factory)")

ErrHarnessNotRegistered is returned when an agent declares a harness but no driver was registered with RegisterHarness.

View Source
var ErrUnsupported = errors.New("operation not supported by this runtime")

ErrUnsupported indicates that a runtime method is not supported by the current backend. Callers can check with errors.Is to surface a clear message instead of treating a silent zero value as a feature.

Functions

func IsValidResumeType

func IsValidResumeType(t ResumeType) bool

IsValidResumeType validates confirmation values coming from /resume. Legacy verbs (approve-session, approve-safe, approve-safer) stay accepted; NormalizeResumeType maps them onto the current set.

The runtime may be resumed by multiple entry points (API, CLI, TUI, tests). Even if upstream layers perform validation, the runtime must never assume the ResumeType is valid; accepting invalid values leads to confusing downstream behaviour where tool execution fails without a clear cause.

func LookupCommand added in v1.60.0

func LookupCommand(ctx context.Context, rt commandLookup, userInput string) (cmd types.Command, rest string, ok bool)

LookupCommand parses userInput as a /command invocation and returns the matching command along with its trailing arguments. The boolean is false when userInput doesn't start with '/' or doesn't match a configured command. Callers that need both the resolved instruction and the original command metadata (e.g. its target agent) typically call LookupCommand to inspect the command before calling ResolveCommand.

func RegisterCommandEvaluator added in v1.114.0

func RegisterCommandEvaluator(factory CommandEvaluatorFactory)

RegisterCommandEvaluator installs the factory ResolveCommand uses to expand ${...} expressions. See pkg/runtime/jscommands. Prefer WithCommandEvaluatorFactory to configure independent runtimes.

func RegisterHarness added in v1.132.0

func RegisterHarness(factory harness.Factory)

RegisterHarness installs the factory used to run `harness:` agents:

runtime.RegisterHarness(codingharness.Factory)

Prefer WithHarnessFactory to configure independent runtimes.

func RegisterModelHook added in v1.149.0

func RegisterModelHook(r *hooks.Registry, registry *provider.Registry)

RegisterModelHook installs provider-backed model hooks on r.

func ResolveCommand

func ResolveCommand(ctx context.Context, rt commandSource, userInput string) string

ResolveCommand transforms a /command into its expanded instruction text. It processes: 1. Command lookup from agent commands 2. Tool command execution (!tool_name(arg=value)) - tools executed and output inserted 3. JavaScript expressions (${...}) - evaluated with access to all agent tools and args array

  • ${args[0]}, ${args[1]}, etc. for positional arguments
  • ${args} or ${args.join(" ")} for all arguments
  • ${tool({...})} for tool calls

For agent-switching commands (those declaring `agent: <name>` and no instruction), ResolveCommand returns the trailing arguments verbatim so the caller can forward them to the target sub-agent after switching. When the command has no instruction and no arguments, the result is the empty string, signalling "no message to send".

Types

type AgentBudgetUsage added in v1.112.0

type AgentBudgetUsage struct {
	AgentName     string  `json:"agent_name"`
	Cost          float64 `json:"cost"`
	Tokens        int64   `json:"tokens"`
	ActiveSeconds float64 `json:"active_seconds"`
}

AgentBudgetUsage is one agent's attributed slice of a budget.

type AgentChoiceEvent

type AgentChoiceEvent struct {
	AgentContext

	Type      string `json:"type"`
	Content   string `json:"content"`
	SessionID string `json:"session_id,omitempty"`
	MessageID string `json:"message_id,omitempty"`
}

func (*AgentChoiceEvent) GetSessionID added in v1.32.1

func (e *AgentChoiceEvent) GetSessionID() string

type AgentChoiceReasoningEvent

type AgentChoiceReasoningEvent struct {
	AgentContext

	Type      string `json:"type"`
	Content   string `json:"content"`
	SessionID string `json:"session_id,omitempty"`
	MessageID string `json:"message_id,omitempty"`
}

func (*AgentChoiceReasoningEvent) GetSessionID added in v1.32.1

func (e *AgentChoiceReasoningEvent) GetSessionID() string

type AgentChoiceReasoningResetEvent added in v1.153.0

type AgentChoiceReasoningResetEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	MessageID string `json:"message_id"`
}

AgentChoiceReasoningResetEvent discards reasoning already streamed for one message. Text and tool calls are unaffected; later reasoning starts from an empty buffer.

func (*AgentChoiceReasoningResetEvent) GetSessionID added in v1.153.0

func (e *AgentChoiceReasoningResetEvent) GetSessionID() string

type AgentContext

type AgentContext struct {
	OperationID uint64    `json:"-"`
	AgentName   string    `json:"agent_name,omitempty"`
	Timestamp   time.Time `json:"timestamp"`
}

AgentContext carries optional agent attribution and timestamp for an event.

func (AgentContext) GetAgentName

func (a AgentContext) GetAgentName() string

GetAgentName returns the agent name for events embedding AgentContext.

func (AgentContext) Operation added in v1.150.0

func (a AgentContext) Operation() uint64

Operation identifies the local foreground run; it is not sent over the wire.

type AgentDetails

type AgentDetails struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Provider    string `json:"provider"`
	Model       string `json:"model"`
	// Thinking is a short label describing the model's current thinking-effort
	// configuration: an effort level (e.g. "high"), "adaptive", a decimal token
	// count for token-based budgets, or "off" when disabled. Empty when the
	// model has no selectable thinking configuration.
	Thinking              string                            `json:"thinking,omitempty"`
	Commands              types.Commands                    `json:"commands,omitempty"`
	ExecutionCapabilities *inspection.ExecutionCapabilities `json:"execution_capabilities,omitempty"`
}

AgentDetails contains information about an agent for display in the sidebar

type AgentInfoEvent

type AgentInfoEvent struct {
	AgentContext

	Type           string `json:"type"`
	AgentName      string `json:"agent_name"`
	Model          string `json:"model"` // this is in provider/model format (e.g., "openai/gpt-4o")
	Description    string `json:"description"`
	WelcomeMessage string `json:"welcome_message,omitempty"`
	ContextLimit   int64  `json:"context_limit,omitempty"`
	// CompactionModel is the identity ("provider/model") of the agent's
	// dedicated compaction model, set only when it actually caps ContextLimit
	// below the primary model's own window.
	CompactionModel string `json:"compaction_model,omitempty"`
	// PrimaryContextLimit is the primary model's own context window, set
	// only alongside CompactionModel.
	PrimaryContextLimit int64 `json:"primary_context_limit,omitempty"`
	// Nil means unknown; model-only update events may omit this field.
	ExecutionCapabilities *inspection.ExecutionCapabilities `json:"execution_capabilities,omitempty"`
}

AgentInfoEvent is sent when agent information is available or changes

type AgentRouteEvent added in v1.147.0

type AgentRouteEvent struct {
	AgentContext

	Type         string `json:"type"`
	SessionID    string `json:"session_id"`
	InvocationID string `json:"invocation_id"`
	StepID       string `json:"step_id"`
	// Phase is before_agent_run, after_agent_complete, or force_handoff.
	Phase     string `json:"phase"`
	FromAgent string `json:"from_agent"`
	ToAgent   string `json:"to_agent"`
	// Evaluator fields are empty for command selectors and forced handoffs.
	Evaluator      string   `json:"evaluator,omitempty"`
	Selected       string   `json:"selected,omitempty"`
	Probability    *float64 `json:"probability,omitempty"`
	Model          string   `json:"model,omitempty"`
	FallbackReason string   `json:"fallback_reason,omitempty"`
}

AgentRouteEvent reports a routing transition without the task text.

func (*AgentRouteEvent) GetSessionID added in v1.147.0

func (e *AgentRouteEvent) GetSessionID() string

type AgentSwitchingEvent

type AgentSwitchingEvent struct {
	AgentContext

	Type      string `json:"type"`
	Switching bool   `json:"switching"`
	FromAgent string `json:"from_agent,omitempty"`
	ToAgent   string `json:"to_agent,omitempty"`
}

AgentSwitchingEvent is sent when agent switching starts or stops

type AuthorizationEvent

type AuthorizationEvent struct {
	AgentContext

	Type         string                  `json:"type"`
	Confirmation tools.ElicitationAction `json:"confirmation"`
}

type BackgroundAgentStatusEvent added in v1.151.0

type BackgroundAgentStatusEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	Running   bool   `json:"running"`
}

BackgroundAgentStatusEvent tracks a detached agent without changing the foreground stream.

func (*BackgroundAgentStatusEvent) GetSessionID added in v1.151.0

func (e *BackgroundAgentStatusEvent) GetSessionID() string

type BudgetExceededEvent added in v1.112.0

type BudgetExceededEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	// Budget names which budget tripped: "run" for the top-level
	// `budget:`, otherwise the key under `budgets:`.
	Budget string `json:"budget"`
	Limit  string `json:"limit"`
	Used   string `json:"used"`
	Max    string `json:"max"`
	// ConfigPath is the YAML path of the limit that tripped, e.g.
	// "budgets.tight.max_cost", so an operator knows exactly what to edit.
	ConfigPath string `json:"config_path"`
	Message    string `json:"message"`
	// StopMessage is the assistant stop message the runtime appends to the
	// session right after this event. message_added events carry no JSON
	// payload, so this is how JSON consumers (the evaluation pipeline
	// reading `run --exec --json` output) see the message a budget stop
	// records. Its dedicated type carries only agent name, role, content,
	// and creation time; tool calls, reasoning, model, usage, and cost
	// cannot be represented at all.
	StopMessage *BudgetStopMessage `json:"stop_message,omitempty"`
}

BudgetExceededEvent is emitted once, when a run crosses a configured budget ceiling and is stopped. Limit names the YAML key that tripped ("max_cost", "max_tokens", "max_time") so an operator knows which one to raise.

func (*BudgetExceededEvent) GetSessionID added in v1.112.0

func (e *BudgetExceededEvent) GetSessionID() string

type BudgetStatus added in v1.112.0

type BudgetStatus struct {
	// Name is "run" for the top-level `budget:`, otherwise the key under
	// `budgets:`.
	Name      string  `json:"name"`
	Cost      float64 `json:"cost"`
	MaxCost   float64 `json:"max_cost,omitempty"`
	Tokens    int64   `json:"tokens"`
	MaxTokens int64   `json:"max_tokens,omitempty"`
	// ElapsedSeconds and MaxTimeSeconds are seconds rather than a
	// duration string so consumers can compute a ratio without parsing.
	ElapsedSeconds float64 `json:"elapsed_seconds"`
	MaxTimeSeconds float64 `json:"max_time_seconds,omitempty"`
	// Unpriced reports that at least one response could not be priced, so
	// Cost understates what was really spent.
	Unpriced bool `json:"unpriced,omitempty"`
	// PerAgent attributes this budget's totals to each agent that spent
	// from it, biggest spender first. Empty until a turn completes.
	PerAgent []AgentBudgetUsage `json:"per_agent,omitempty"`
}

BudgetStatus is one budget's reading: its ceilings, what has been spent against them, and which agents did the spending.

type BudgetStopChatMessage added in v1.119.0

type BudgetStopChatMessage struct {
	Role      chat.MessageRole `json:"role"`
	Content   string           `json:"content"`
	CreatedAt string           `json:"created_at,omitempty"`
}

BudgetStopChatMessage is the inner chat message of a BudgetStopMessage, mirroring chat.Message's JSON keys for the allowed fields only.

type BudgetStopMessage added in v1.119.0

type BudgetStopMessage struct {
	AgentName string                `json:"agent_name,omitempty"`
	Message   BudgetStopChatMessage `json:"message"`
}

BudgetStopMessage is the wire form of the stop message embedded in a BudgetExceededEvent. It mirrors the JSON shape of session.Message ({"agent_name":...,"message":{...}}) restricted to the safe fields, so no caller can ever put reasoning, tool calls, model, usage, or cost on the wire.

type BudgetUsageEvent added in v1.112.0

type BudgetUsageEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	// Budgets carries one reading per active budget, run-wide first then
	// named budgets alphabetically, so a consumer can render them in a
	// stable order.
	Budgets []BudgetStatus `json:"budgets,omitempty"`
}

BudgetUsageEvent reports a run's spend against its configured budget. It is emitted after every priced turn so a UI can track consumption while the run is still going, rather than only learning about the budget at the moment it stops the agent.

Fields are absent when the corresponding limit is unset, so a consumer can render only the ceilings the operator actually configured.

func (*BudgetUsageEvent) GetSessionID added in v1.112.0

func (e *BudgetUsageEvent) GetSessionID() string

GetSessionID implements SessionScoped so sub-session budget events can be attributed to the sub-session that produced them, even though they count against the root run's shared budget.

type CommandEvaluator added in v1.114.0

type CommandEvaluator interface {
	Evaluate(ctx context.Context, instruction string, args []string) string
}

CommandEvaluator expands ${...} JavaScript expressions in a /command instruction, with access to the agent's tools and the command arguments.

type CommandEvaluatorFactory added in v1.135.0

type CommandEvaluatorFactory = func(agentTools []tools.Tool) CommandEvaluator

CommandEvaluatorFactory builds an evaluator with the current agent's tools.

type ContextBreakdown added in v1.99.0

type ContextBreakdown struct {
	// SystemPrompt covers the invariant system messages: the agent
	// instruction, multi-agent/handoff prompts, and toolset instructions.
	SystemPrompt ContextCategory `json:"system_prompt"`
	// ToolDefinitions covers the JSON schemas (name, description,
	// parameters) of every tool exposed to the agent.
	ToolDefinitions ContextCategory `json:"tool_definitions"`
	// PromptFiles covers the add_prompt_files content (AGENTS.md, ...)
	// injected as transient context at every turn.
	PromptFiles ContextCategory `json:"prompt_files"`
	// Messages covers the user and assistant conversation turns.
	Messages ContextCategory `json:"messages"`
	// ToolResults covers the tool-role result messages.
	ToolResults ContextCategory `json:"tool_results"`
	// CompactionSummary covers the synthetic message that carries the
	// latest compaction summary, when the session has been compacted.
	CompactionSummary ContextCategory `json:"compaction_summary"`

	// PromptFileItems details the individual files behind the PromptFiles
	// category, in resolution order.
	PromptFileItems []ContextFile `json:"prompt_file_items,omitempty"`
	// AttachedFiles lists the files attached to the session (/attach,
	// @-mentions), in attach order. Their content was inlined into user
	// messages at send time, so their tokens are already counted in the
	// Messages category; the per-file numbers here are re-estimated from
	// the current on-disk content and are informational, not an extra
	// bucket in TotalTokens.
	AttachedFiles []ContextFile `json:"attached_files,omitempty"`
	// LatestCompactionSummary is the verbatim text behind the
	// CompactionSummary category: the most recent compaction summary
	// stored on the session, or "" when it has never been compacted.
	LatestCompactionSummary string `json:"latest_compaction_summary,omitempty"`

	// ContextLimit is the resolved context window of the effective model,
	// or 0 when it cannot be determined (harness-backed agents, models
	// absent from the catalogue).
	ContextLimit int64 `json:"context_limit"`
	// Model is the effective model label ("provider/model", or the
	// harness label for harness-backed agents).
	Model string `json:"model"`

	// CompactionModel is the identity ("provider/model") of the agent's
	// dedicated compaction model, set whenever one is configured (regardless
	// of whether its window actually caps ContextLimit) — renderers need the
	// unresolved-primary edge case (PrimaryContextLimit == 0) too. Use
	// CompactionContextLimit and PrimaryContextLimit together with
	// [LocalRuntime.effectiveContextLimit]'s cap predicate to decide whether
	// to attribute a reduction.
	CompactionModel string `json:"compaction_model,omitempty"`
	// CompactionContextLimit is the dedicated compaction model's own context
	// window, or 0 when it cannot be resolved. Set only alongside
	// CompactionModel.
	CompactionContextLimit int64 `json:"compaction_context_limit,omitempty"`
	// PrimaryContextLimit is the primary model's own context window (before
	// any compaction-model cap is applied), or 0 when it cannot be resolved.
	// Set only alongside CompactionModel.
	PrimaryContextLimit int64 `json:"primary_context_limit,omitempty"`
}

ContextBreakdown describes the estimated composition of the prompt the runtime would send on the next model call, broken down by category. All token counts are estimates produced by compaction.EstimateMessageTokens (provider-reported counts where available, a chars-per-token heuristic otherwise); the actual provider tokenizer may count differently.

func (*ContextBreakdown) TotalTokens added in v1.99.0

func (b *ContextBreakdown) TotalTokens() int64

TotalTokens returns the estimated size of the whole prompt.

type ContextCategory added in v1.99.0

type ContextCategory struct {
	Tokens int64 `json:"tokens"`
	Items  int   `json:"items"`
}

ContextCategory aggregates the estimated token footprint of one slice of the context window along with the number of items composing it (messages, tool definitions, or prompt files depending on the category).

type ContextFile added in v1.99.0

type ContextFile struct {
	// Path is the file's absolute location on disk.
	Path string `json:"path"`
	// Tokens is the estimated in-context footprint of the file. It is 0
	// for files whose content never reaches the prompt inline (unsupported
	// types, oversized text files) and for missing files.
	Tokens int64 `json:"tokens"`
	// Missing marks files that can no longer be read from disk.
	Missing bool `json:"missing,omitempty"`
}

ContextFile describes one file contributing to the context window, with the estimated token footprint of its current on-disk content.

type CreateSessionRequest added in v1.58.0

type CreateSessionRequest struct {
	AgentName string `json:"agent_name,omitempty"`
	// ToolsApproved is the legacy --yolo signal. New callers should
	// prefer SafetyPolicy; option setters keep both in sync.
	ToolsApproved bool `json:"tools_approved"`
	// SafetyPolicy is the user-owned per-session safety preference (CLI
	// flags, alias options, user settings — never author YAML); empty
	// falls back to the ToolsApproved-derived default or, for fresh local
	// sessions, to the author-declared config defaults. See
	// [session.SafetyPolicy].
	SafetyPolicy session.SafetyPolicy `json:"safety_policy,omitempty"`
	// SafetyExplicit marks a SafetyPolicy chosen explicitly on the command
	// line (--safety / --yolo) rather than resolved from alias or
	// user-settings defaults. Resuming a stored session only honours
	// explicit values: defaults must never replace the persisted mode.
	// Not serialized: the remote protocol has no resume path yet (--remote
	// is mutually exclusive with --session).
	SafetyExplicit    bool                 `json:"-"`
	HideToolResults   bool                 `json:"hide_tool_results"`
	SessionDB         string               `json:"session_db,omitempty"`
	ResumeSessionID   string               `json:"resume_session_id,omitempty"`
	SnapshotsEnabled  bool                 `json:"snapshots_enabled"`
	GlobalPermissions *permissions.Checker `json:"-"`
	WorkingDir        string               `json:"working_dir,omitempty"`
}

CreateSessionRequest is the typed input to a backend's session creation. It carries the agent selection and every CLI-flag-driven session knob.

The same forward-compatibility argument as LoadTeamRequest applies: this is the payload a remote backend will eventually send over the wire.

Boolean fields intentionally do NOT use `omitempty`. With `omitempty`, an explicit `false` is wire-indistinguishable from "unset", so a future server-side default flip from `false` to `true` would silently change the semantics for clients that omitted the field on purpose. Always serialising the boolean keeps the sender's choice authoritative.

GlobalPermissions is currently json:"-" (the permissions.Checker is an opaque struct without a wire form yet); it'll get a serializable representation in a follow-up.

type CurrentAgentInfo

type CurrentAgentInfo struct {
	Name        string
	Description string
	Commands    types.Commands
}

type ElicitationClosedEvent added in v1.150.0

type ElicitationClosedEvent struct {
	AgentContext

	Type          string `json:"type"`
	ElicitationID string `json:"elicitation_id"`
	SessionID     string `json:"session_id,omitempty"`
}

ElicitationClosedEvent retires a request after resolution or cancellation.

func (*ElicitationClosedEvent) GetSessionID added in v1.150.0

func (e *ElicitationClosedEvent) GetSessionID() string

type ElicitationError

type ElicitationError struct {
	Action  string
	Message string
}

ElicitationError represents a declined or cancelled elicitation, exposed to callers that prefer error-style propagation over an Action value.

func (*ElicitationError) Error

func (e *ElicitationError) Error() string

type ElicitationRequestEvent

type ElicitationRequestEvent struct {
	AgentContext

	Type    string `json:"type"`
	Message string `json:"message"`
	Mode    string `json:"mode,omitempty"` // "form" or "url"
	Schema  any    `json:"schema,omitempty"`
	URL     string `json:"url,omitempty"`
	// ElicitationID is the internally-generated correlation ID used to route
	// a ResumeElicitation response back to this specific request (see
	// elicitationHandler). It is always set and always unique, regardless of
	// whether the originating MCP server supplied its own wire ID: two
	// independent servers can coincidentally reuse the same wire ID, so that
	// value is never used for routing (#3584).
	ElicitationID string `json:"elicitation_id,omitempty"`
	// ServerElicitationID is the MCP wire-protocol elicitationId as supplied
	// by the originating server, if any (URL-mode elicitations only; form
	// elicitations leave it empty). It is informational only — useful for
	// correlating with server-side logs — and must never be used as a
	// routing key.
	ServerElicitationID string `json:"server_elicitation_id,omitempty"`
	// SessionID is the session (or sub-session) on whose behalf this
	// elicitation was raised. A detached background job's sub-session ID
	// differs from its parent/foreground session, which lets consumers (see
	// the TUI supervisor) tell apart a foreground stream's own elicitation
	// from a still-live background job's when the foreground stream stops
	// (#3584 review item 4).
	SessionID string         `json:"session_id,omitempty"`
	Meta      map[string]any `json:"meta,omitempty"`
}

ElicitationRequestEvent is sent when an elicitation request is received from an MCP server

func (*ElicitationRequestEvent) GetSessionID added in v1.110.0

func (e *ElicitationRequestEvent) GetSessionID() string

GetSessionID makes ElicitationRequestEvent satisfy SessionScoped.

type ElicitationRequestHandler

type ElicitationRequestHandler func(ctx context.Context, message string, schema map[string]any) (map[string]any, error)

ElicitationRequestHandler is the callback signature an embedder can supply to handle inbound elicitation requests directly (e.g. an HTTP server).

type ElicitationResult

type ElicitationResult struct {
	Action  tools.ElicitationAction
	Content map[string]any // The submitted form data (only present when action is "accept")
}

ElicitationResult represents the result of an elicitation request.

Returned by the embedder via ResumeElicitation when the user responds to a schema-driven prompt that an MCP server (or the runtime) requested.

type ErrorEvent

type ErrorEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id,omitempty"`
	Error     string `json:"error"`
	Code      string `json:"code,omitempty"`
}

func (*ErrorEvent) GetSessionID added in v1.87.0

func (e *ErrorEvent) GetSessionID() string

GetSessionID makes ErrorEvent satisfy SessionScoped so the existing isRootEvent check in the platform runner correctly distinguishes root-session errors from child-session errors forwarded by runForwarding.

type EvaluationUsageEvent added in v1.143.0

type EvaluationUsageEvent struct {
	AgentContext

	Type       string              `json:"type"`
	SessionID  string              `json:"session_id"`
	Evaluation *session.Evaluation `json:"evaluation"`
}

EvaluationUsageEvent reports a paid assessment independently of its decision.

func (*EvaluationUsageEvent) GetSessionID added in v1.143.0

func (e *EvaluationUsageEvent) GetSessionID() string

type Event

type Event interface {
	GetAgentName() string
}

func AgentChoice

func AgentChoice(agentName, sessionID, content string, messageID ...string) Event

func AgentChoiceReasoning

func AgentChoiceReasoning(agentName, sessionID, content string, messageID ...string) Event

func AgentChoiceReasoningReset added in v1.153.0

func AgentChoiceReasoningReset(agentName, sessionID, messageID string) Event

func AgentInfo

func AgentInfo(agentName, model, description, welcomeMessage string, contextLimit ...int64) Event

func AgentSwitching

func AgentSwitching(switching bool, fromAgent, toAgent string) Event

func Authorization

func Authorization(confirmation tools.ElicitationAction, agentName string) Event

func BackgroundAgentStatus added in v1.151.0

func BackgroundAgentStatus(sessionID, agentName string, running bool) Event

func BudgetExceeded added in v1.112.0

func BudgetExceeded(sessionID, agentName string, br budgetBreach, stopMessage *chat.Message) Event

BudgetExceeded builds the budget_exceeded event. Only the safe fields of stopMessage (role, content, creation time) are copied onto the wire, so a caller cannot leak the other chat.Message fields. A nil stopMessage omits stop_message entirely.

func BudgetUsage added in v1.112.0

func BudgetUsage(sessionID, agentName string, snaps []namedBudgetSnapshot) Event

func ElicitationRequest

func ElicitationRequest(message, mode string, schema any, url, elicitationID, serverElicitationID, sessionID string, meta map[string]any, agentName string) Event

func Error

func Error(msg string) Event

func ErrorForSession added in v1.87.0

func ErrorForSession(sessionID, msg string) Event

ErrorForSession creates an error event tagged with the session ID that produced it. Use this inside the runtime run loop where sess.ID is available so that isRootEvent can distinguish root-session errors from child-session errors forwarded by runForwarding.

func ErrorWithCode added in v1.59.0

func ErrorWithCode(code, msg string) Event

func ErrorWithCodeForSession added in v1.87.0

func ErrorWithCodeForSession(sessionID, code, msg string) Event

ErrorWithCodeForSession creates an error event with a code and session ID. See ErrorForSession for the session-tagging rationale.

func HookBlocked

func HookBlocked(toolCall tools.ToolCall, toolDefinition tools.Tool, message, agentName string) Event

func HookFinished added in v1.53.0

func HookFinished(event hooks.EventType, sessionID string, result *hooks.Result, dispatchErr error, duration time.Duration, agentName string) Event

func HookStarted added in v1.53.0

func HookStarted(event hooks.EventType, sessionID, agentName string) Event

func MCPInitFinished

func MCPInitFinished(agentName string) Event

func MCPInitStarted

func MCPInitStarted(agentName string) Event

func MaxIterationsReached

func MaxIterationsReached(maxIterations int) Event

func MessageAdded

func MessageAdded(sessionID string, msg *session.Message, agentName string) Event

func ModelFallback

func ModelFallback(agentName, failedModel, fallbackModel, reason string, attempt, maxAttempts int) Event

ModelFallback creates a new ModelFallbackEvent.

func NewTokenUsageEvent

func NewTokenUsageEvent(sessionID, agentName string, usage *Usage) Event

NewTokenUsageEvent creates a TokenUsageEvent with the given usage data.

func PartialToolCall

func PartialToolCall(toolCall tools.ToolCall, toolDefinition tools.Tool, agentName string) Event

func Paused added in v1.82.0

func Paused(sessionID, agentName string) Event

func PlanChanged added in v1.119.0

func PlanChanged(scope, name, action string, version int, agentName string) Event

func RAGIndexingCompleted

func RAGIndexingCompleted(ragName, strategyName string) Event

func RAGIndexingProgress

func RAGIndexingProgress(ragName, strategyName string, current, total int, agentName string) Event

func RAGIndexingStarted

func RAGIndexingStarted(ragName, strategyName string) Event

func SessionCompaction

func SessionCompaction(sessionID, status, agentName string) Event

func SessionCompactionCompleted added in v1.99.0

func SessionCompactionCompleted(sessionID, outcome, agentName string) Event

SessionCompactionCompleted is the terminal counterpart of a "started" SessionCompaction event, carrying the outcome ("applied", "skipped" or "failed") so consumers can render an honest completion signal. A "completed" event may arrive without a preceding "started" when a pre-compaction hook vetoes the operation; consumers replaying the event stream should tolerate the unpaired terminal event.

func SessionRecovered added in v1.147.0

func SessionRecovered(sessionID string) Event

func SessionSummary

func SessionSummary(sessionID, summary, agentName string, firstKeptEntry int, cost float64, model string, usage *chat.Usage) Event

SessionSummary builds the event announcing an applied compaction summary. cost is the dollar cost of producing the summary; 0 when nothing was billed (hook-supplied summaries, status-only remote notifications). model and usage attribute that cost to the model that generated the summary; empty/nil when no LLM call ran.

func SessionTitle

func SessionTitle(sessionID, title string) Event

func ShellCommandFinished added in v1.144.0

func ShellCommandFinished(id, command, output string, err error) Event

func ShellCommandOutput added in v1.144.0

func ShellCommandOutput(id, output string) Event

func ShellCommandStarted added in v1.144.0

func ShellCommandStarted(id, command string) Event

func ShellOutput

func ShellOutput(output string) Event

func StreamStarted

func StreamStarted(sessionID, agentName string) Event

func StreamStopped

func StreamStopped(sessionID, agentName, reason string) Event

func SubSessionCompleted

func SubSessionCompleted(parentSessionID string, subSession any, agentName string) Event

func TeamInfo

func TeamInfo(availableAgents []AgentDetails, currentAgent string) Event

func ToolCall

func ToolCall(toolCall tools.ToolCall, toolDefinition tools.Tool, agentName string) Event

func ToolCallConfirmation

func ToolCallConfirmation(toolCall tools.ToolCall, toolDefinition tools.Tool, agentName string, metadata map[string]string) Event

func ToolCallOutput added in v1.70.2

func ToolCallOutput(toolCallID string, toolDefinition tools.Tool, output, agentName string) Event

func ToolCallResponse

func ToolCallResponse(toolCallID string, toolDefinition tools.Tool, result *tools.ToolCallResult, response, agentName string) Event

func ToolCallsRetracted added in v1.153.0

func ToolCallsRetracted(toolCallIDs []string, agentName string) Event

func ToolsetInfo

func ToolsetInfo(availableTools int, loading bool, agentName string) Event

func UserMessage

func UserMessage(message, sessionID string, multiContent []chat.MessagePart, sessionPos ...int) Event

func Warning

func Warning(message, agentName string) Event

type EventObserver added in v1.53.0

type EventObserver interface {
	// OnRunStart fires once when [LocalRuntime.RunStream] begins, before
	// any event is dispatched. Use it for one-shot lifecycle work like
	// persisting initial session metadata.
	OnRunStart(ctx context.Context, sess *session.Session)
	// OnEvent fires once per event, after the runtime emits it but
	// before the consumer's channel receives it. Observers cannot
	// modify or suppress events (a future extension may relax this);
	// to drop an event from persistence, simply ignore it inside
	// OnEvent.
	OnEvent(ctx context.Context, sess *session.Session, event Event)
}

EventObserver receives the runtime's event stream as it's produced. Implementations subscribe to lifecycle moments and act on them — persisting to a store, forwarding to a metrics pipeline, writing an audit transcript, etc.

Concurrency: the runtime invokes observers synchronously from the goroutine that forwards events to the consumer's channel, in registration order. A slow observer therefore back-pressures both downstream observers and the consumer; long-running work (network I/O, file syncing) should fan out to a private goroutine.

Errors: observers do not return errors. The runtime cannot recover from a misbehaving observer (it can't unregister it mid-stream and can't ask the consumer to retry), so an observer must log internally and never panic. The contract is "best-effort observation" rather than "all-or-nothing transactional".

Observers see every event the runtime emits, including sub-session events (from delegated tasks via transfer_task) and SessionScoped-mismatch events. Filtering is the observer's responsibility; see PersistenceObserver for the canonical pattern.

type EventSink added in v1.59.0

type EventSink interface {
	// Emit delivers an event to the sink. The default implementation
	// preserves back-pressure: if the consumer is slow, Emit blocks
	// until the event can be delivered. Implementations must still be
	// panic-safe so a closed channel does not crash the caller.
	Emit(event Event)
}

EventSink is the write side of the runtime's event stream. Methods that produce events accept an EventSink instead of a raw chan Event, decoupling event producers from the channel implementation.

Implementations must be safe for concurrent use: multiple goroutines may call Emit simultaneously (e.g. tool-call handlers running in parallel).

func NewChannelSink added in v1.59.0

func NewChannelSink(ch chan<- Event) EventSink

NewChannelSink returns an EventSink that writes to ch. This is the standard bridge between the runtime's EventSink-based internals and external callers that create raw event channels (e.g. app.go, tests).

type EventSinkFunc added in v1.59.0

type EventSinkFunc func(Event)

EventSinkFunc adapts a plain function into an EventSink, following the same adapter pattern as http.HandlerFunc. This is convenient for tests and one-off callbacks that don't need a full struct.

func (EventSinkFunc) Emit added in v1.59.0

func (f EventSinkFunc) Emit(e Event)

type HookBlockedEvent

type HookBlockedEvent struct {
	AgentContext

	Type           string         `json:"type"`
	ToolCall       tools.ToolCall `json:"tool_call"`
	ToolDefinition tools.Tool     `json:"tool_definition"`
	Message        string         `json:"message"`
}

HookBlockedEvent is sent when a pre-tool hook blocks a tool call

type HookFinishedEvent added in v1.53.0

type HookFinishedEvent struct {
	AgentContext

	Type       string          `json:"type"`
	SessionID  string          `json:"session_id"`
	HookEvent  hooks.EventType `json:"hook_event"`
	DurationMs int64           `json:"duration_ms"`
	Allowed    bool            `json:"allowed"`
	Error      string          `json:"error,omitempty"`
	Message    string          `json:"message,omitempty"`
}

HookFinishedEvent is emitted when a configured hook event completes.

func (*HookFinishedEvent) GetSessionID added in v1.53.0

func (e *HookFinishedEvent) GetSessionID() string

type HookStartedEvent added in v1.53.0

type HookStartedEvent struct {
	AgentContext

	Type      string          `json:"type"`
	SessionID string          `json:"session_id"`
	HookEvent hooks.EventType `json:"hook_event"`
}

HookStartedEvent is emitted when a configured hook event begins dispatching.

func (*HookStartedEvent) GetSessionID added in v1.53.0

func (e *HookStartedEvent) GetSessionID() string

type LiveSession added in v1.104.0

type LiveSession struct {
	SessionID    string `json:"session_id"`
	AgentName    string `json:"agent_name"`
	InputTokens  int64  `json:"input_tokens"`
	OutputTokens int64  `json:"output_tokens"`
	ContextLimit int64  `json:"context_limit"`
	// Current marks the caller's current root session. It is listed even
	// while idle (no active stream), unlike child rows which exist only
	// while their RunStream is live.
	Current bool `json:"current"`

	// CompactionModel is the identity ("provider/model") of the row's agent
	// dedicated compaction model, set only when it actually caps ContextLimit
	// below the primary model's own window. Render-unused in the /context
	// dialog (the header's single cap statement is authoritative there); kept
	// on the struct as part of the JSON/API surface for other consumers.
	CompactionModel string `json:"compaction_model,omitempty"`
	// PrimaryContextLimit is the primary model's own context window, set
	// only alongside CompactionModel. Render-unused today (see CompactionModel).
	PrimaryContextLimit int64 `json:"primary_context_limit,omitempty"`
}

LiveSession is one row of the /context team view: a currently running RunStream session (or the idle current root session) with its agent identity, session identity and context budget. Token counts come from the session's provider-reported cumulative usage; ContextLimit is 0 when the effective model's window cannot be resolved (harness-backed agents, models absent from the catalogue).

func (LiveSession) ShortID added in v1.104.0

func (s LiveSession) ShortID() string

ShortID returns the first 8 characters of the session ID, enough to disambiguate concurrent runs of the same agent in UI listings.

func (LiveSession) UsedTokens added in v1.104.0

func (s LiveSession) UsedTokens() int64

UsedTokens returns the session's current context occupancy estimate.

type LoadTeamRequest added in v1.58.0

type LoadTeamRequest struct {
	Source         config.Source         `json:"-"`
	ModelOverrides []string              `json:"model_overrides,omitempty"`
	PromptFiles    []string              `json:"prompt_files,omitempty"`
	RunConfig      *config.RuntimeConfig `json:"-"`
}

LoadTeamRequest is the typed input to a backend's team load. It carries everything the team loader needs: the resolved agent source plus the runtime config and the per-flag knobs the user supplied.

LocalBackend consumes this struct directly. The same struct is the payload a future RemoteBackend marshals over the wire so the server runs teamloader.LoadWithConfig with identical inputs.

JSON tags reflect the wire contract being designed. Fields that don't yet have a wire-friendly representation (the Source interface, the RuntimeConfig with its embedded sync.Mutex and environment.Provider) are tagged json:"-" until they get one. Round-trip tests live in payload_test.go.

type LocalRuntime

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

LocalRuntime manages the execution of agents

func NewLocalRuntime

func NewLocalRuntime(ctx context.Context, agents *team.Team, opts ...Opt) (*LocalRuntime, error)

NewLocalRuntime creates a new LocalRuntime without the persistence wrapper. This is useful for testing or when persistence is handled externally.

func (*LocalRuntime) AgentConfigInfo added in v1.88.0

func (r *LocalRuntime) AgentConfigInfo(ctx context.Context, name string) inspection.AgentConfigInfo

AgentConfigInfo inspects an agent without starting tools or drivers.

func (*LocalRuntime) AgentExecutionCapabilities added in v1.150.0

func (r *LocalRuntime) AgentExecutionCapabilities(name string) *inspection.ExecutionCapabilities

AgentExecutionCapabilities inspects the named agent without starting tools or drivers. Unknown agents return nil; callers must not interpret absence as native support.

func (*LocalRuntime) AgentThinkingConfiguration added in v1.144.0

func (r *LocalRuntime) AgentThinkingConfiguration(agentName string) ([]effort.Level, effort.Level)

AgentThinkingConfiguration reports a conservative, network-free single-model selector. A blank current level means an unset, adaptive, or token-based budget, not "none".

func (*LocalRuntime) AgentToolsetStatuses added in v1.88.0

func (r *LocalRuntime) AgentToolsetStatuses(name string) []tools.ToolsetStatus

AgentToolsetStatuses returns one ToolsetStatus per toolset of the named agent, in declaration order. It mirrors CurrentAgentToolsetStatuses but for an arbitrary agent and is side-effect-free: it reads each toolset's live lifecycle (state, kind, last error, restart count) without starting it. Unknown agents yield nil, so callers degrade gracefully.

func (*LocalRuntime) AvailableModels

func (r *LocalRuntime) AvailableModels(ctx context.Context) []modelcatalog.ModelChoice

AvailableModels returns configured and discovered choices for the active agent.

func (*LocalRuntime) CancelFollowUp added in v1.139.0

func (r *LocalRuntime) CancelFollowUp(_ context.Context, id string) bool

func (*LocalRuntime) CancelSteer added in v1.139.0

func (r *LocalRuntime) CancelSteer(_ context.Context, id string) bool

func (*LocalRuntime) Close

func (r *LocalRuntime) Close() error

Close releases resources held by the runtime. The session store is *not* closed here: it is provided by the embedder via WithSessionStore and may be shared with other runtimes (e.g. the TUI's session spawner reuses the same store across spawned sessions, so closing it here would break later session lookups). Embedders that own the store are responsible for closing it once when their process is shutting down.

func (*LocalRuntime) CommandEvaluatorFactory added in v1.135.0

func (r *LocalRuntime) CommandEvaluatorFactory() CommandEvaluatorFactory

CommandEvaluatorFactory returns the effective slash-command evaluator factory. Runtime decorators passed to ResolveCommand should forward this method to preserve instance configuration, including an explicitly disabled evaluator.

func (*LocalRuntime) CompactLiveSession added in v1.104.0

func (r *LocalRuntime) CompactLiveSession(_ context.Context, sessionID, additionalPrompt string, events EventSink) error

CompactLiveSession queues an explicit manual compaction for the identified live session. The request is accepted non-blockingly and executes on the target session's own run goroutine at a safe iteration boundary (or during its final teardown drain), so it can never interleave with an in-flight model turn. Compaction and usage events are emitted to events; when hooks veto the compaction before any terminal event, a completed/skipped event is synthesized so the requester always observes a terminal signal.

It returns an error when sessionID is not a live session (unknown or already finished) or when a request is already pending for it.

func (*LocalRuntime) ContextBreakdown added in v1.99.0

func (r *LocalRuntime) ContextBreakdown(ctx context.Context, sess *session.Session) (*ContextBreakdown, error)

ContextBreakdown computes the estimated context-window composition for sess, categorizing the output of session.Session.GetMessagesAndLastSummary and adding the tool definitions and prompt files that accompany every model call.

Tool listing failures and unreadable prompt files degrade gracefully: the corresponding category is computed from whatever could be gathered and the failure is logged, so a broken toolset never hides the rest of the data.

func (*LocalRuntime) CurrentAgent

func (r *LocalRuntime) CurrentAgent() *agent.Agent

CurrentAgent returns the current agent

func (*LocalRuntime) CurrentAgentCommands

func (r *LocalRuntime) CurrentAgentCommands(context.Context) types.Commands

func (*LocalRuntime) CurrentAgentInfo

func (r *LocalRuntime) CurrentAgentInfo(context.Context) CurrentAgentInfo

func (*LocalRuntime) CurrentAgentName

func (r *LocalRuntime) CurrentAgentName(context.Context) string

func (*LocalRuntime) CurrentAgentSkillsToolset

func (r *LocalRuntime) CurrentAgentSkillsToolset() *skills.ToolSet

CurrentAgentSkillsToolset returns the skills toolset for the current agent, or nil if not enabled.

func (*LocalRuntime) CurrentAgentSubAgentNames

func (r *LocalRuntime) CurrentAgentSubAgentNames() []string

CurrentAgentSubAgentNames implements agenttool.Runner. It is the legacy shared current-agent resolver, kept so the Runner contract stays source-compatible; HandleRun never takes this path for LocalRuntime because the session-aware SubAgentNames above is preferred.

func (*LocalRuntime) CurrentAgentThinkingLevels added in v1.112.0

func (r *LocalRuntime) CurrentAgentThinkingLevels(ctx context.Context) []effort.Level

CurrentAgentThinkingLevels returns the thinking-effort levels the current agent's active model supports, or nil when the runtime has no model switcher configured, the agent/model can't be resolved, or the model does not support thinking at all. Backs the /effort argument completer (#3731): candidates must come from this resolution, not the static effort vocabulary, because SetAgentThinkingLevel hard-rejects any level outside it.

func (*LocalRuntime) CurrentAgentTools

func (r *LocalRuntime) CurrentAgentTools(ctx context.Context) ([]tools.Tool, error)

CurrentAgentTools returns the tools available to the current agent. This starts toolsets if needed; returned handlers enforce this agent's skill policy without permitting embedded commands outside a tool call.

func (*LocalRuntime) CurrentAgentToolsetStatuses added in v1.54.0

func (r *LocalRuntime) CurrentAgentToolsetStatuses() []tools.ToolsetStatus

CurrentAgentToolsetStatuses returns one ToolsetStatus per toolset of the active agent. The list is in declaration order. Toolsets that wrap another (StartableToolSet, Multiplexer) are unwrapped so the inner supervisor's state is visible.

func (*LocalRuntime) CurrentMCPPrompts

func (r *LocalRuntime) CurrentMCPPrompts(ctx context.Context) map[string]tools.PromptInfo

CurrentMCPPrompts returns the available MCP prompts from all active MCP toolsets for the current agent. It discovers prompts by calling ListPrompts on each MCP toolset and aggregates the results into a map keyed by prompt name.

func (*LocalRuntime) CycleAgentThinkingLevel added in v1.78.0

func (r *LocalRuntime) CycleAgentThinkingLevel(ctx context.Context, agentName string) (effort.Level, error)

CycleAgentThinkingLevel implements Runtime.CycleAgentThinkingLevel for LocalRuntime. It reads the agent's current effective model, advances the thinking-effort level by one step through the levels that specific model supports (see modelinfo.SupportedThinkingLevels), re-creates the provider(s) with the new level, and installs them as a runtime override.

func (*LocalRuntime) EmitAgentInfo added in v1.78.0

func (r *LocalRuntime) EmitAgentInfo(ctx context.Context, events EventSink)

EmitAgentInfo implements Runtime.EmitAgentInfo: it refreshes the agent and team display without touching toolset discovery.

func (*LocalRuntime) EmitElicitationRequestForTesting added in v1.110.0

func (r *LocalRuntime) EmitElicitationRequestForTesting(event Event)

EmitElicitationRequestForTesting invokes whatever OnElicitationRequest sink is currently registered, exactly as elicitationHandler would, but without the real MCP elicitation handshake. elicitationHandler is unexported, so callers outside this package (e.g. pkg/server) cannot drive it directly to prove a *specific* runtime instance has the expected sink wired; this gives them a seam to do that instead of reconstructing the sink separately and invoking it in isolation, which would pass even if the runtime under test was never actually wired up (#3584 re-review should-fix 1).

func (*LocalRuntime) EmitStartupInfo

func (r *LocalRuntime) EmitStartupInfo(ctx context.Context, sess *session.Session, events EventSink)

EmitStartupInfo emits initial agent, team, and toolset information for immediate sidebar display. When sess is non-nil and contains token data, a TokenUsageEvent is also emitted so that the sidebar can display context usage percentage on session restore.

func (*LocalRuntime) ExecuteMCPPrompt

func (r *LocalRuntime) ExecuteMCPPrompt(ctx context.Context, promptName string, arguments map[string]string) (string, error)

ExecuteMCPPrompt executes an MCP prompt with provided arguments and returns the content.

func (*LocalRuntime) FollowUp added in v1.44.0

func (r *LocalRuntime) FollowUp(ctx context.Context, msg QueuedMessage) error

FollowUp enqueues a message to be processed after the current agent turn finishes. Unlike Steer, follow-ups are popped one at a time and each gets a full undivided agent turn.

func (*LocalRuntime) HasActiveWork added in v1.144.0

func (r *LocalRuntime) HasActiveWork() bool

HasActiveWork is a cheap quiescence check; callers must separately prevent new foreground runs.

func (*LocalRuntime) LiveSessions added in v1.104.0

func (r *LocalRuntime) LiveSessions(ctx context.Context, current *session.Session) []LiveSession

LiveSessions returns the caller's current root session followed by every currently live RunStream session that descends from it (foreground children and background agent tasks, nested sub-agents included). Descent is decided by each entry's tree root ID, cached at registration, so a nested background agent stays listed after its intermediate foreground parent finished and unregistered. Live sessions rooted outside current's tree (e.g. a stale root stream still draining after App.NewSession/ReplaceSession swapped the current session, and its descendants) are excluded. current may be nil, in which case every live entry is listed. Child rows are stable-sorted by agent name then session ID, so concurrent runs of the same agent stay distinct and the ordering is deterministic. current is listed even while idle.

func (*LocalRuntime) MirrorsElicitationOnRunStream added in v1.111.0

func (r *LocalRuntime) MirrorsElicitationOnRunStream()

MirrorsElicitationOnRunStream marks LocalRuntime as a runtime whose OnElicitationRequest sink is the single, exactly-once delivery point for an elicitation request even though elicitationHandler ALSO best-effort- sends the very same event on the RunStream channel, for the benefit of out-of-process consumers reading RunStream directly (see elicitationBridge). Embedders that forward RunStream events verbatim into their own event bus (e.g. pkg/app.App) use this marker — via an optional capability check, since it is not part of the Runtime interface — to know they must skip *ElicitationRequestEvent to avoid delivering the same request twice.

RemoteRuntime deliberately does NOT implement this: its OnElicitationRequest is a no-op, so the copy on its RunStream is the ONLY delivery and callers must not skip it (#3584 review — an earlier fix skipped unconditionally and silently dropped every remote elicitation).

func (*LocalRuntime) OnBackgroundEvent added in v1.99.0

func (r *LocalRuntime) OnBackgroundEvent(handler func(Event))

OnBackgroundEvent receives lifecycle and usage events from detached agent tasks.

func (*LocalRuntime) OnBackgroundEventWithContext added in v1.147.0

func (r *LocalRuntime) OnBackgroundEventWithContext(handler func(context.Context, Event))

OnBackgroundEventWithContext preserves detached producer ownership.

func (*LocalRuntime) OnElicitationRequest added in v1.110.0

func (r *LocalRuntime) OnElicitationRequest(handler func(Event))

OnElicitationRequest registers a handler invoked whenever an MCP toolset raises an elicitation request. This is the reliable route for background-job elicitations (run_background_agent): their RunStream runs on a detached goroutine and can race concurrent streams for the bridge's single channel slot (#3584), so elicitationHandler calls this sink directly, synchronously, and unconditionally — before it ever touches the best-effort bridge — as the single, exactly-once delivery point. Embedders (e.g. the TUI's App, or the API server for session-scoped SSE delivery) register a handler here that forwards the event to their UI/transport.

func (*LocalRuntime) OnElicitationRequestWithContext added in v1.147.0

func (r *LocalRuntime) OnElicitationRequestWithContext(handler func(context.Context, Event))

OnElicitationRequestWithContext preserves the originating run's ownership.

func (*LocalRuntime) OnToolsChanged

func (r *LocalRuntime) OnToolsChanged(handler func(Event))

OnToolsChanged registers a handler that is called when an MCP toolset reports a tool list change outside of a RunStream. This allows the UI to update the tool count immediately. The runtime subscribes to the team's toolsets on behalf of the handler, replacing only its own previous subscriptions so runtimes sharing a toolset do not displace each other; a nil handler unsubscribes.

func (*LocalRuntime) PermissionsInfo

func (r *LocalRuntime) PermissionsInfo() *PermissionsInfo

PermissionsInfo returns the team-level permission patterns. Returns nil if no permissions are configured.

func (*LocalRuntime) QueueStatus added in v1.59.0

func (r *LocalRuntime) QueueStatus() QueueStatus

func (*LocalRuntime) ReadSkillContent added in v1.143.0

func (r *LocalRuntime) ReadSkillContent(ctx context.Context, sess *session.Session, name string) (string, error)

func (*LocalRuntime) RefreshModelsCatalog added in v1.104.0

func (r *LocalRuntime) RefreshModelsCatalog(ctx context.Context) error

RefreshModelsCatalog forces a refetch of the models.dev catalog backing the model picker, bypassing the store's refresh interval. It returns ErrUnsupported when the runtime's model store cannot refresh (e.g. an in-memory test store).

func (*LocalRuntime) ResetStartupInfo

func (r *LocalRuntime) ResetStartupInfo()

ResetStartupInfo resets the startup info emission flag. This should be called when replacing a session to allow re-emission of agent, team, and toolset info to the UI.

func (*LocalRuntime) ResolveGeneratedFile added in v1.138.0

ResolveGeneratedFile reads an artifact only after revalidating its manifest.

func (*LocalRuntime) RestartToolset added in v1.54.0

func (r *LocalRuntime) RestartToolset(ctx context.Context, name string) error

RestartToolset locates the named toolset on the active agent and asks its canonical lifecycle wrapper to restart it in place. The wrapper serializes the operation with start/stop and keeps its lifecycle state in sync with the underlying supervisor.

Returns an error when:

  • no toolset matches name (matching uses the same logic as the /tools dialog: the toolset's Name() if any, otherwise its description),
  • no matching toolset supports restart,
  • the supervisor itself returned an error (timeout, classified transport failure, etc.).

Display names are not guaranteed unique (a YAML name: can shadow a built-in), so non-restartable matches are skipped rather than aborting: the first restartable toolset with the given name wins.

func (*LocalRuntime) Resume

func (r *LocalRuntime) Resume(_ context.Context, req ResumeRequest)

func (*LocalRuntime) ResumeElicitation

func (r *LocalRuntime) ResumeElicitation(ctx context.Context, action tools.ElicitationAction, content map[string]any, elicitationID ...string) error

ResumeElicitation sends an elicitation response back to a waiting elicitation request. When elicitationID is non-empty it is routed to that specific request; when empty, it falls back to resolving the sole pending request for backward compatibility with callers that predate per-request correlation. Returns an error if no matching elicitation is in progress.

Unlike the old shared-channel implementation, this never blocks on ctx: each waiter channel is buffered (capacity 1) and registered before its request event is emitted, so resolving it is always a non-blocking map lookup plus a buffered send — there is no TOCTOU window to race. A resolve that raced a ctx-cancellation on the handler side is decided by an atomic terminal state (see elicitationWaiter), so a true here always means the response will reach the caller, never a discarded one.

func (*LocalRuntime) Run

func (r *LocalRuntime) Run(ctx context.Context, sess *session.Session) ([]session.Message, error)

Run executes the agent loop synchronously and returns the final session messages. This is a convenience wrapper around RunStream for non-streaming callers.

func (*LocalRuntime) RunAgent

RunAgent implements agenttool.Runner. It starts a sub-agent synchronously and blocks until completion or cancellation.

Background tasks inherit the parent session's permissions because there is no user present to respond to interactive approval prompts during async execution. Tool calls that result in an "Ask" outcome will be auto-denied by the dispatcher due to the non-interactive context.

func (*LocalRuntime) RunSkillFork added in v1.62.0

func (r *LocalRuntime) RunSkillFork(ctx context.Context, sess *session.Session, args skills.RunSkillArgs, evts EventSink) (*tools.ToolCallResult, error)

RunSkillFork executes a `context: fork` skill as an isolated sub-session. The expanded SKILL.md body becomes the child's first user message; the agent's own system prompt is preserved. Entry point for callers outside a tool call (the App's slash-command path); run_skill goes through [LocalRuntime.handleRunSkill].

func (*LocalRuntime) RunStream

func (r *LocalRuntime) RunStream(ctx context.Context, sess *session.Session) <-chan Event

RunStream starts the agent's interaction loop and returns a channel of events. The returned channel is closed when the loop terminates (success, error, or context cancellation). Each iteration: sends messages to the model, streams the response, executes any tool calls, and loops until the model signals stop or the iteration limit is reached.

func (*LocalRuntime) SessionStore

func (r *LocalRuntime) SessionStore() session.Store

SessionStore returns the session store for browsing/loading past sessions.

func (*LocalRuntime) SetAgentModel

func (r *LocalRuntime) SetAgentModel(ctx context.Context, agentName, modelRef string) error

SetAgentModel implements Runtime.SetAgentModel for LocalRuntime.

func (*LocalRuntime) SetAgentThinkingLevel added in v1.94.0

func (r *LocalRuntime) SetAgentThinkingLevel(ctx context.Context, agentName string, level effort.Level) (effort.Level, error)

SetAgentThinkingLevel implements Runtime.SetAgentThinkingLevel for LocalRuntime. The requested level must be one the agent's current model supports; otherwise an error listing the supported levels is returned.

func (*LocalRuntime) SetCurrentAgent

func (r *LocalRuntime) SetCurrentAgent(_ context.Context, agentName string) error

func (*LocalRuntime) SetRecallHandler added in v1.99.0

func (r *LocalRuntime) SetRecallHandler(handler RecallHandler)

SetRecallHandler registers an embedder-owned wake-up path for tool recalls. When unset, recalls fall back to the steer queue and are consumed by the next active RunStream.

func (*LocalRuntime) Steer added in v1.44.0

func (r *LocalRuntime) Steer(ctx context.Context, msg QueuedMessage) error

Steer enqueues a user message for urgent mid-turn injection into the running agent loop. The message will be picked up after the current batch of tool calls finishes but before the loop checks whether to stop.

func (*LocalRuntime) SubAgentNames added in v1.121.0

func (r *LocalRuntime) SubAgentNames(sess *session.Session) []string

SubAgentNames implements agenttool.SessionSubAgentResolver, which HandleRun prefers over the legacy CurrentAgentSubAgentNames. The sub-agent list resolves from the calling session — a pinned background session yields its pinned agent — so a nested run_background_agent dispatched from a detached background task is validated against the actual caller, not whatever the concurrent foreground loop's shared current agent points at (#3886).

func (*LocalRuntime) Summarize

func (r *LocalRuntime) Summarize(ctx context.Context, sess *session.Session, additionalPrompt string, events EventSink)

Summarize generates a summary for the session based on the conversation history. The additionalPrompt parameter allows users to provide additional instructions for the summarization (e.g., "focus on code changes" or "include action items").

Summarize is the public entry point used by user-driven /compact actions; it reports compactionReasonManual to BeforeCompaction / AfterCompaction hooks and "manual" to PreCompact hooks. Internal callers (proactive threshold, overflow recovery) use [LocalRuntime.compactWithReason] directly to forward a more specific reason.

func (*LocalRuntime) SupportsModelSwitching added in v1.58.0

func (r *LocalRuntime) SupportsModelSwitching() bool

SupportsModelSwitching reports whether the runtime was built with a [ModelSwitcherConfig], i.e. whether [SetAgentModel] / [AvailableModels] will return real data instead of the no-config empty path.

func (*LocalRuntime) TitleGenerator

func (r *LocalRuntime) TitleGenerator(ctx context.Context) *sessiontitle.Generator

TitleGenerator returns a title generator for automatic session title generation, or nil when no configured model is a usable title candidate (see sessiontitle.New). A harness agent has no models: its driver titles the session when it implements harness.Completer.

func (*LocalRuntime) TogglePause added in v1.55.0

func (r *LocalRuntime) TogglePause(context.Context) (bool, error)

TogglePause toggles whether runStreamLoop pauses at iteration boundaries. Returns true if now paused. The pause takes effect as soon as the in-flight LLM request and its tool calls complete.

The error return is reserved for runtimes that need to talk to a remote service to flip the flag; LocalRuntime always returns nil.

Internally, pauseCh is non-nil and open while paused; closing it on resume wakes every goroutine waiting in waitIfPaused.

func (*LocalRuntime) UpdateSessionTitle

func (r *LocalRuntime) UpdateSessionTitle(ctx context.Context, sess *session.Session, title string) error

UpdateSessionTitle persists the session title via the session store.

func (*LocalRuntime) WithAgentModel added in v1.53.0

func (r *LocalRuntime) WithAgentModel(ctx context.Context, agentName, modelRef string) (restore func(), err error)

WithAgentModel applies modelRef as a model override on the named agent and returns a function that restores the previous override safely.

The returned restore func is always non-nil. On success it uses pointer-identity compare-and-swap on the agent's override, so a concurrent change made between the apply and the restore (e.g. by the TUI model picker) is preserved instead of being clobbered. The post- apply snapshot is captured atomically with the store inside SetModelOverride, so there is no window where a concurrent change could be misattributed to this scope. On error the agent is left untouched and restore is a no-op, so callers can always defer it without nil-checking.

type MCPInitFinishedEvent

type MCPInitFinishedEvent struct {
	AgentContext

	Type string `json:"type"`
}

type MCPInitStartedEvent

type MCPInitStartedEvent struct {
	AgentContext

	Type string `json:"type"`
}

MCPInitStartedEvent is for MCP initialization lifecycle events

type MaxIterationsReachedEvent

type MaxIterationsReachedEvent struct {
	AgentContext

	Type          string `json:"type"`
	MaxIterations int    `json:"max_iterations"`
}

type MessageAddedEvent

type MessageAddedEvent struct {
	AgentContext

	Type      string           `json:"type"`
	SessionID string           `json:"session_id"`
	Message   *session.Message `json:"-"`
	// Completion metadata remains available when Message is omitted on the wire.
	AssistantMessageEmpty bool `json:"assistant_message_empty,omitempty"`
	HasToolCalls          bool `json:"has_tool_calls,omitempty"`
}

MessageAddedEvent is emitted when a message is added to the session. This event is used by the PersistentRuntime wrapper to persist messages.

func (*MessageAddedEvent) GetSessionID added in v1.32.1

func (e *MessageAddedEvent) GetSessionID() string

type MessageQueue added in v1.44.0

type MessageQueue interface {
	// Enqueue adds a message to the queue. Returns false if the queue is
	// full or the context is cancelled.
	Enqueue(ctx context.Context, msg QueuedMessage) bool
	// Dequeue removes and returns the next message from the queue.
	// Returns the message and true, or a zero value and false if the
	// queue is empty. Must not block.
	Dequeue(ctx context.Context) (QueuedMessage, bool)
	// Drain returns all pending messages and removes them from the queue.
	// Must not block — if the queue is empty it returns nil.
	Drain(ctx context.Context) []QueuedMessage
}

MessageQueue is the interface for storing messages that are injected into the agent loop. Implementations must be safe for concurrent use: Enqueue is called from API handlers while Dequeue/Drain are called from the agent loop goroutine.

The default implementation is NewInMemoryMessageQueue. Callers that need durable or distributed storage can provide their own implementation via the WithSteerQueue or WithFollowUpQueue options.

func NewInMemoryMessageQueue added in v1.44.0

func NewInMemoryMessageQueue(capacity int) MessageQueue

NewInMemoryMessageQueue creates an in-memory FIFO queue with the given capacity.

type MessageTransform added in v1.54.0

type MessageTransform func(ctx context.Context, in *hooks.Input, msgs []chat.Message) ([]chat.Message, error)

MessageTransform is the in-process-only handler signature for a before_llm_call transform that rewrites the chat messages about to be sent to the model. It receives the full message slice in chain order and returns the (possibly-rewritten) replacement.

Transforms are intentionally a runtime-private contract: the cost of JSON-roundtripping a full conversation through the cross-process hook protocol would be prohibitive, so command and model hooks cannot rewrite messages. Embedders register transforms via WithMessageTransform; the runtime ships BuiltinStripUnsupportedModalities out of the box.

Transforms run AFTER the standard before_llm_call gate (see [LocalRuntime.executeBeforeLLMCallHooks]) — a hook that wants to abort the call should target the gate, not a transform.

Returning a non-nil error logs a warning and falls through to the previous message slice; a transform failure must never break the run loop.

type MessageUsage

type MessageUsage struct {
	chat.Usage

	Cost         float64
	Model        string
	FinishReason chat.FinishReason `json:"finish_reason,omitempty"`
}

MessageUsage contains per-message usage data to include in TokenUsageEvent. It embeds chat.Usage and adds Cost, Model, and FinishReason fields.

type ModelFallbackEvent

type ModelFallbackEvent struct {
	AgentContext

	Type          string `json:"type"`
	FailedModel   string `json:"failed_model"`
	FallbackModel string `json:"fallback_model"`
	Reason        string `json:"reason"`
	Attempt       int    `json:"attempt"`      // Current attempt number (1-indexed)
	MaxAttempts   int    `json:"max_attempts"` // Total attempts allowed for this model
}

ModelFallbackEvent is emitted when the runtime switches to a fallback model after the previous model in the chain fails. This can happen due to: - Retryable errors (5xx, timeouts) after exhausting retries - Non-retryable errors (429, 4xx) which skip retries and move immediately to fallback

type ModelStore

type ModelStore interface {
	GetModel(ctx context.Context, id modelsdev.ID) (*modelsdev.Model, error)
	GetDatabase(ctx context.Context) (*modelsdev.Database, error)
}

type Opt

type Opt func(*LocalRuntime)

func WithAutoInjector added in v1.58.0

func WithAutoInjector(inj builtins.AutoInjector) Opt

WithAutoInjector adds an builtins.AutoInjector that augments every per-agent hook configuration during executor build. The canonical use case is the snapshot controller returned by builtins.RegisterSnapshot: pass the same controller to the App via app.WithSnapshotController so /undo and friends drive the same instance that captures the checkpoints.

Multiple calls accumulate; injectors run in registration order.

func WithBudget added in v1.112.0

func WithBudget(cfg *latest.BudgetConfig) Opt

WithBudget sets the run-wide budget: the cost, token and wall-clock ceilings that stop a run once crossed, regardless of which agent spends. A nil or all-zero config leaves runs unbudgeted, which is the default.

func WithClock added in v1.53.0

func WithClock(now func() time.Time) Opt

WithClock replaces the runtime's clock. Defaults to time.Now. Tests that need deterministic timestamps (assistant message CreatedAt, fallback cooldown windows, tool-call latency) can pass a fake clock so assertions don't depend on wall-clock advancement.

func WithCommandEvaluatorFactory added in v1.135.0

func WithCommandEvaluatorFactory(factory CommandEvaluatorFactory) Opt

WithCommandEvaluatorFactory selects the slash-command evaluator for this runtime. Passing nil leaves JavaScript expressions unexpanded, even when a global evaluator is registered. Without this option, the global evaluator is used.

func WithCurrentAgent

func WithCurrentAgent(agentName string) Opt

func WithElicitationHandler added in v1.144.0

func WithElicitationHandler(handler tools.ElicitationHandler) Opt

WithElicitationHandler handles requests synchronously instead of emitting elicitation events. Non-interactive runtimes still decline; the handler must honor the request context.

func WithEnv

func WithEnv(env []string) Opt

WithEnv sets the environment variables for hooks execution

func WithEventObserver added in v1.53.0

func WithEventObserver(o EventObserver) Opt

WithEventObserver appends o to the runtime's observer chain. Observers are invoked in registration order, synchronously, on every event the runtime produces. Multiple calls are additive.

The runtime auto-registers a PersistenceObserver for the configured session store; users do not need to wire persistence themselves. Custom observers (telemetry, audit, metrics, A2A forward) compose alongside that one.

func WithEventObserverFactory added in v1.153.0

func WithEventObserverFactory(factory func() EventObserver) Opt

WithEventObserverFactory creates an independent observer for each RunStream. Factories run synchronously before OnRunStart; nil results are ignored.

func WithFollowUpQueue added in v1.44.0

func WithFollowUpQueue(q MessageQueue) Opt

WithFollowUpQueue sets a custom MessageQueue for end-of-turn follow-up messages. If not provided, an in-memory buffered queue is used.

func WithHarnessFactory added in v1.135.0

func WithHarnessFactory(factory harness.Factory) Opt

WithHarnessFactory selects the harness driver for this runtime only. Passing nil disables harnesses, even when a global driver is registered. Without this option, the runtime uses RegisterHarness's global driver.

func WithHooksRegistry added in v1.58.0

func WithHooksRegistry(reg *hooks.Registry) Opt

WithHooksRegistry plugs a pre-populated hooks.Registry into the runtime instead of letting it allocate a fresh one. Embedders use this to pre-register builtins they own (today snapshot, tomorrow any custom builtin) so the auto-injection chain set up by WithAutoInjector resolves against the same registry.

The runtime continues to register its own stateless and closure-bound builtins (add_date, max_iterations, cache_response, unload, ...) on top of the supplied registry, so the embedder only needs to install entries that the runtime can't construct itself.

func WithManagedOAuth

func WithManagedOAuth(managed bool) Opt

func WithMaxOverflowCompactions added in v1.53.0

func WithMaxOverflowCompactions(n int) Opt

WithMaxOverflowCompactions overrides how many consecutive context-overflow auto-compactions the run loop is allowed to attempt before surfacing the error. Defaults to defaultMaxOverflowCompactions (1).

Tests use this to exercise both branches of the overflow-recovery code path: pass 0 to verify the failure surface immediately; pass a higher number to verify the loop bounds compaction attempts. Negative values are clamped to 0.

func WithMessageTransform added in v1.54.0

func WithMessageTransform(name string, fn MessageTransform) Opt

WithMessageTransform registers a MessageTransform under name so it is applied to every LLM call, in registration order, after the before_llm_call gate. Transforms are runtime-global: per-agent scoping (if needed) lives in the transform body, where hooks.Input.AgentName is available — the runtime-shipped strip transform is an example.

Empty name or nil fn are silently ignored, matching the no-error shape of the other Opt helpers.

func WithModelStore

func WithModelStore(store ModelStore) Opt

func WithModelSwitcherConfig

func WithModelSwitcherConfig(cfg *modelcatalog.Config) Opt

WithModelSwitcherConfig sets the model switcher configuration for the runtime.

func WithNamedBudgets added in v1.112.0

func WithNamedBudgets(defs map[string]latest.BudgetConfig, agentBudgets map[string][]string) Opt

WithNamedBudgets registers the manifest's named budget definitions and the budget names each agent declared. A named budget referenced by several agents is one shared pot, not a copy per agent.

func WithNonInteractive added in v1.55.0

func WithNonInteractive(nonInteractive bool) Opt

WithNonInteractive marks the runtime as headless (e.g., MCP serve mode). When set, blocking operations like elicitation requests are automatically declined instead of waiting for user interaction that will never come.

Note: this complements session.WithNonInteractive, which controls per-session loop behavior (e.g., auto-stop on max iterations). Both should be set for fully headless operation - the runtime flag prevents elicitation hangs, while the session flag adjusts iteration behavior. In MCP serve mode, both are set by the server code in pkg/mcp/server.go.

func WithProviderRegistry added in v1.84.0

func WithProviderRegistry(registry *provider.Registry) Opt

func WithRetryOnRateLimit added in v1.32.3

func WithRetryOnRateLimit() Opt

WithRetryOnRateLimit enables automatic retry with backoff for HTTP 429 (rate limit) errors when no fallback models are available. When enabled, the runtime will honor the Retry-After header from the provider's response to determine wait time before retrying, falling back to exponential backoff if the header is absent.

This is off by default. It is intended for library consumers that run agents programmatically and prefer to wait for rate limits to clear rather than fail immediately.

When fallback models are configured, 429 errors always skip to the next model regardless of this setting.

func WithSessionCompaction

func WithSessionCompaction(sessionCompaction bool) Opt

func WithSessionStore

func WithSessionStore(store session.Store) Opt

func WithSteerQueue added in v1.44.0

func WithSteerQueue(q MessageQueue) Opt

WithSteerQueue sets a custom MessageQueue for mid-turn message injection. If not provided, an in-memory buffered queue is used.

func WithTelemetry added in v1.53.0

func WithTelemetry(t Telemetry) Opt

WithTelemetry replaces the runtime's Telemetry sink. Defaults to a pass-through to the package-level pkg/telemetry helpers. Tests pass a recorder to assert that the runtime emitted the expected lifecycle events without setting up an OTel client.

func WithToolListTimeout added in v1.82.0

func WithToolListTimeout(d time.Duration) Opt

WithToolListTimeout overrides how long EmitStartupInfo waits for a single toolset to enumerate its tools before skipping it. Defaults to defaultToolListTimeout. A non-positive value is ignored so the default stands. Tests pass a short timeout to exercise the skip path (a toolset whose Tools() blocks) without a real-time wait.

func WithToolStartTimeout added in v1.98.0

func WithToolStartTimeout(d time.Duration) Opt

WithToolStartTimeout overrides how long EmitStartupInfo waits for a single toolset to start before skipping it. Defaults to defaultToolStartTimeout. A non-positive value is ignored so the default stands. Tests pass a short timeout to exercise the skip path (a toolset whose Start() blocks) without a real-time wait.

func WithTracer

func WithTracer(t trace.Tracer) Opt

WithTracer sets a custom OpenTelemetry tracer; if not provided, tracing is disabled (no-op).

func WithUnmanagedOAuthRedirectURI added in v1.69.0

func WithUnmanagedOAuthRedirectURI(uri string) Opt

WithUnmanagedOAuthRedirectURI configures the redirect_uri the runtime advertises when running MCP server OAuth flows in unmanaged mode (i.e. when WithManagedOAuth(false) is set). When set, docker-agent generates state + PKCE + DCR in-process and emits an elicitation carrying the `authorize_url` + `state`; the client returns `{code, state}` via ResumeElicitation and docker-agent does the token exchange itself. When empty, the runtime falls back to the legacy unmanaged contract where the client performs the OAuth flow and returns an access token.

func WithWorkingDir

func WithWorkingDir(dir string) Opt

WithWorkingDir sets the working directory for hooks execution

type PartialToolCallEvent

type PartialToolCallEvent struct {
	AgentContext

	Type           string         `json:"type"`
	ToolCall       tools.ToolCall `json:"tool_call"`
	ToolDefinition *tools.Tool    `json:"tool_definition,omitempty"`
}

PartialToolCallEvent is sent when a tool call is first received (partial/complete)

type PausedEvent added in v1.82.0

type PausedEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id,omitempty"`
}

PausedEvent reports that the run loop has reached an iteration boundary and is now blocked because /pause was toggled on. It is emitted once the in-flight LLM request and its tool calls have finished — i.e. the transition from "pausing" (still finishing a roundtrip) to "paused" (idle until resumed). The TUI uses it to flip its indicator from "Pausing…" to "Paused".

func (*PausedEvent) GetSessionID added in v1.82.0

func (e *PausedEvent) GetSessionID() string

type PendingMessageCanceler added in v1.139.0

type PendingMessageCanceler interface {
	CancelSteer(ctx context.Context, id string) bool
	CancelFollowUp(ctx context.Context, id string) bool
}

PendingMessageCanceler is implemented by runtimes that can withdraw queued messages before the agent loop consumes them.

type PermissionsInfo

type PermissionsInfo struct {
	Allow []string
	Ask   []string
	Deny  []string
}

PermissionsInfo contains the allow, ask, and deny patterns for tool permissions.

type PersistenceObserver added in v1.53.0

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

PersistenceObserver is the stock EventObserver that mirrors the runtime's event stream to a session.Store:

  • persists the initial session row on [OnRunStart] for non-sub-session runs;
  • tracks streaming assistant content (AgentChoice and AgentChoiceReasoning) into a single growing message row, finalised on MessageAddedEvent;
  • persists user messages, sub-session attachments, summaries, token usage, and session-title updates as they fly past.

Sub-session and SessionScoped-mismatch filtering live inside [OnEvent] so callers don't have to think about them.

The runtime auto-registers one of these in NewLocalRuntime against the configured store. Custom sinks (telemetry, audit, A2A, ...) layer alongside via WithEventObserver.

func (*PersistenceObserver) NewRunObserver added in v1.153.0

func (p *PersistenceObserver) NewRunObserver() EventObserver

NewRunObserver isolates streaming transcript state for each invocation.

func (*PersistenceObserver) OnEvent added in v1.53.0

func (p *PersistenceObserver) OnEvent(ctx context.Context, sess *session.Session, event Event)

OnEvent applies the per-event-type persistence rules. Sub-session events are skipped (the parent absorbs them on SubSessionCompleted), and any SessionScoped event tagged with a different session id (forwarded sub-agent streaming events) is filtered out so it can't pollute the parent's transcript.

func (*PersistenceObserver) OnRunStart added in v1.53.0

func (p *PersistenceObserver) OnRunStart(ctx context.Context, sess *session.Session)

OnRunStart persists the session row before the run loop starts. Sub-sessions skip this: the parent session's store absorbs them via the SubSessionCompletedEvent handling in OnEvent.

type PlanChangedEvent added in v1.119.0

type PlanChangedEvent struct {
	AgentContext

	Type   string `json:"type"`
	Scope  string `json:"scope"`
	Name   string `json:"name"`
	Action string `json:"action"`
	// Version is the plan version after a write, or the guard version of a
	// guarded delete (0 when unguarded).
	Version int `json:"version,omitempty"`
}

PlanChangedEvent fires after an agent successfully mutates a shared plan (write, status change, or delete) through the plan toolset. It carries identity and version only — no content — so a UI refreshes through its own plan service instead of trusting an event payload. It is deliberately not session-scoped: shared plans are global across sessions.

type QueueStatus added in v1.59.0

type QueueStatus struct {
	SteerDepth       int
	SteerCapacity    int
	FollowupDepth    int
	FollowupCapacity int
}

QueueStatus represents the current depth and capacity of message queues

type QueuedMessage added in v1.44.0

type QueuedMessage struct {
	ID           string
	Content      string
	MultiContent []chat.MessagePart
}

QueuedMessage is a user message waiting to be injected into the agent loop, either mid-turn (via the steer queue) or at end-of-turn (via the follow-up queue).

type RAGIndexingCompletedEvent

type RAGIndexingCompletedEvent struct {
	AgentContext

	Type         string `json:"type"`
	RAGName      string `json:"rag_name"`
	StrategyName string `json:"strategy_name"`
}

type RAGIndexingProgressEvent

type RAGIndexingProgressEvent struct {
	AgentContext

	Type         string `json:"type"`
	RAGName      string `json:"rag_name"`
	StrategyName string `json:"strategy_name"`
	Current      int    `json:"current"`
	Total        int    `json:"total"`
}

type RAGIndexingStartedEvent

type RAGIndexingStartedEvent struct {
	AgentContext

	Type         string `json:"type"`
	RAGName      string `json:"rag_name"`
	StrategyName string `json:"strategy_name"`
}

RAGIndexingStartedEvent is for RAG lifecycle events

type RecallHandler added in v1.99.0

type RecallHandler func(ctx context.Context, msg QueuedMessage) bool

RecallHandler delivers a tool-produced message through an embedder-owned wake-up path. Embedders use it to resume an idle UI/session when background work completes after the active RunStream has stopped.

type ResumeRequest

type ResumeRequest = toolexec.ResumeRequest

ResumeRequest carries the user's confirmation decision along with an optional reason (used when rejecting a tool call to help the model understand why). The struct fields live in toolexec.ResumeRequest; this alias is kept for readers who land here from the runtime API.

func ResumeApprove

func ResumeApprove() ResumeRequest

ResumeApprove creates a ResumeRequest to approve a single tool call.

func ResumeApproveAutonomous added in v1.117.0

func ResumeApproveAutonomous() ResumeRequest

ResumeApproveAutonomous creates a ResumeRequest that approves the pending call and flips the session to SafetyPolicyAutonomous.

func ResumeApproveBalanced added in v1.117.0

func ResumeApproveBalanced() ResumeRequest

ResumeApproveBalanced creates a ResumeRequest that approves the pending call and flips the session to SafetyPolicyBalanced.

func ResumeApproveSession deprecated

func ResumeApproveSession() ResumeRequest

ResumeApproveSession creates a ResumeRequest to approve all tool calls for the session.

Deprecated: use ResumeApproveAutonomous.

func ResumeApproveTool

func ResumeApproveTool(toolName string) ResumeRequest

ResumeApproveTool creates a ResumeRequest to always approve a specific tool for the session.

func ResumeReject

func ResumeReject(reason string) ResumeRequest

ResumeReject creates a ResumeRequest to reject a tool call with an optional reason.

type ResumeType

type ResumeType = toolexec.ResumeType

ResumeType identifies the user's response to a confirmation request.

The runtime emits a TOOL_PERMISSION_REQUEST event whenever a tool call requires user approval, then blocks until the embedder calls Resume(...) with one of the values below.

ResumeType, ResumeRequest, and the ResumeType* constants are aliased from toolexec so the dispatcher and the runtime share one definition without circular imports.

func NormalizeResumeType added in v1.117.0

func NormalizeResumeType(t ResumeType) ResumeType

NormalizeResumeType maps legacy resume verbs onto the current set. See toolexec.NormalizeResumeType.

func ValidResumeTypes

func ValidResumeTypes() []ResumeType

ValidResumeTypes returns the current (non-legacy) confirmation values, in declaration order.

type RoutingDecisionEvent added in v1.147.0

type RoutingDecisionEvent struct {
	AgentContext

	Type      string                   `json:"type"`
	SessionID string                   `json:"session_id"`
	Decision  *session.RoutingDecision `json:"decision"`
}

RoutingDecisionEvent reports a persisted control decision, including those that left the active agent unchanged.

func (*RoutingDecisionEvent) GetSessionID added in v1.147.0

func (e *RoutingDecisionEvent) GetSessionID() string

type Runtime

type Runtime interface {
	// CurrentAgentInfo returns information about the currently active agent
	CurrentAgentInfo(ctx context.Context) CurrentAgentInfo
	// CurrentAgentName returns the name of the currently active agent
	CurrentAgentName(ctx context.Context) string
	// SetCurrentAgent sets the currently active agent for subsequent user messages
	SetCurrentAgent(ctx context.Context, agentName string) error
	// CurrentAgentTools returns the tools for the active agent
	CurrentAgentTools(ctx context.Context) ([]tools.Tool, error)
	// CurrentAgentToolsetStatuses returns lifecycle status for each toolset of
	// the active agent (name, kind, state, last error, restart count).
	// Used by the /tools dialog. Best-effort: toolsets that don't expose
	// state appear with State == StateStopped/Ready as appropriate.
	CurrentAgentToolsetStatuses() []tools.ToolsetStatus

	// RestartToolset finds the named toolset on the active agent and asks
	// its supervisor to drop the current session and reconnect. Returns
	// an error if no toolset matches name or the toolset does not
	// implement tools.Restartable.
	RestartToolset(ctx context.Context, name string) error
	// EmitStartupInfo emits initial agent, team, and toolset information for immediate display.
	// When sess is non-nil and contains token data, a TokenUsageEvent is also emitted
	// so the UI can display context usage percentage on session restore.
	EmitStartupInfo(ctx context.Context, sess *session.Session, events EventSink)
	// EmitAgentInfo emits up-to-date agent and team info (model, thinking
	// level, description) without re-running heavier startup work such as
	// tool discovery. Used to refresh the UI after a lightweight change like
	// cycling the thinking level, avoiding the tool-count flicker that
	// re-emitting full startup info would cause.
	EmitAgentInfo(ctx context.Context, events EventSink)
	// ResetStartupInfo resets the startup info emission flag, allowing re-emission
	ResetStartupInfo()
	// RunStream starts the agent's interaction loop and returns a channel of events.
	// Consumers must drain it to closure before releasing turn ownership, even
	// after cancellation. Cancel the supplied context before draining on errors.
	RunStream(ctx context.Context, sess *session.Session) <-chan Event
	// Run starts the agent's interaction loop and returns the final messages
	Run(ctx context.Context, sess *session.Session) ([]session.Message, error)
	// Resume allows resuming execution after user confirmation.
	// The ResumeRequest carries the decision type and an optional reason (for rejections).
	Resume(ctx context.Context, req ResumeRequest)
	// ResumeElicitation sends an elicitation response back to a waiting
	// elicitation request. elicitationID correlates the response with a
	// specific concurrent request (see ElicitationRequestEvent.ElicitationID);
	// omit it (or pass "") to fall back to resolving the sole pending
	// request, for backward compatibility with older clients. The parameter
	// is variadic — rather than a required 4th positional argument — purely
	// so pre-#3584 callers of this interface method keep compiling unchanged;
	// implementations should treat more than one value as a caller error and
	// use only the first.
	ResumeElicitation(_ context.Context, action tools.ElicitationAction, content map[string]any, elicitationID ...string) error
	// SessionStore returns the session store for browsing/loading past sessions.
	// Returns nil if no persistent session store is configured.
	SessionStore() session.Store

	// Summarize generates a summary for the session
	Summarize(ctx context.Context, sess *session.Session, additionalPrompt string, events EventSink)

	// PermissionsInfo returns the team-level permission patterns (allow/ask/deny).
	// Returns nil if no permissions are configured.
	PermissionsInfo() *PermissionsInfo

	// ReadSkillContent loads a skill for sess without executing embedded commands.
	ReadSkillContent(ctx context.Context, sess *session.Session, name string) (string, error)

	// CurrentAgentSkillsToolset returns the skills toolset for the current agent, or nil if skills are not enabled.
	CurrentAgentSkillsToolset() *skills.ToolSet

	// RunSkillFork executes a `context: fork` skill as an isolated
	// sub-session of sess. Used by the run_skill tool and the App's
	// slash-command path. Returns a ToolCallResult carrying the sub-agent's
	// last assistant message, or a user-facing error reason; err is non-nil
	// only for unexpected runtime failures.
	RunSkillFork(ctx context.Context, sess *session.Session, args skills.RunSkillArgs, events EventSink) (*tools.ToolCallResult, error)

	// CurrentMCPPrompts returns MCP prompts available from the current agent's toolsets.
	// Returns an empty map if no MCP prompts are available.
	CurrentMCPPrompts(ctx context.Context) map[string]tools.PromptInfo

	// ExecuteMCPPrompt executes a named MCP prompt with the given arguments.
	ExecuteMCPPrompt(ctx context.Context, promptName string, arguments map[string]string) (string, error)

	// UpdateSessionTitle persists a new title for the current session.
	UpdateSessionTitle(ctx context.Context, sess *session.Session, title string) error

	// TitleGenerator returns a generator for automatic session titles, or nil
	// if the runtime does not support local title generation (e.g. remote
	// runtimes) or no configured model is a usable title candidate.
	TitleGenerator(ctx context.Context) *sessiontitle.Generator

	// Steer enqueues a user message for urgent mid-turn injection into the
	// running agent loop. Returns an error if the queue is full or steering
	// is not available.
	Steer(ctx context.Context, msg QueuedMessage) error
	// FollowUp enqueues a message for end-of-turn processing. Each follow-up
	// gets a full undivided agent turn. Returns an error if the queue is full.
	FollowUp(ctx context.Context, msg QueuedMessage) error

	// SetAgentModel sets a model override for the named agent.
	// modelRef can be:
	//   - "" (empty) to clear the override and use the agent's default model
	//   - A model name from the config (e.g., "my_fast_model")
	//   - An inline spec (e.g., "openai/gpt-4o")
	// Returns [ErrUnsupported] for runtimes that don't expose model
	// switching (e.g. remote runtimes, where the server owns the choice).
	SetAgentModel(ctx context.Context, agentName, modelRef string) error

	// CycleAgentThinkingLevel advances the named agent's thinking-effort
	// level to the next value in its provider's cycle (wrapping around),
	// applies it as a runtime model override, and returns the newly
	// selected level. Returns [ErrUnsupported] for runtimes that can't
	// switch models (e.g. remote runtimes) or for models that don't
	// support thinking-effort selection.
	CycleAgentThinkingLevel(ctx context.Context, agentName string) (effort.Level, error)

	// SetAgentThinkingLevel sets the named agent's thinking-effort level to
	// the requested value, applies it as a runtime model override, and
	// returns the applied level. The level must be one the current model
	// supports. Returns [ErrUnsupported] for runtimes that can't switch
	// models (e.g. remote runtimes) or for models that don't support
	// thinking-effort selection.
	SetAgentThinkingLevel(ctx context.Context, agentName string, level effort.Level) (effort.Level, error)

	// AvailableModels returns the models the user can pick from in the
	// /model picker. Returns nil for runtimes that don't expose model
	// switching; see SupportsModelSwitching for a cheap pre-check.
	AvailableModels(ctx context.Context) []modelcatalog.ModelChoice

	// SupportsModelSwitching reports whether SetAgentModel and
	// AvailableModels are wired for this runtime. Use it to gate UI
	// affordances (e.g. show /model in the menu) without paying the
	// cost of AvailableModels.
	SupportsModelSwitching() bool

	// OnToolsChanged registers a handler invoked outside of any RunStream
	// when a toolset reports a tool list change (e.g. after an MCP
	// ToolListChanged notification). A nil handler unregisters. Runtimes
	// that don't emit such events can implement this as a no-op.
	OnToolsChanged(handler func(Event))

	// OnBackgroundEvent registers a handler invoked outside of any RunStream
	// for events surfaced from detached background work (e.g. token usage
	// from background agent tasks started via run_background_agent), which
	// has no live event channel of its own. Runtimes that don't run local
	// background work can implement this as a no-op.
	OnBackgroundEvent(handler func(Event))

	// OnElicitationRequest registers a handler invoked whenever an MCP
	// toolset raises an elicitation request, regardless of which stream
	// (foreground or a detached background job) is currently "active" for
	// the runtime's internal elicitation bridge. This is the reliable
	// delivery route for background-job elicitations (#3584); runtimes
	// that don't run local background work can implement this as a no-op.
	OnElicitationRequest(handler func(Event))

	// QueueStatus returns the current depth and capacity of message queues
	QueueStatus() QueueStatus

	// TogglePause toggles whether the run loop is paused at iteration
	// boundaries. Returns the new state (true if now paused). Returns
	// [ErrUnsupported] for runtimes that don't expose pause control.
	TogglePause(ctx context.Context) (paused bool, err error)

	// Close releases resources held by the runtime (e.g., background
	// agents and pending lifecycles). The session store is *not* closed
	// here: it is supplied by the embedder via WithSessionStore and may
	// be shared with other runtimes (e.g. the TUI's spawner reuses the
	// same store across spawned sessions). Embedders that own the store
	// must close it themselves.
	Close() error
}

Runtime defines the contract for runtime execution

func New

func New(ctx context.Context, agents *team.Team, opts ...Opt) (Runtime, error)

New creates a runtime ready to drive an agent loop. It is a thin alias for NewLocalRuntime returning the Runtime interface, kept for source compatibility with callers written before persistence became an EventObserver. Persistence is auto-registered against the configured (or default in-memory) session store; pass WithSessionStore to override and WithEventObserver to layer additional observers (telemetry, audit, ...).

type SessionCompactionEvent

type SessionCompactionEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	Status    string `json:"status"`
	// Outcome qualifies a "completed" status: "applied" (a summary
	// replaced part of the history), "skipped" (no-op: nothing to
	// compact or the model produced no summary), or "failed" (an error
	// was emitted). Empty on "started" events and events from older
	// servers; consumers should treat empty as "applied" for backward
	// compatibility.
	Outcome string `json:"outcome,omitempty"`
}

func (*SessionCompactionEvent) GetSessionID added in v1.55.0

func (e *SessionCompactionEvent) GetSessionID() string

type SessionRecoveredEvent added in v1.147.0

type SessionRecoveredEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id"`
}

SessionRecoveredEvent is an authoritative idle boundary after snapshot recovery. Reset stream depth and transient interactions without running stop-triggered actions.

func (*SessionRecoveredEvent) GetSessionID added in v1.147.0

func (e *SessionRecoveredEvent) GetSessionID() string

type SessionScoped added in v1.32.1

type SessionScoped interface {
	GetSessionID() string
}

SessionScoped is implemented by events that belong to a specific session. The PersistentRuntime uses this to filter out sub-session events that should not be persisted into the parent session's history.

type SessionSummaryEvent

type SessionSummaryEvent struct {
	AgentContext

	Type           string      `json:"type"`
	SessionID      string      `json:"session_id"`
	Summary        string      `json:"summary"`
	FirstKeptEntry int         `json:"first_kept_entry,omitempty"`
	Cost           float64     `json:"cost,omitempty"`
	Model          string      `json:"model,omitempty"`
	Usage          *chat.Usage `json:"usage,omitempty"`
	// contains filtered or unexported fields
}

func (*SessionSummaryEvent) GetSessionID added in v1.55.0

func (e *SessionSummaryEvent) GetSessionID() string

type SessionTitleEvent

type SessionTitleEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	Title     string `json:"title"`
}

func (*SessionTitleEvent) GetSessionID added in v1.55.0

func (e *SessionTitleEvent) GetSessionID() string

type ShellOutputEvent

type ShellOutputEvent struct {
	AgentContext

	Type      string `json:"type"`
	CommandID string `json:"command_id,omitempty"`
	Command   string `json:"command,omitempty"`
	Output    string `json:"output,omitempty"`
	Error     string `json:"error,omitempty"`
	Done      bool   `json:"done,omitempty"`
}

type StreamStartedEvent

type StreamStartedEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id,omitempty"`
}

func (*StreamStartedEvent) GetSessionID added in v1.55.0

func (e *StreamStartedEvent) GetSessionID() string

type StreamStoppedEvent

type StreamStoppedEvent struct {
	AgentContext

	Type      string `json:"type"`
	SessionID string `json:"session_id,omitempty"`
	Reason    string `json:"reason,omitempty"`
	// FinishReason is the terminal model result, independent of content or usage.
	FinishReason chat.FinishReason `json:"finish_reason,omitempty"`
}

StreamStoppedEvent reports that a RunStream loop has stopped. Reason carries the turnEndReason* classification (normal, error, canceled) so consumers can tell successful completion apart from crashes and user-initiated stops.

Delivery is bounded-blocking: finalizeEventChannel waits (up to a deadline) for the consumer to accept it, so any consumer still draining the channel reliably receives it, and it is dropped only once the consumer has abandoned the channel entirely (#4136). Still, treat the channel close, not receipt of this event, as the guaranteed terminal signal — it remains the only delivery that can never be dropped. Do not assume session-end hooks have finished when this event arrives: it is emitted before they run.

func (*StreamStoppedEvent) GetSessionID added in v1.55.0

func (e *StreamStoppedEvent) GetSessionID() string

type SubSessionCompletedEvent

type SubSessionCompletedEvent struct {
	AgentContext

	Type            string `json:"type"`
	ParentSessionID string `json:"parent_session_id"`
	SubSession      any    `json:"sub_session"` // *session.Session
}

SubSessionCompletedEvent is emitted when a sub-session completes and is added to parent. This event is used by the PersistentRuntime wrapper to persist sub-sessions.

type SubSessionConfig added in v1.32.5

type SubSessionConfig struct {
	// Task is the user-facing task description.
	Task string
	// ExpectedOutput is an optional description of what the sub-agent should produce.
	ExpectedOutput string
	// SystemMessage, when non-empty, replaces the default task-based system
	// message. This is used by skill sub-agents whose system prompt is the
	// skill content itself rather than the team delegation boilerplate.
	SystemMessage string
	// AgentName is the name of the agent that will execute the sub-session.
	AgentName string
	// Title is a human-readable label for the sub-session (e.g. "Transferred task").
	Title string
	// ToolsApproved overrides whether tools are pre-approved in the child session.
	//
	// Deprecated: prefer SafetyPolicy; kept for callers that only know
	// the legacy blanket-approval flag.
	ToolsApproved bool
	// SafetyPolicy is the safety mode the child session inherits from
	// its parent, so a Balanced/Autonomous opt-in (or a Strict pin)
	// survives task transfers, skills, and background agents.
	SafetyPolicy session.SafetyPolicy
	// Permissions defines session-level tool permission overrides.
	Permissions *session.PermissionsConfig
	// NonInteractive marks the child session as running without a user present
	// (e.g. MCP server, A2A adapter, background agent). This causes the runtime
	// to auto-stop on max iterations instead of blocking for user input.
	NonInteractive bool
	// PinAgent, when true, pins the child session to AgentName via
	// session.WithAgentName. This is required for concurrent background
	// tasks that must not share the runtime's mutable currentAgent field.
	PinAgent bool
	// AllowHandoffs permits intentional routing inside a pinned skill fork.
	AllowHandoffs bool
	// ImplicitUserMessage, when non-empty, overrides the default "Please proceed."
	// user message sent to the child session. This allows callers like skill
	// sub-agents to pass the task description as the user message.
	ImplicitUserMessage string
	// ExcludedTools lists tool names that should be filtered out of the agent's
	// tool list for the child session. This prevents recursive tool calls
	// (e.g. run_skill calling itself in a skill sub-session).
	ExcludedTools []string
	// AllowedTools, when non-empty, restricts the child session's inherited
	// agent tools to those whose names match an entry (glob or exact). Used by
	// fork-mode skills that declare an allowed-tools list. ExtraToolSets are
	// exempt from this filter.
	AllowedTools []string
	// ExtraToolSets are additional toolsets exposed in the child session on
	// top of the agent's own toolsets. Used by fork-mode skills that declare
	// assistive toolsets.
	ExtraToolSets []tools.ToolSet
	// DisableStructuredOutput exempts the child session from tool-mode
	// structured-output enforcement. Set only by fork-mode skills, whose
	// answer is free-form text for the calling agent; ordinary delegations
	// and background agents stay enforced.
	DisableStructuredOutput bool
	// DelegationLineage is the chain of agents that delegated to produce this
	// child session (parent lineage plus the delegating caller), as computed
	// by validateDelegation. Set only for true delegation edges
	// (transfer_task, run_background_agent); when nil the child inherits the
	// parent session's lineage unchanged, so non-delegation sub-sessions
	// (e.g. skills) preserve ancestry without adding an edge.
	DelegationLineage []string
}

SubSessionConfig describes the shape of a child session: system prompt, implicit user message, agent identity, tool approval, exclusions, etc. It is the data input to [newSubSession]; the orchestration around running such a session (telemetry, current-agent switching, event forwarding) lives in [LocalRuntime.runForwarding] and [LocalRuntime.runCollecting].

type TeamInfoEvent

type TeamInfoEvent struct {
	AgentContext

	Type            string         `json:"type"`
	AvailableAgents []AgentDetails `json:"available_agents"`
	CurrentAgent    string         `json:"current_agent"`
}

TeamInfoEvent is sent when team information is available

type Telemetry added in v1.53.0

type Telemetry interface {
	// RecordSessionStart is fired once at the top of RunStream.
	RecordSessionStart(ctx context.Context, agentName, sessionID string)
	// RecordSessionEnd is fired when the run loop exits.
	RecordSessionEnd(ctx context.Context)
	// RecordError is fired when the run loop or a model call surfaces a fatal error.
	RecordError(ctx context.Context, message string)
	// RecordToolCall is fired after every tool invocation, regardless of outcome.
	RecordToolCall(ctx context.Context, toolName, sessionID, agentName string, duration time.Duration, err error)
	// RecordTokenUsage reports per-call tokens and cost, not cumulative session totals.
	RecordTokenUsage(ctx context.Context, model string, inputTokens, outputTokens int64, cost float64)
}

Telemetry is the runtime's hook for recording observability events.

The default implementation forwards every call to the package-level helpers in pkg/telemetry, which themselves no-op when no telemetry client is attached to the context — preserving the runtime's historical "telemetry is best-effort" semantics for production code.

Tests can inject a recording implementation via WithTelemetry to assert that the runtime emitted the expected lifecycle events without standing up a full OTel pipeline.

type TokenUsageEvent

type TokenUsageEvent struct {
	AgentContext

	Type                  string `json:"type"`
	SessionID             string `json:"session_id"`
	Usage                 *Usage `json:"usage"`
	AssistantMessageEmpty bool   `json:"assistant_message_empty,omitempty"`
}

func (*TokenUsageEvent) GetSessionID added in v1.53.0

func (e *TokenUsageEvent) GetSessionID() string

GetSessionID makes TokenUsageEvent satisfy SessionScoped so the observer fan-out can drop sub-session events without each observer re-implementing the check.

type ToolCallConfirmationEvent

type ToolCallConfirmationEvent struct {
	AgentContext

	Type           string         `json:"type"`
	ToolCall       tools.ToolCall `json:"tool_call"`
	ToolDefinition tools.Tool     `json:"tool_definition"`
	// Metadata carries arbitrary key/value annotations attached to the
	// confirmation prompt. Toolsets contribute static metadata via
	// [tools.Tool.Metadata]; a permission_request hook can enrich it per
	// call. nil when neither source supplied any.
	Metadata map[string]string `json:"metadata,omitempty"`
}

type ToolCallEvent

type ToolCallEvent struct {
	AgentContext

	Type           string         `json:"type"`
	ToolCall       tools.ToolCall `json:"tool_call"`
	ToolDefinition tools.Tool     `json:"tool_definition"`
}

ToolCallEvent is sent when a tool call is received

type ToolCallOutputEvent added in v1.70.2

type ToolCallOutputEvent struct {
	AgentContext

	Type           string     `json:"type"`
	ToolCallID     string     `json:"tool_call_id"`
	ToolDefinition tools.Tool `json:"tool_definition"`
	Output         string     `json:"output"`
}

type ToolCallResponseEvent

type ToolCallResponseEvent struct {
	AgentContext

	Type           string                `json:"type"`
	ToolCallID     string                `json:"tool_call_id"`
	ToolDefinition tools.Tool            `json:"tool_definition"`
	Response       string                `json:"response"`
	Result         *tools.ToolCallResult `json:"result,omitempty"`
}

type ToolCallsRetractedEvent added in v1.153.0

type ToolCallsRetractedEvent struct {
	AgentContext

	Type        string   `json:"type"`
	ToolCallIDs []string `json:"tool_call_ids"`
}

ToolCallsRetractedEvent is sent when tool calls announced by PartialToolCallEvent will never run: a refusal or a server fallback superseded them.

type ToolHandlerFunc

type ToolHandlerFunc func(ctx context.Context, sess *session.Session, toolCall tools.ToolCall, events EventSink, rt tools.Runtime) (*tools.ToolCallResult, error)

ToolHandlerFunc handles a runtime-managed tool call. rt is the dispatcher's per-call handle, used by handlers that need to talk back to the in-flight call (streaming output, asking the user to approve an action).

type ToolsetInfoEvent

type ToolsetInfoEvent struct {
	AgentContext

	Type           string `json:"type"`
	AvailableTools int    `json:"available_tools"`
	Loading        bool   `json:"loading"`
}

ToolsetInfoEvent is sent when toolset information is available When Loading is true, more tools may still be loading (e.g., MCP servers starting)

type Usage

type Usage struct {
	InputTokens   int64         `json:"input_tokens"`
	OutputTokens  int64         `json:"output_tokens"`
	ContextLength int64         `json:"context_length"`
	ContextLimit  int64         `json:"context_limit"`
	Cost          float64       `json:"cost"`
	LastMessage   *MessageUsage `json:"last_message,omitempty"`
	// SnapshotOnly refreshes totals without reporting another chat response.
	SnapshotOnly bool `json:"snapshot_only,omitempty"`
	// CompactionThreshold is the fraction of the context window at which
	// auto-compaction triggers for the agent that produced this snapshot,
	// so UIs can color context gauges against it. 0 means unknown;
	// consumers should fall back to [compaction.DefaultThreshold].
	CompactionThreshold float64 `json:"compaction_threshold,omitempty"`
}

func SessionUsage

func SessionUsage(sess *session.Session, contextLimit int64, compactionThreshold ...float64) *Usage

SessionUsage builds a Usage from the session's current token counts, the model's context limit, and the session's cost. The reported cost is the session's own cost plus the cost of sub-sessions embedded at load time (restored or branched history), which never emit events of their own. Sub-sessions attached during a live run are excluded: they report their own cost through separate per-session events, and folding them in here would double count in UIs that aggregate per-session entries. The optional compactionThreshold is the agent's configured auto-compaction trigger fraction (0 or omitted when unknown), passed along verbatim for UI gauges.

type UserMessageEvent

type UserMessageEvent struct {
	AgentContext

	MessageID       string             `json:"message_id,omitempty"`
	Type            string             `json:"type"`
	Message         string             `json:"message"`
	MultiContent    []chat.MessagePart `json:"multi_content,omitempty"`
	SessionID       string             `json:"session_id"`
	SessionPosition int                `json:"session_position"` // Index in session.Messages, -1 if unknown
}

UserMessageEvent is sent when a user message is received

func (*UserMessageEvent) GetSessionID added in v1.55.0

func (e *UserMessageEvent) GetSessionID() string

type WarningEvent

type WarningEvent struct {
	AgentContext

	Type    string `json:"type"`
	Message string `json:"message"`
}

Directories

Path Synopsis
Package compactor owns session-aware compaction work that used to live inline in pkg/runtime: extracting the conversation to summarize, computing the kept-tail boundary, and running the default LLM-based summarization strategy.
Package compactor owns session-aware compaction work that used to live inline in pkg/runtime: extracting the conversation to summarize, computing the kept-tail boundary, and running the default LLM-based summarization strategy.
Package eventmerge joins the streaming delta events a runtime emits (one per model token or per tool output write) into fewer, larger deltas.
Package eventmerge joins the streaming delta events a runtime emits (one per model token or per tool output write) into fewer, larger deltas.
Package inspection provides side-effect-free views of agents and toolsets.
Package inspection provides side-effect-free views of agents and toolsets.
Package jscommands wires pkg/js's goja-backed evaluator into the runtime, enabling ${...} JavaScript expressions in slash-command instructions:
Package jscommands wires pkg/js's goja-backed evaluator into the runtime, enabling ${...} JavaScript expressions in slash-command instructions:
Package pricing calculates per-call costs without mutating catalog entries.
Package pricing calculates per-call costs without mutating catalog entries.
Package toolexec hosts utilities used by the runtime to execute tool calls.
Package toolexec hosts utilities used by the runtime to execute tool calls.
Package wire is the (work-in-progress) HTTP transport for pkg/runtime.
Package wire is the (work-in-progress) HTTP transport for pkg/runtime.

Jump to

Keyboard shortcuts

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