All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
- Thread lifecycle changes now serialize with active execution. Archive and soft-delete reject threads with queued or running turns, and archived threads reject new turns, retries, and pre-existing turn starts until explicitly unarchived. Full-history forks reject active sources instead of copying nonterminal turns, and startup failures terminalize any turn created before execution ownership is established. Rename remains available during execution because it does not alter run ownership.
- Capability-validated durable reasoning effort. Runtime thread starts, turn starts/resumes, and retries now reject explicit reasoning effort when the selected catalog model is unknown, does not advertise reasoning, or does not advertise that exact effort. Supported explicit choices are stored in thread settings and turn input, inherited by later turns, and recovered by retries instead of becoming renderer-only state.
- Durable live turn steering. The app server now binds the exact public
turn/steerrequest and response, requires thread and expected-active-turn correlation, and queues text instructions for the next safe model-request boundary. A durable steer item moves from queued to completed only after the next provider stream starts; interruption or terminal completion first marks it failed, and only completed instructions replay into later turns. Stable client message ids make active-turn response retries idempotent and reject conflicting text. - Response-loss-safe full-history thread forks. The generated
thread/forkextension accepts a source thread and bounded idempotency key, rejects queued or running source work, and transactionally copies durable turns and items with regenerated identities. Repeating the same request, including after daemon restart, returns the original child without emitting anotherthread/startednotification. Forked timelines retain public file-change evidence but never inherit private exact-restoration snapshots. - Restart-safe exact file-change reversal. Runtime file-change items now
advertise whether Gollem persisted a private recovery snapshot. The
item/fileChange/revertextension accepts only thread/item identity and an idempotency key, reuses the existing file-mutation approval flow, verifies exact workspace, path, content digest, mode, and terminal-turn ownership, and emits a durable receipt. Reversal is limited to regular files up to 1 MiB with exactly one observed hard link; directories, paths traversing symlinks, multiply linked files, unknown link counts, stale files, mismatched workspaces, active workspace turns, and incomplete evidence fail closed. Runtime mutations capture before/after evidence under the filesystem mutation lock only after approval, and reverts reserve the workspace without blocking unrelated thread reads. Pending operations reconcile after restart from deterministic transaction directories only inside the approved revert operation when the target and quarantined regular file are provably in a safe state. File metadata and affected directories are synchronized before a durable receipt can commit, and startup reconciles a private snapshot whose public item completion was interrupted. A daemon-wide coordinator makes rollback, thread deletion, and turn or thread starts serialize with that reservation across every client connection, while denied operations release their key only after proving no mutation occurred. - Restart-safe app-server retry and daemon ownership. File-backed app-server
daemons now hold one process-lifetime store lock and reconcile queued or
running turns to an inspectable interrupted state after owner loss. The
generated
turn/retryextension requires an idempotency key, atomically creates or reuses one retry turn, preserves the recorded source prompt and model selection, and bounds model-visible replay after the latest compaction. Recovery never recreates pending approval authority or silently treats prior tool side effects as resumed. - Typed app-server catalog and run-lifecycle bindings. Generated clients can now infer provider/model discovery, thread and turn start, turn interruption, thread/turn lifecycle notifications, and live text/reasoning deltas without raw JSON. Runtime-specific types preserve the current Gollem wire while exact standalone Codex contracts remain distinct.
- Adaptive thinking for Anthropic providers. New
ModelSettings.AdaptiveThinking *boolemits{thinking: {type: "adaptive"}}from both theanthropicandvertexai_anthropicproviders — the model decides when and how much to think. Gated per model (Claude 4.6 generation and newer; clear build-time error on older models), mutually exclusive with the legacyThinkingBudgetmanual mode, and temperature is omitted on the wire as the API requires. Response and stream paths already parsedthinkingblocks; this closes the request side. - Opus 4.8 and Fable model gating.
claude-opus-4-8andclaude-fable-5(newClaudeOpus48/ClaudeFable5constants) are recognized as post-4.7 flagships: adaptive-only thinking (manual budgets rejected with a pointer toAdaptiveThinking), and the full effort range includingxhighandmaxnow passes per-model effort gating. core.WithAdaptiveThinkingagent option, and the CLI's default reasoning setup now selects adaptive thinking for Claude 4.6+ models instead of a manual budget (which is rejected on 4.7+ — the budget default made the new models unusable from the CLI). An explicit-thinking-budgetstill wins.- Request guards matching API removals (both Anthropic
providers): temperature/top_p are stripped on Opus 4.7+ (the API
400s on them regardless of thinking config, and Fable thinks
unconditionally server-side), and forced tool choice
(
required/specific tool) combined with any thinking mode now fails fast with a clear error instead of an API 400. - Reasoning sandwich works with adaptive thinking. The codetool
middleware only varied a manual
ThinkingBudget, so on Claude 4.6+ agents (which now default to adaptive thinking, no budget) it was silently inert. WithAdaptiveThinkingon it now variesReasoningEffortper phase — effort is adaptive thinking's depth control — keeping the plan-high/implement-lower/verify-high shape on Anthropic. First direct tests for the middleware included.
- Hosted coverage uploads, patch thresholds, badge, and service configuration.
GetDeps[D]extracts typed dependencies fromRunContextwithout manual type assertionsTryGetDeps[D]safe variant returning(D, bool)WithDepsagent option for setting dependencies at agent level- Agent-level deps merge with run-level
WithRunDeps(run-level takes precedence)
ModelProfilestruct describes model capabilities (tool calls, vision, streaming, context window)Profiledoptional interface for models to self-declare capabilitiesGetProfilereturns profile or default (full capabilities) for non-Profiled modelsNewCapabilityRouterselects first model matching required capabilities
UsageQuotawith hard limits on requests, total/input/output tokensQuotaExceededErrorreturned when quota is breachedWithUsageQuotaagent option; checked before each model request- Zero values mean unlimited (opt-in enforcement)
MessageInterceptorintercepts outgoing model requests (allow/drop/modify)ResponseInterceptorintercepts incoming model responsesRedactPIIbuilt-in interceptor for regex-based PII redactionAuditLogbuilt-in interceptor for message loggingWithMessageInterceptor/WithResponseInterceptoragent options
ToolChoicewith modes: auto, required, none, force (specific tool)ToolChoiceAuto,ToolChoiceRequired,ToolChoiceNone,ToolChoiceForceconstructorsWithToolChoiceagent option;WithToolChoiceAutoResetprevents infinite loopsToolChoicefield added toModelSettingsfor provider pass-through
CostTrackerwith per-modelModelPricing(input/output/cached token costs)Recordaccumulates costs;TotalCostandCostBreakdownfor reportingRunCostonRunResultfor per-run cost visibilityWithCostTrackeragent option; thread-safe for concurrent recording
PipelinechainsPipelineStepfunctions sequentiallyAgentStepwrapsAgent[string]as a pipeline stepTransformStepfor pure string transformationsParallelStepsruns steps concurrently and joins resultsConditionalStepbranches based on a predicateThenappends steps immutably (returns new pipeline)
AutoContextConfigwith token threshold, keep-last-N, optional summary modelWithAutoContextagent option for transparent overflow handling- Simple word-based token estimation (no external deps)
- Summarizes old messages via model call when threshold exceeded
StreamTextwithStreamTextOptions(delta mode, debounce window)StreamTextDeltafor raw incremental chunksStreamTextAccumulatedfor growing accumulated textStreamTextDebouncedfor grouped event delivery- Returns
iter.Seq2[string, error]consistent with existing streaming API
AgentMiddlewarewraps model calls with cross-cutting concernsWithAgentMiddlewareagent option; middleware compose in order (first = outermost)LoggingMiddlewarelogs request/response summariesMaxTokensMiddlewareenforces token limits via ModelSettingsTimingMiddlewarerecords request durations- Middleware can modify inputs, outputs, or skip the model call entirely
RateLimitedModelwraps anyModelwith token-bucket rate limitingNewRateLimitedModelwith configurable requests-per-second and burst- Requests exceeding rate are delayed, not rejected
- Context cancellation stops waiting requests
CacheStoreinterface withMemoryCacheimplementationNewMemoryCacheWithTTLfor TTL-based expirationCachedModelwrapsModelto cacheRequest()responses by SHA-256 hash- Streaming requests bypass cache
WithToolTimeoutper-tool execution deadline viacontext.WithTimeoutWithDefaultToolTimeoutagent-level default for tools without explicit timeout- Per-tool timeout takes precedence over agent default
RunConditionpredicate checked after each model responseOr()andAnd()combinators for composing conditions- Built-in conditions:
MaxRunDuration,TextContains,ToolCallCount,ResponseContains WithRunConditionagent optionRunConditionErrorerror type when condition triggers
HandoffFiltertransforms messages at agent handoff boundaries- Built-in filters:
StripSystemPrompts,KeepLastN,SummarizeHistory ChainFiltersfor composing multiple filters in sequenceChainRunWithFilterfor filtered agent chainingHandoff.AddStepWithFilterfor filtered handoff pipeline steps
TraceExporterinterface for pluggable trace exportJSONFileExporterwrites JSON trace files to a directoryConsoleExporterprints human-readable trace summariesMultiExporterfans out to multiple exportersWithTraceExporteragent option (implicitly enables tracing)
Override()creates independent agent with replaced modelWithTestModel()convenience returns agent +TestModelpair- Original agent is never modified
RetryModelwrapsModelwith configurable retry for transient failuresRetryConfigwithMaxRetries,InitialBackoff,MaxBackoff,BackoffFactor,JitterDefaultRetryConfigtargets HTTP 429/500/502/503- Both
RequestandRequestStreamretry
RunSnapshotcaptures full run state (messages, usage, step)MarshalSnapshot/UnmarshalSnapshotfor JSON round-tripBranch()creates independent copies for alternate-path explorationWithSnapshotRunOptionto resume from saved state- Hook-friendly capture via
Snapshot(rc)
EventBuswith typedSubscribe/Publish/PublishAsyncusing generics- Type-safe: subscribers only receive matching event types
Unsubscribevia returned function fromSubscribe- Built-in events:
RunStartedEvent,RunCompletedEvent,ToolCalledEvent WithEventBusagent option; bus accessible viaRunContext.EventBus- Thread-safe under concurrent access
Hookstruct with 6 event callbacks:OnRunStart,OnRunEnd,OnModelRequest,OnModelResponse,OnToolStart,OnToolEndWithHooksagent option for registering multiple hooks in order- All hooks fire at correct points in the agent run loop
PromptTemplatewith Gotext/templatesyntax ({{.VarName}})NewPromptTemplate,MustTemplate,Format,Partial,VariablesAPIWithSystemPromptTemplateagent option for template-based system promptsTemplateVarsinterface for custom deps types
InputGuardrailFuncvalidates/transforms prompts before the agent loopTurnGuardrailFuncvalidates messages before each model requestGuardrailErrordistinct error type with guardrail name- Built-in guardrails:
MaxPromptLength,ContentFilter,MaxTurns
RunBatchexecutes multiple prompts concurrently with ordered resultsWithBatchConcurrencycontrols parallel execution limit- Context cancellation aborts all in-flight runs
ModelRouterinterface andRouterModelimplementingModelClassifierRouterfor function-based routingThresholdRouterfor prompt-length-based model selectionRoundRobinRouterfor even distribution across models
SlidingWindowMemorykeeps last N message pairsTokenBudgetMemorydrops oldest messages to fit token budgetSummaryMemoryuses a model to summarize older messages- All implement
HistoryProcessorfor use withWithHistoryProcessor
RepairFunc[T]intercepts parse failures before retry flowWithOutputRepairagent option for custom repair logicModelRepair[T]helper uses a model to fix malformed JSON- Repaired output still runs through validators
Clonecreates independent agent copies with additional optionsChainRunpipes agents: first output transforms to second promptChainRunFullreturns both intermediate and final results with combined usage
RunTracecaptures all execution steps with timestamps and durationsTraceStepwith kinds:model_request,model_response,tool_call,tool_resultWithTracingagent option; trace available onRunResult.Trace- JSON-serializable for debugging, replay, and compliance auditing
ToolResultValidatorFuncvalidates tool results before passing to model- Per-tool validators via
WithToolResultValidatortool option - Agent-wide validators via
WithGlobalToolResultValidator - Invalid results become
RetryPromptPartwith validation error
KnowledgeBaseinterface for pluggable RAG, graph databases, and memory services- Agent transparently calls
Retrieve()before each request andStore()after successful runs StaticKnowledgeBasefor testing and simple use casesWithKnowledgeBaseandWithKnowledgeBaseAutoStoreagent options
MarshalMessages/UnmarshalMessagesfor JSON round-trip of conversations- Envelope pattern with
kindandtypediscriminators for all part types RunResult.AllMessagesJSON()andNewMessagesJSON()helpers
ImagePart,AudioPart,DocumentParttypes implementingModelRequestPartBinaryContent()helper for base64 data: URI generation- Full serialization support for multimodal parts
- Per-tool
PrepareFuncfor dynamic include/exclude/modify at each agent step - Agent-wide
WithToolsPreparefor bulk tool filtering - Context-based tool availability (e.g., hide tools based on run state)
CallDeferrederror type for tools that pause the agent for external resolutionRunResultDeferred/ErrDeferredfor clean deferred signalingWithDeferredResultsto resume runs with externally-resolved tool results- Mixed deferred and normal tool calls in the same step
FanOutNodefor parallel branch execution via goroutinesSend[S]directives andReduceFuncfor state merging- Error propagation from parallel branches
- Mermaid diagram support for fan-out nodes
GetHistory()for browsing checkpoint historyReplayFrom()to resume from any checkpoint stepForkFrom()to branch with modified stateStatefulToolinterface for tool state persistence across checkpointsExportToolStates/RestoreToolStatesfor checkpoint-aware tools
Storeinterface with namespace-scoped CRUD and searchMemoryStore(in-memory, thread-safe) implementationSQLiteStore(persistent, pure-Go via modernc.org/sqlite)StoreKnowledgeBaseadapter bridging Store to KnowledgeBase interfaceMemoryToolfor agent-accessible memory operations
StepEvaluatorinterface for per-step scoring- Built-in evaluators:
MaxStepsEvaluator,NoRetryEvaluator - Step scores in
CaseResultand aggregated reports
- Terminal UI using bubbletea with color-coded message display
- Step mode (press 's') and auto mode (press 'a') for agent execution
- Tool call formatting, usage stats, and scroll navigation
cmd/gollemCLI entry point for interactive debugging
- Provider fallback chains — FallbackModel tries multiple models in order until one succeeds
- Rate limiting middleware — token bucket rate limiter with configurable rps and burst
- Retry middleware with exponential backoff — configurable max retries, delay caps, RetryIf predicates
- Request/response caching middleware — SHA-256 hash-based cache with TTL expiration and stats
- Reflection/self-correction pattern — RunWithReflection loops output through a validator with configurable iterations
- Comprehensive README.md with quick start, architecture diagram, and feature documentation
- CONTRIBUTING.md with development setup, code style, and PR process
- CHANGELOG.md documenting all phases
- New examples: temporal, evaluation, multi-agent delegation, deep context management, graph workflows
- SSE transport for MCP servers
- Multi-server Manager with namespaced tool aggregation
- ToolSource interface for unified client usage
- OpenTelemetry tracing and metrics middleware
- Streaming middleware support
- Dataset and Case types for structured evaluation
- Built-in evaluators: ExactMatch, Contains, JSONMatch, Custom, LLMJudge
- Runner with multi-evaluator support
- Report aggregation with pass/fail scoring
- Agent delegation via AgentTool
- Sequential handoff pipelines
- Typed graph engine with conditional branching and cycle detection
- Mermaid diagram generation
- TemporalModel wrapping model requests as activities
- Tool call wrapping as activities
- TemporalAgent orchestrator
- Activity collection for worker registration
- Planning tool for multi-step task coherence
- Checkpoint save/load/resume system
- Custom JSON serialization for ModelMessage interfaces
- LongRunAgent wrapper combining all deep features
- Three-tier context compression (offload large results, offload inputs, LLM summarization)
- Token estimation utility
- Filesystem-backed context store
- ContextManager as HistoryProcessor
- Dynamic system prompts (WithDynamicSystemPrompt)
- History processors (WithHistoryProcessor)
- Human-in-the-loop tool approval (WithToolApproval)
- Node-by-node agent iteration (Agent.Iter)
- Concurrency and tool call limits
- Toolsets for grouped tool management
- Makefile with comprehensive targets
- golangci-lint v2 configuration
- GitHub Actions CI/CD workflows
- MIT License and .gitignore
- Testable examples