Documentation
¶
Index ¶
- Constants
- Variables
- type Agent
- func (a *Agent) Abort()
- func (a *Agent) AppendMessage(msg core.AgentMessage) error
- func (a *Agent) CancelSteer() []core.SteerItem
- func (a *Agent) Compact(ctx context.Context, focus string) (*core.CompactionPayload, error)
- func (a *Agent) CompactAt() int
- func (a *Agent) CompactAtFloor() int
- func (a *Agent) CompactWithCheckpoint(ctx context.Context, checkpoint, focus string) (*core.CompactionPayload, error)
- func (a *Agent) CompactionEpoch() int
- func (a *Agent) Drain(timeout time.Duration)
- func (a *Agent) DrainSteers() []core.SteerItem
- func (a *Agent) DrainUntilBarrier() []core.SteerItem
- func (a *Agent) EffectiveCompactAt() int
- func (a *Agent) Enqueue(msg string) bool
- func (a *Agent) IsRunning() bool
- func (a *Agent) LoadMessages(msgs []core.AgentMessage) error
- func (a *Agent) LoadState(msgs []core.AgentMessage, compactionEpoch int) error
- func (a *Agent) MaxBudget() float64
- func (a *Agent) Messages() []core.AgentMessage
- func (a *Agent) Model() core.Model
- func (a *Agent) NativeDocBytesUndelivered() int64
- func (a *Agent) PeekQueueHead() (core.SteerItem, bool)
- func (a *Agent) PendingSteers() []core.SteerItem
- func (a *Agent) PermissionCheck() ...
- func (a *Agent) PopQueueBarrier(id string) bool
- func (a *Agent) PushSteersFront(items []core.SteerItem)
- func (a *Agent) QueueLen() int
- func (a *Agent) Reconfigure(provider core.Provider, model core.Model, thinkingLevel string) error
- func (a *Agent) ReleaseNativeDocBytes(n int64)
- func (a *Agent) ReserveNativeDocBytes(n int64)
- func (a *Agent) Reset() error
- func (a *Agent) RestoreConversation(messages []core.AgentMessage, epoch int) error
- func (a *Agent) Run(ctx context.Context, prompt string) ([]core.AgentMessage, error)
- func (a *Agent) RunCost() float64
- func (a *Agent) RunWithCustom(ctx context.Context, prompt string, custom map[string]any) ([]core.AgentMessage, error)
- func (a *Agent) Send(ctx context.Context, prompt string) ([]core.AgentMessage, error)
- func (a *Agent) SendItems(ctx context.Context, items []core.SteerItem, msgIDs []string, announce func()) ([]core.AgentMessage, []string, error)
- func (a *Agent) SendPrepareCompact(ctx context.Context, prompt string, slot *sessioncheckpoint.Slot, ...) ([]core.AgentMessage, error)
- func (a *Agent) SendWithContent(ctx context.Context, content []core.Content) ([]core.AgentMessage, error)
- func (a *Agent) SendWithContentAnnounced(ctx context.Context, content []core.Content, msgID string) ([]core.AgentMessage, error)
- func (a *Agent) SendWithContentMsgID(ctx context.Context, content []core.Content, msgID string) ([]core.AgentMessage, error)
- func (a *Agent) SendWithCustom(ctx context.Context, prompt string, custom map[string]any) ([]core.AgentMessage, error)
- func (a *Agent) SendWithCustomAnnounced(ctx context.Context, prompt string, custom map[string]any) ([]core.AgentMessage, error)
- func (a *Agent) SendWithMsgID(ctx context.Context, prompt, msgID string) ([]core.AgentMessage, error)
- func (a *Agent) SetCompactAt(tokens int) error
- func (a *Agent) SetDefaultCompactAt(tokens int)
- func (a *Agent) SetMaxBudget(v float64) error
- func (a *Agent) SetModel(provider core.Provider, model core.Model) error
- func (a *Agent) SetPermissionCheck(...) error
- func (a *Agent) SetSystemPrompt(prompt string) error
- func (a *Agent) SetThinkingLevel(level string) error
- func (a *Agent) SnapshotConversation() ([]core.AgentMessage, int)
- func (a *Agent) Steer(it core.SteerItem) bool
- func (a *Agent) Subscribe(fn func(core.AgentEvent)) func()
- func (a *Agent) SystemPrompt() string
- func (a *Agent) ThinkingLevel() string
- func (a *Agent) TimedOut() bool
- func (a *Agent) TrySteer(it core.SteerItem) error
- type AgentConfig
- type AgentState
- type BudgetExceededError
- type Emitter
- type Hooks
Constants ¶
const MarkerRunTimedOut = "(run timed out)"
MarkerRunTimedOut is the synthetic assistant-message text inserted when a run ends on its MaxRunDuration deadline before the model replied. Exported so callers that surface partial output can recognise and exclude it (it is a status marker, not real assistant text).
Variables ¶
var ErrBudgetExceeded = &BudgetExceededError{}
ErrBudgetExceeded is a sentinel for errors.Is checks.
var ErrDoomLoop = errors.New("doom loop detected")
ErrDoomLoop is a sentinel for a run stopped because it repeated identical tool calls (a doom loop). The concrete error wraps it via fmt.Errorf("%w").
var ErrMaxTurnsExceeded = errors.New("max turns exceeded")
ErrMaxTurnsExceeded is a sentinel for a run that hit its MaxTurns cap. The concrete error wraps it (with the turn count) via fmt.Errorf("%w").
var ErrSteerAdmissionClosed = errors.New("steer admission closed")
ErrSteerAdmissionClosed means the current run has stopped accepting queued messages. Callers may retry the message as a new run once the run settles.
var ErrSteerQueueFull = errors.New("steer queue full")
ErrSteerQueueFull means the steer queue has reached its bounded capacity.
var ErrUnresolvedAttachment = errors.New("unresolved attachment reference in provider request")
ErrUnresolvedAttachment reports a provider-bound request that still carries an attachment reference with no bytes. It is a bug in the producing or materializing side, never something the user can fix by retrying.
Functions ¶
This section is empty.
Types ¶
type Agent ¶
type Agent struct {
// contains filtered or unexported fields
}
Agent runs the core loop: prompt → LLM → tool calls → execute → repeat. It's a library — no I/O, no UI, no filesystem opinions.
func New ¶
func New(cfg AgentConfig) (*Agent, error)
New creates an Agent from config. Returns error if configuration is invalid. Call Run() to execute a prompt.
func (*Agent) AppendMessage ¶
func (a *Agent) AppendMessage(msg core.AgentMessage) error
AppendMessage appends a non-LLM message to the current conversation state. Used to persist timeline events before the next user turn.
func (*Agent) CancelSteer ¶
CancelSteer drops and returns all steer messages still queued for inter-step delivery. Used when the user pulls queued steers back into the input to edit them, so the agent doesn't also deliver the originals (double-delivery). Safe to call while running; already-delivered steers cannot be recalled.
func (*Agent) Compact ¶
Compact forces context compaction regardless of the auto-compaction threshold. Returns the compaction payload on success, nil if there was nothing to compact, or an error if the agent is running or compaction fails.
func (*Agent) CompactAt ¶
CompactAt returns the current soft compaction threshold in tokens (0 = the default window-based behavior).
func (*Agent) CompactAtFloor ¶
CompactAtFloor returns the lowest threshold SetCompactAt will actually honor, in tokens. Reads the agent's own compaction settings rather than the package defaults, since a session may have been built with different reserve/keep values.
func (*Agent) CompactWithCheckpoint ¶
func (a *Agent) CompactWithCheckpoint(ctx context.Context, checkpoint, focus string) (*core.CompactionPayload, error)
CompactWithCheckpoint is Compact with a mechanically appended ephemeral checkpoint. The checkpoint bypasses the summarizer so it cannot be omitted. focus is an optional caller instruction (from `/compact <focus>`) forwarded to the summarizer; empty for automatic compaction.
func (*Agent) CompactionEpoch ¶
CompactionEpoch returns the current compaction epoch.
func (*Agent) Drain ¶
Drain waits until all in-flight events have been processed by subscribers, or timeout expires. Rarely needed — Send/Run auto-drain before returning. Kept for backward compatibility and special cases (e.g., mid-run flushes).
func (*Agent) DrainSteers ¶
DrainSteers removes and returns all steer messages still queued for inter-step delivery. Used to hand queued messages to a new run when the operation that accepted them (e.g. a manual compaction) finishes without running the agent loop, which would otherwise leave them undelivered.
func (*Agent) DrainUntilBarrier ¶
DrainUntilBarrier removes and returns the queued steers up to (but not including) the first barrier command. Used by the pump to start a new run with the steers that follow an executed command.
func (*Agent) EffectiveCompactAt ¶ added in v0.34.0
EffectiveCompactAt returns the threshold actually in force for this agent, in tokens: its own CompactAt when set, otherwise the inherited/global default, 0 when neither applies (compact at the model window). Distinct from CompactAt, which reports only what THIS session chose — a subagent, or a session running under a global default, has no choice of its own but still compacts early.
func (*Agent) Enqueue ¶
Enqueue queues a message for post-turn delivery. It will be processed after the current agent turn completes, triggering a new turn. Returns false when the ending run can no longer consume it.
func (*Agent) LoadMessages ¶
func (a *Agent) LoadMessages(msgs []core.AgentMessage) error
LoadMessages replaces the conversation history with the given messages. Used to restore a previous session. Returns error if the agent is running.
func (*Agent) LoadState ¶
func (a *Agent) LoadState(msgs []core.AgentMessage, compactionEpoch int) error
LoadState replaces the full conversation state including compaction epoch. Used to restore a previous session with compaction history.
func (*Agent) MaxBudget ¶
MaxBudget returns the current per-run budget ceiling in USD (0 = unlimited).
func (*Agent) Messages ¶
func (a *Agent) Messages() []core.AgentMessage
Messages returns a shallow copy of the current conversation messages. The returned slice is independent (append-safe), but individual messages share content slices with the internal state. Safe for reading (e.g., JSON marshaling for session persistence) but callers should not mutate content.
func (*Agent) NativeDocBytesUndelivered ¶
NativeDocBytesUndelivered returns the decoded native document/image bytes that have been accepted into the session (queued steers, plus any drained batch still in flight to history) but are not yet visible in the conversation history. The serve layer adds this to the history total when enforcing the per-session native-content budget, so concurrent sends can't collectively exceed it through the async steer-delivery window.
func (*Agent) PeekQueueHead ¶
PeekQueueHead returns a copy of the item at the head of the unified queue without removing it, and false when the queue is empty. Used by the bus queue pump to decide whether the next item is a barrier command or a steer.
func (*Agent) PendingSteers ¶
PendingSteers returns a snapshot of the user-visible steer messages still queued for inter-step delivery, without removing them. Used to report authoritative queue state (e.g. reconnect snapshots) without disturbing delivery order. Internal steers (system-generated, with suppressed delivery events) are excluded so they never surface as phantom "queued" chips.
func (*Agent) PermissionCheck ¶
func (a *Agent) PermissionCheck() func(ctx context.Context, name string, args map[string]any) *core.ToolCallDecision
PermissionCheck returns the current permission callback.
func (*Agent) PopQueueBarrier ¶
PopQueueBarrier removes the head item only if it is still the barrier command with the given ID, returning false when the head changed. Lets the pump execute a queued command exactly once, safely against concurrent enqueues.
func (*Agent) PushSteersFront ¶
PushSteersFront re-inserts items at the head of the steer queue, preserving their order. Used to hand drained items back when a delivery attempt loses a race for the run slot, so FIFO order (oldest first) survives.
func (*Agent) QueueLen ¶
QueueLen returns the number of items currently in the unified queue rail (steers and barriers, including internal steers). Used by the producer-side strict-order gate: a user run must not start while the queue is non-empty.
func (*Agent) Reconfigure ¶
Reconfigure swaps the provider, model, and/or thinking level mid-conversation. Preserves conversation history. Strips thinking blocks from historical assistant messages to avoid invalid signatures when the model changes. Returns error if the agent is currently running.
func (*Agent) ReleaseNativeDocBytes ¶
ReleaseNativeDocBytes undoes a ReserveNativeDocBytes when the reserved send never started (so SendWithContent's settle won't run).
func (*Agent) ReserveNativeDocBytes ¶
ReserveNativeDocBytes adds n decoded native-content bytes to the inflight ledger BEFORE a direct content send's message reaches history. A direct SendWithContent appends to history asynchronously (in the run goroutine), so without this reservation a concurrent send could read the quota after the caller released its serialization lock but before the message is countable in history, and admit content past the per-session cap. The paired settle happens inside SendWithContent right after the append; if the send is never started (e.g. the run slot was lost), the caller must release the reservation with ReleaseNativeDocBytes.
func (*Agent) Reset ¶
Reset clears conversation state. Returns error if the agent is currently running.
Reset deliberately does NOT drop the queued steers/barriers: when a queued /clear barrier is executed at idle, everything still in the queue is, by FIFO, behind the /clear and therefore belongs to the fresh conversation (reset in-place). Callers that want to discard the queue call CancelSteer explicitly.
func (*Agent) RestoreConversation ¶
func (a *Agent) RestoreConversation(messages []core.AgentMessage, epoch int) error
func (*Agent) Run ¶
Run initializes state with a new prompt and runs the agent loop. Any previous conversation state is replaced. For multi-turn, use Send. Returns all messages produced during the run. Before returning, Run waits for all accepted in-flight events to be processed by subscribers (up to DrainTimeout). Dropped events are not waited on.
func (*Agent) RunCost ¶
RunCost returns the USD cost accumulated by the most recent Run/Send. It is a faithful measure of real spend whenever the model has pricing — including usage from empty or failed turns that never became an assistant message — regardless of whether a MaxBudget cap was active.
func (*Agent) RunWithCustom ¶ added in v0.28.0
func (a *Agent) RunWithCustom(ctx context.Context, prompt string, custom map[string]any) ([]core.AgentMessage, error)
RunWithCustom initializes state with a prompt carrying custom metadata and runs the agent loop. The metadata is retained in the transcript but does not affect the LLM payload.
func (*Agent) Send ¶
Send appends a user message and runs the agent loop, continuing the conversation. If no previous state exists (e.g., first call without Run), state is auto-initialized. State mutation is atomic with the "not running" check — concurrent Send calls cannot corrupt state. Before returning, Send waits for all accepted in-flight events to be processed by subscribers (up to DrainTimeout). Dropped events are not waited on.
func (*Agent) SendItems ¶
func (a *Agent) SendItems(ctx context.Context, items []core.SteerItem, msgIDs []string, announce func()) ([]core.AgentMessage, []string, error)
SendItems appends one user message per queued item (each with its own MsgID, carrying image/content blocks when present) and runs the agent loop. It is used to start a fresh run for the steers that were queued after a barrier command, preserving per-item granularity (no folding into one message).
msgIDs, when non-empty, supplies the stable MsgID for each item in order (len(msgIDs) must equal len(items)); an empty entry (or a nil/short slice) is auto-minted. Callers pre-mint so they can announce each delivered chip with a known MsgID without waiting for the run — clients dedup by MsgID on reconnect. The returned MsgIDs are the effective ones in item order. Barrier items are commands, never messages, and are skipped defensively.
announce, when non-nil, is invoked once the items are genuinely in history and before the run's own events — the same guarantee SendWithMsgID gives a direct prompt, so an announcement can never race a concurrent history snapshot (a reconnect between the two would lose the steer until a reload).
func (*Agent) SendPrepareCompact ¶
func (a *Agent) SendPrepareCompact(ctx context.Context, prompt string, slot *sessioncheckpoint.Slot, extraPrompt string) ([]core.AgentMessage, error)
SendPrepareCompact runs the internal pre-compaction turn. It is the only entry point that grants the checkpoint permission bypass, and it always constructs that tool from slot rather than accepting a caller-provided tool.
func (*Agent) SendWithContent ¶
func (a *Agent) SendWithContent(ctx context.Context, content []core.Content) ([]core.AgentMessage, error)
SendWithContent appends a user message with mixed content blocks (text + images) and runs the agent loop, continuing the conversation. The content is deep-cloned (core.CloneContent) to take ownership from the caller, so a later mutation of the caller's slice or of a block's Arguments map can't change the stored message or race a concurrent reader. Before returning, SendWithContent waits for all accepted in-flight events to be processed by subscribers (up to DrainTimeout). Dropped events are not waited on.
func (*Agent) SendWithContentAnnounced ¶ added in v0.21.0
func (a *Agent) SendWithContentAnnounced(ctx context.Context, content []core.Content, msgID string) ([]core.AgentMessage, error)
SendWithContentAnnounced is SendWithContentMsgID that also announces the prompt (AgentEventUserMessage) from the append point. Only the user-initiated ingress paths announce: internal producers render themselves.
func (*Agent) SendWithContentMsgID ¶ added in v0.21.0
func (a *Agent) SendWithContentMsgID(ctx context.Context, content []core.Content, msgID string) ([]core.AgentMessage, error)
SendWithContentMsgID is SendWithContent with a caller-supplied MsgID for the user message, letting the caller announce this prompt live under an ID shared with the message that lands in state — so clients dedup it against their optimistic echo and against reconnect snapshots. Mirrors SendWithMsgID.
func (*Agent) SendWithCustom ¶
func (a *Agent) SendWithCustom(ctx context.Context, prompt string, custom map[string]any) ([]core.AgentMessage, error)
SendWithCustom appends a user message with custom metadata and runs the agent loop. The custom map is attached to the AgentMessage (persisted in session, available to frontends for rendering decisions) but does not affect LLM behavior.
func (*Agent) SendWithCustomAnnounced ¶ added in v0.28.0
func (a *Agent) SendWithCustomAnnounced(ctx context.Context, prompt string, custom map[string]any) ([]core.AgentMessage, error)
SendWithCustomAnnounced appends a custom user message and announces it after it reaches history. It is for custom sources with an explicit live UI representation; other internal sources remain unannounced.
func (*Agent) SendWithMsgID ¶
func (a *Agent) SendWithMsgID(ctx context.Context, prompt, msgID string) ([]core.AgentMessage, error)
SendWithMsgID is Send with a caller-supplied MsgID for the user message, letting the caller correlate a later event (e.g. a Steered announcement for a batch of queued steers folded into this one prompt) with the message that lands in state — so reconnect snapshots dedup it by that shared MsgID.
It also announces the prompt (AgentEventUserMessage) from the append point, so subscribers only learn about it once it is genuinely in history — see announceUserMessage.
func (*Agent) SetCompactAt ¶
SetCompactAt sets the soft compaction threshold in tokens. When >0, the agent compacts once context exceeds this many tokens (clamped to the model window), instead of waiting for the full window. 0 restores the default (window-based) behavior. Returns error if the agent is currently running.
func (*Agent) SetDefaultCompactAt ¶ added in v0.34.1
SetDefaultCompactAt updates the GLOBAL fallback threshold, leaving the session's own choice untouched. Unlike SetCompactAt it is allowed while the agent is running: the setting is meant to reach every conversation the moment it changes, and a long run is exactly the case that needs it. The loop reads a.config.Compaction through a pointer it captured at run start, so this replaces the struct (copy-on-write) rather than mutating the shared value.
func (*Agent) SetMaxBudget ¶
SetMaxBudget changes the per-run budget ceiling. Goal mode uses this to cap each iteration at the remaining total budget. Validated like New(): a positive budget requires model pricing. Returns an error if the agent is running.
func (*Agent) SetModel ¶
SetModel changes the model and optionally the provider. If provider is nil, keeps the current provider. Strips thinking blocks from history when the model changes. Returns error if the agent is currently running.
func (*Agent) SetPermissionCheck ¶
func (a *Agent) SetPermissionCheck(fn func(ctx context.Context, name string, args map[string]any) *core.ToolCallDecision) error
SetPermissionCheck swaps the permission check function at runtime. nil disables permission checks. Returns error if the agent is running.
func (*Agent) SetSystemPrompt ¶
SetSystemPrompt replaces the system prompt. Returns error if the agent is running.
func (*Agent) SetThinkingLevel ¶
SetThinkingLevel changes only the thinking level. Returns error if the agent is currently running.
func (*Agent) SnapshotConversation ¶
func (a *Agent) SnapshotConversation() ([]core.AgentMessage, int)
func (*Agent) Steer ¶
Steer queues a message for inter-step delivery. The agent sees it at the next gap between tool executions. Safe to call while running. Returns false if admission is closed or the queue is full, so callers can surface or reclassify a message that the current run will not consume.
func (*Agent) Subscribe ¶
func (a *Agent) Subscribe(fn func(core.AgentEvent)) func()
Subscribe registers a listener for agent events. Returns an unsubscribe function. Listeners are async — slow listeners don't block the loop. Send/Run auto-drain before returning, so all accepted events are processed.
func (*Agent) SystemPrompt ¶
SystemPrompt returns the current system prompt.
func (*Agent) ThinkingLevel ¶
ThinkingLevel returns the current thinking level.
type AgentConfig ¶
type AgentConfig struct {
Provider core.Provider
Model core.Model
SystemPrompt string
ThinkingLevel string
CacheTTL string // Prompt-cache TTL: "" (5m default) or "1h". Interactive agent only.
// PromptCacheKey identifies this agent's conversation for cache routing on
// the Responses providers (OpenAI, xAI). Empty omits the field entirely.
PromptCacheKey string
MaxTokens int // Max output tokens per LLM call. 0 = shared model-aware default.
Tools *core.Registry
Extensions []extension.Extension
WorkspaceRoot string
// Guardrails
MaxTurns int // Default: 50. 0 = unlimited.
MaxToolCallsPerTurn int // Default: 20. 0 = unlimited.
MaxRunDuration time.Duration // Default: 30m. 0 = unlimited.
MaxBudget float64 // Max USD per run. 0 = unlimited. Requires Model.Pricing when > 0.
// Permission check called before each tool execution. May block waiting
// for user approval. Return nil to approve, blocking decision to reject.
// nil = no permission checks (all tools auto-approved).
PermissionCheck func(ctx context.Context, name string, args map[string]any) *core.ToolCallDecision
// Custom message conversion (nil = default: filter non-LLM messages)
ConvertToLLM func([]core.AgentMessage) []core.Message
// MaterializeContent, if set, is called with the LLM-ready messages just before
// the provider request is built, to expand attachment descriptors into
// provider-ready inline bytes on a COPY. It must not mutate its input. A
// non-nil error aborts the turn (the referenced attachment could not be
// resolved). pkg/agent stays decoupled from the blob store: the closure is
// injected by the caller via the store's MaterializerFor.
MaterializeContent func(context.Context, []core.Message) ([]core.Message, error)
// AttachmentScope is the agent's attachment capability: the store plus the
// session that OWNS anything it externalizes. It is a single indivisible
// value on purpose — the agent derives BOTH halves from it (it publishes it
// on the run context so tools can produce references, and it takes the
// materializer from the same value so those references can be resolved), so
// no constructor can wire one half and forget the other.
//
// nil = this agent works inline: it produces no references, and it hides any
// capability inherited from a caller's context (see executeWithOptions).
// Agents whose conversation is discarded (plan/code reviewers, goal
// verifier) must stay nil: externalizing there would only leave orphan
// references in the parent's index.
AttachmentScope *attachment.Scope
// Compaction settings. nil = use DefaultCompactionSettings.
// Set Enabled:false to disable.
Compaction *core.CompactionSettings
// SessionCheckpoint is the ephemeral handoff slot. When set, automatic
// compaction appends its contents to the summary and clears it, matching
// the manual CompactWithCheckpoint path.
SessionCheckpoint *sessioncheckpoint.Slot
// DrainTimeout is the maximum time Send/Run will wait for subscribers to
// finish processing events before returning. Default: 2s.
// Set to 0 to disable auto-drain.
DrainTimeout time.Duration
Logger *slog.Logger
}
AgentConfig configures an Agent.
type AgentState ¶
type AgentState struct {
Messages []core.AgentMessage
Model core.Model
CompactionEpoch int // incremented after each compaction; invalidates stale Usage
}
AgentState holds the mutable state during an agent run.
type BudgetExceededError ¶
BudgetExceededError is returned when a run's accumulated cost exceeds MaxBudget.
func (*BudgetExceededError) Error ¶
func (e *BudgetExceededError) Error() string
func (*BudgetExceededError) Is ¶
func (e *BudgetExceededError) Is(target error) bool
Is reports whether target is a *BudgetExceededError, enabling errors.Is checks against the ErrBudgetExceeded sentinel.
type Emitter ¶
type Emitter struct {
// contains filtered or unexported fields
}
Emitter fans out events to subscribers asynchronously. Each subscriber has a buffered channel. If the buffer fills, events are dropped. Panics in handlers are recovered without stranding the inflight counter.
Drain() waits until all accepted in-flight events have been processed. Dropped events (full buffer) are not tracked and won't delay Drain.
func (*Emitter) Drain ¶
Drain waits until all in-flight events have been processed by all subscribers, or timeout expires. The timeout is a safety net for stuck handlers.
func (*Emitter) Emit ¶
func (e *Emitter) Emit(event core.AgentEvent)
Emit sends an event to all active subscribers. Lossy delta events are dropped when a subscriber's buffer is full; structural events block until there is room (or the subscriber is torn down) so they are never lost.
func (*Emitter) Subscribe ¶
func (e *Emitter) Subscribe(fn func(core.AgentEvent)) func()
Subscribe registers a listener. Returns an unsubscribe function (safe to call multiple times). The listener runs in its own goroutine and receives events asynchronously.
type Hooks ¶
type Hooks interface {
FireBeforeAgentStart(ctx context.Context) []core.AgentMessage
FireToolCall(ctx context.Context, name string, args map[string]any) *core.ToolCallDecision
FireToolResult(ctx context.Context, name string, result core.Result, isError bool) core.Result
FireContext(ctx context.Context, msgs []core.AgentMessage) []core.AgentMessage
FireObserver(event core.AgentEvent)
}
Hooks is the interface the agent loop needs from the extension system. Defined here (consumer-side) so the loop doesn't depend on extension internals.