Floret is a reusable Go engine for interactive AI agents. It owns the model loop and the complete admitted Agent lifecycle: canonical messages, threads, turns, runs, tools, approvals, todos, artifacts, context, SubAgents, recovery, provider state, prompt cache, and observable execution facts.
The host application owns product UI, credentials, provider profiles, resource authorization, routing, read state, uploads before admission, and transport diagnostics. It must not persist or rebuild a second queryable Agent lifecycle.
Hosts can use provider.ParseOpenAIModelMetadata to read explicit serving facts
from OpenAI-compatible model inventories. Missing limits and capabilities remain
unknown; conflicting declarations fail. config.ReasoningLevelUltra is available
only when the selected gateway explicitly advertises that effort. Discovery,
selection, protocol routing and user overrides remain host-owned.
Tool repetition is evaluated in model call order across local and hosted
activity. Only consecutive calls with identical complete arguments count;
descriptions are significant. The Engine rejects a repeated local call with
paired feedback before allowing one decision to adjust or summarize. Hosts can
inspect runtime.ThreadTurnFailure.ToolRepetition for safe exact diagnostics.
Floret is not a graph workflow framework, a multi-agent orchestrator, or a product persistence layer.
Hosts may use provider.PrepareModelImage for bounded, deterministic model-only
PNG/JPEG/WebP/static-GIF resizing and quality compression. Explicit options own
quality, longest side, source bytes and pixel limits. EXIF orientation is applied,
alpha is retained, and animations are preserved unchanged within bounds or rejected
without selecting a frame. Hosts own product defaults and coordinate mapping;
source identity and original dimensions are returned alongside model dimensions.
Always transform original authorized bytes before request estimation and freezing.
No derivative storage or conversation migration is introduced.
Hosts can explicitly opt into model-only PNG compression with
provider.PrepareImage. It preserves dimensions and source identity, keeps
transparency lossless, and only uses a smaller JPEG candidate. The zero quality
policy preserves bytes. provider.CheckRequestBytes checks exact rendered
JSON independently of tokens; provider.RequestByteLimitError retains the
existing overflow classification. provider.DeepSeekOptions.MaxRequestBytes
applies the same optional limit before preparation and dispatch. Canonical assets
and historical records remain unchanged; transport retries reuse frozen bytes.
Activity window consumers may opt into source-backed summaries, bounded field ranges, and atomic selected values through the optional runtime reader interfaces. See thread updates for authorization, budgets, live replacement and historical preparation contracts.
Set ContextPolicy.ModelMaxOutputTokens to the model output capability to enable request-fitted budgets. MaxOutputTokens remains an explicit per-request ceiling. Automatic output is min(model capability, effective window - projected input - min(window / 100, 4096)); automatic compaction starts at 90% of that window. An explicit ceiling is never silently reduced and may require earlier compaction. The margin is inside the default 10% compaction buffer, not another output reserve. Policies omitting ModelMaxOutputTokens retain their published v7 output-reservation semantics. Automatic summary and title requests also respect the opted-in model capability.
Gateways declare provider.OutputControlClient or provider.OutputControlServer. Client-controlled prepared requests implement PreparedRequestOutputLimiter to return a new immutable wire snapshot from frozen input. Attachments and managed facts are not resolved again; network retries replay the final snapshot. A server-controlled gateway cannot accept an explicit client ceiling. Observation reports request_output_tokens, output_control and safety_margin_tokens for the actual request, separately from input usage and composition estimates.
Domain schema 32 retains the atomic 17 -> 18 output-budget edge and 18 -> 19 for canonical parent events, and appends 19 -> 20 for completed-error input, retaining every older migration and all historical conversation facts without inferring historical capabilities. The 21 -> 22 edge admits request-bound accounting; 23 -> 24 adds frozen character attribution and input measurement scope without rewriting canonical entries. Older writers reject the upgraded envelope. Cancellation, bounded length continuation and unknown-effect recovery retain their existing boundaries.
The Engine evaluates each complete frozen next request once. Projected input is qualified native input (or native input plus normalized output at a committed response boundary) plus an estimate of only the subsequent frozen protocol input. Without a matching measurement it uses the complete conservative request estimate. The automatic threshold stays min(90% of the window, request safe limit); output reservation semantics and the bounded overflow recovery are unchanged.
Gateways may implement provider.PreparedRequestMeasurement and attach provider.RequestMeasurement to native Usage. Evidence binds the exact attempt, account/execution identity, full frozen input and successful terminal response. The provider.RenderedMeasurementPrefix and RenderedMeasurementSuffix helpers hash ordered protocol items and the fixed input surface without retaining content. Suffix estimation uses Floret's estimator; adapters do not calculate pressure. Neither method may read attachments, refresh context, authorize tools or count through the network. Output refits and retries preserve the frozen input.
InputTokenScope retains its protocol meaning: provider_execution alone never qualifies. Incomplete visible attribution does not invalidate a proven total. Encrypted reasoning requires explicit protocol inclusion evidence and a matching native boundary, never a ciphertext-length estimate. New opaque suffixes invalidate calibration. Model, account/connection, tool/system surface, estimator, canonical history and compaction lineage must match. Native cache buckets are counted once; OutputTokensReported distinguishes explicit zero, and OutputIncludesReasoning prevents duplicate output counting. Aggregated or failed attempts cannot establish a response boundary. Input plus output is a conservative projection, not measured current occupancy, because some generated tokens may not be replayed.
Automatic pressure is evaluated only after context collection and freezing. Responses update measurements without scheduling a second compaction path. Manual and overflow compaction retain the same bounded generate/validate/install lifecycle. A safe soft-threshold no-op permits sending and is suppressed only for the same frozen input and budget; hard-limit failures never dispatch. Successful installation clears old measurement and continuation. Existing decision evidence retains selected boundary and invalidation reason without a second ledger.
Domain schema 27 -> 28 fences these semantics. It validates canonical authority without rewriting historical messages, usage, summaries or missing evidence. Historical input anchors remain eligible under their original transparent-input contract; new response boundaries require new evidence. Invalid calibration falls back to estimation and cannot prevent historical thread opening.
Upgrades preserve supported historical conversations as a release requirement. Domain schema 26 -> 27 repairs only compaction references proven by canonical journal identity or the exact released writer contract. Startup and read-only inspection share this migration; unresolved authority rolls back the complete transaction. Historical messages, tool outcomes, attachments, timestamps and compaction decision evidence remain intact. No task or tool resumes automatically.
The journal owns durable message identity. Engine installs committed canonical messages and the complete canonical context after compaction; observation events never persist the same output again. Invalid boundaries fail explicitly instead of guessing a retained exchange. Provider-context revision v11 establishes an observable lineage upgrade without rewriting old requests, responses or usage.
Immutable synthetic released-writer databases cover repeated compaction, interleaved observations, Fork and nested Fork. Ordinary tests verify migration and rollback; candidate and published adoption gates also continue these threads through public APIs across restart. Incident qualification uses separate copies and fake providers, never production execution.
The Engine owns one ordered response fragment collection for each exact Run and
provider attempt. Optional provider.Event.OutputPart identifies native items
and zero-based output/content positions; gateways without native items remain
valid and use Engine channel/hosted boundaries. DeepSeek preserves native parts,
including terminal suffixes that update an earlier fragment.
Harness commits those fragments, classified calls and opaque provider state in one existing provider-context transaction. One memory-only batch handoff installs the canonical view before tool execution. Observation events do not independently settle drafts. Current-attempt drafts can survive a refresh; committed canonical text is authoritative and replaced attempts cannot change it.
Schema 24 -> 25 stores only content/reasoning source references on canonical messages. It preserves historical public item IDs and entry references, reveals correction-response reasoning at its original position, and keeps invalid calls and validation feedback out of actionable tool rows. Technical feedback remains in model history. Legacy shape interpretation runs only in the atomic startup migration; current restart does not rewrite records. Hosts render Floret order and IDs directly without content deduplication or client sorting.
New assistant and thinking sources expose optional ThreadItem.OutputStartedAt and OutputEndedAt in views, windows and history. The Engine records the first and last nonempty output chunks; sealing does not extend the interval beyond the last chunk. This is received-output timing, not provider compute time. A live source has no end yet, a single chunk has equal endpoints, and historical unmeasured sources omit both. Canonical metadata preserves the interval across restart and Fork without rewriting older records or changing the schema.
Opt in with runtime.WithAgentGoals() to let the executing model maintain one
clear objective and reflect before naturally stopping. Use the optional
runtime.ThreadGoalController for user SetGoal / DeleteGoal operations;
changes appear in ThreadView.Goal and the canonical timeline immediately and
enter the next new model request. Management never starts execution. Reflection
reuses the existing context, provider continuation and bounded stop hook; Goal
completion requires a current evidence-bearing review and successful Turn end.
Goals are independent of todos. The 22 -> 23 schema edge preserves history.
The Harness installs the Goal tool, dispatch, result handling and reflection
together for each enabled execution, including explicit Goal continuation without
agent-wide opt-in. Goal declares a write to canonical thread state; it has no
external resources and does not enter host effect authorization. Host tools retain
their normal authorization, and a conflicting host Goal tool is rejected when the
canonical tool is installed.
For an explicit user command that also pursues the objective, use the optional
runtime.ThreadGoalSubmitter.SubmitGoal. Persist product execution authorization under
runtime.GoalSubmissionRequestKey before submission so ordinary execution and restart
resolve the same identity. It atomically saves the Goal and admits
its submitted text as a normal user Turn only when idle. Active and waiting
Turns are updated without queuing work or resolving interactions. Replays retain
the original decision, including after Stop or restart. Execution preparation
failures retain the Goal and use the existing recoverable Turn failure surface.
This additive API reuses schema 24 journal shapes; no migration is needed.
Goal field descriptions explain set/delete/review requirements; runtime facts
are engine state, not new user instructions or additional authorization.
See the Goal contract.
Set runtime.Options.EnableParentEvents explicitly to enable the optional
runtime.ThreadParentEventService returned by Host.ThreadService. The default
keeps existing hosts' model inputs unchanged. This additive API decision serves
Flower's child reporting tools without adding methods to ThreadService.
ReportToParent derives the direct parent from canonical child ownership and
verifies the authorized active tool invocation. Reports require nonempty UTF-8
text up to 8192 bytes. Exact invocation replay returns its stable receipt;
conflicting content or identity fails. Hosts supply invocation authority, never
model-selected sender, recipient or wakeup flags. Reads must be freshly
authorized by the host. Read-only child policy may permit reporting to its own
parent without granting other thread writes or interaction responses.
Completion, failure, cancellation, confirmed interruption, typed execution request timeout, input and approval facts create references atomically with their source. Running states and message previews create none. Receipts and bounded, frozen admissions live in the existing journal. No inbox, consumer table, periodic scan or second lifecycle is introduced. Only unresolved interactions are bootstrapped on opt-in; historical terminal facts are not backfilled.
A natural logical provider boundary admits pending events after tool pairs and before budgeting, compaction and request freezing. Receipt never sends, steers, wakes an idle thread, answers an interaction or resamples a natural completion. Retry retains admitted text even when preparation failed. Forks inherit their cut's receipts and admissions; later events still target the original parent. Compaction preserves canonical read access and admission coverage.
Automatic event projections include stable source and event references. Reports have at most a 512-byte UTF-8 preview. Individual projections are bounded by 2 KiB/512 estimated tokens and each new event message by 8 KiB/2048 estimated tokens, including framing. Unresolved interactions and unknown-effect failures have priority. Overflow includes a closed event range and requires reading the omitted events before claiming all delegated work has been reviewed. Normal whole-request budget failures remain authoritative; no extra sampling drains notifications. Error previews contain reason codes, not raw failures or approval commands. Use sufficient untruncated reports directly; read report events only when their full text is needed. Completion events contain no final report: hosts expose a separate result read capability for final handoffs and failure details. Reuse an already available result for the same child turn.
tools.SubAgentOperationStatus identifies metadata-only child checks in typed
Activity presentation. It is distinct from SubAgentOperationInspect, whose
result may include a complete final report. This additive action serves Flower
without changing existing inspection, waiting, or event-read contracts.
ListParentEvents exposes metadata, filters and explicit pagination;
ReadParentEvents reads full reports by event ID or a closed immutable range.
Both inputs optionally accept Latest or BeforeEventID for backward navigation,
returning chronological events and PreviousBeforeEventID as the earlier cursor.
Do not combine these options with AfterEventID. Existing omitted options retain
forward pagination. A presentation can retain a finite reading interval, fetch
metadata on scroll, and fetch a single report only when its detail is visible.
ListParentEventsInput.AfterOrdinal and BeforeOrdinal optionally seek an exclusive interval on the current canonical path. Zero omits a bound. A before bound selects its latest receipts; otherwise selection starts at the after bound. Both directions return chronological events. These fields exclude event-relative cursors and Latest; nonzero bounds must increase. Returned event cursors and first/last identities describe the full path, so subsequent scrolling can leave the initial ordinal interval. Positions are canonical entry ordinals, not item ranks or timestamps; callers must reselect after a path change. Exact report reads retain the existing event-ID and fixed-range contracts. An optional LeafID selects an ancestor still on the current path; append preserves that selection, while removal from the active path fails with ErrJournalInvariant. Every page returns its actual LeafID. Interaction resolution is current at the read transaction and does not claim to be the historical resolution at that leaf.
ThreadView.ParentEvents is a bounded paginated receipt view separate from
streamed item ordinals. Successful event pages always encode events as an array,
including an empty array for an empty page; disabled parent events remain absent. Its Admitted field means context placement, never
“model read”. Hosts use existing subscriptions before checking pending events
when implementing event-aware waits; waiting timeouts are not execution timeouts.
ParentEventPage.ThreadID (thread_id) identifies the queried canonical thread
path on every successful list, read and current view, including empty or filtered
pages. A fork inherits events without rewriting their original ParentThreadID;
that recipient can differ from the page identity. Hosts validate page scope
against the requested thread and authorize source navigation independently.
ParentEvent.ParentTurnID (JSON parent_turn_id) identifies the most recently started ordinary parent turn preceding receipt in canonical Path order. It remains that turn after termination until another ordinary turn starts; context compaction does not advance it. No preceding ordinary turn means the field is omitted. Forks retain inherited ownership and original recipient identity. List, full read, pagination and restart derive the same field without changing historical bytes or admission. This projection does not change the domain schema. Hosts own presentation. The optional ActivityError.Code retains a stable diagnostic identifier (up to 128 ASCII letters, digits, underscores, dots or hyphens), separate from its readable message. Hosts may use it to localize presentation; it never changes the recorded tool outcome or authorizes retries.
Build with Go 1.27.2.
go get github.com/floegence/floret/v7@v7.40.0Production integrations must resolve the published module. Do not use a local
replace, go.work, or sibling repository path. Earlier major versions remain
available only from their published tags; v7 does not restore retired facades.
Prepared request estimates count visible input, protocol framing, and conservative media/unknown-content bounds. Encrypted and redacted reasoning stays replayable, but ciphertext bytes are diagnostics, not token counts. Such estimates retain partial attribution and cannot calibrate pressure from provider-execution usage. The Engine's bounded overflow recovery remains authoritative for hidden input.
Every Agent uses one explicit provider.Gateway. Floret allocates durable
thread, turn, and run identities; an application supplies only a stable
identity.LogicalRequestID for each logical mutation. This production example
uses the official OpenAI-compatible Gateway and SQLite:
package main
import (
"context"
"os"
"github.com/floegence/floret/v7/config"
"github.com/floegence/floret/v7/provider"
"github.com/floegence/floret/v7/runtime"
"github.com/floegence/floret/v7/storage"
)
func main() {
ctx := context.Background()
gateway, err := provider.NewOpenAICompatible(provider.OpenAICompatibleOptions{
Provider: "openai", Model: "gpt-4.1-mini",
BaseURL: "https://api.openai.com/v1", APIKey: os.Getenv("OPENAI_API_KEY"),
StateCompatibilityKey: "openai:gpt-4.1-mini:chat-completions:v1",
Capabilities: provider.Capabilities{
Reasoning: provider.ReasoningUnsupported,
AttachmentPayload: provider.AttachmentDescriptors,
},
})
if err != nil { panic(err) }
agent, err := runtime.NewAgent(config.AgentConfig{
Profile: config.AgentProfile{ID: "assistant", Name: "Assistant"},
SystemPrompt: "Answer clearly and concisely.",
Context: config.ContextPolicy{ContextWindowTokens: config.DefaultContextWindowTokens},
}, gateway)
if err != nil {
panic(err)
}
host, err := runtime.Open(ctx, runtime.Options{Storage: storage.SQLite("floret.db")})
if err != nil {
panic(err)
}
defer func() {
if err := host.Shutdown(context.Background()); err != nil {
panic(err)
}
}()
service, err := host.ThreadService(runtime.AgentFactoryFunc(func(context.Context, runtime.AgentRequest) (*runtime.Agent, error) {
return agent, nil
}))
if err != nil {
panic(err)
}
created, err := service.Create(ctx, runtime.CreateThreadInput{RequestKey: "create-conversation-42"})
if err != nil {
panic(err)
}
_, err = service.Send(ctx, runtime.SendInput{ThreadID: created.ThreadID, RequestKey: "send-message-42", Input: runtime.UserInput{Text: "Hello"}})
if err != nil {
panic(err)
}
}runtime.UserInput.References and runtime.UserInput.Context are admitted
with the user message and remain model context through follow-ups, Ask User
responses, retries, forks, restart, and compaction. Reference kind, label, text,
and truncation status render in submitted order; opaque ResourceRef values
never enter model text. Context items have Kind, Title, and Text and describe
non-secret runtime facts effective from that message. Append a new snapshot when
facts change. Context is included in admission fingerprints and request-prefix
checks; it does not grant tool authorization.
Hosts may also set runtime.SendInput.SupplementalContext for material that is
needed only by the current provider turn. Floret validates and renders that
context for the provider without adding a second canonical conversation
message. The pre-dispatch checkpoint records only that an ephemeral overlay was
present; it never stores the overlay, its payload hash, provider continuation,
or overlay-derived request measurements.
Hosts that need immutable execution metadata may construct an Agent with
runtime.WithAgentRunLabels. Correlation labels remain observable, while the
opaque Host map reaches provider requests, permission checks, and local tool
invocations without becoming durable conversation state.
Run it with OPENAI_API_KEY=... go run ./cmd/examples/openai-sqlite. The complete
example also reads the authoritative assistant projection. florettest remains
test-only; use it for deterministic provider scripts and florettest.NewIDSource
for deterministic lifecycle identities.
| Package | Responsibility |
|---|---|
identity |
Thread, turn, run, prompt-scope, trace, logical-request, and artifact identities |
config |
Provider-neutral Agent profile, prompt, context, and reasoning policy |
runtime |
Immutable Agent construction, durable Host lifecycle, commands, queries, and subscriptions |
observation |
Sanitized runtime events and host-facing projections |
tools |
Local tool definitions, permissions, resources, effects, and results |
tools/webfetch |
Secure public-text HTTP/HTTPS fetch tool with fixed network and output limits |
provider |
Model Gateway contract and official provider constructors |
storage |
Opaque storage values and official memory and SQLite constructors |
storage/spi |
Advanced physical storage implementation contract |
florettest |
Scripted gateways and public conformance suites for tests only |
Ordinary applications use identity, config, runtime, observation,
tools, the official provider constructors, and opaque storage.Source
values. Custom provider transports and physical storage implementations are
advanced integration surfaces with separate conformance suites. Downstream
code must never import internal/*.
Tool definitions may opt into BatchExclusiveGroup. Two or more valid,
prepared calls in the same nonempty group receive paired BATCH_CONFLICT
results before authorization or execution. Unrelated calls continue normally.
This host-only declaration does not serialize calls, infer dependencies, or
replace resource permissions and cross-batch locking. Empty groups preserve
existing behavior.
Tool definitions may provide InvalidActivity when a host needs to preserve a
safe display label from a parseable JSON object that fails the input schema.
Floret uses that callback only for presentation: the invalid invocation still
fails closed before permission, effect dispatch, and handler execution.
Question activity may include host-authored answer summaries for completed
prompts. A secret answer is represented only by Redacted: true; Floret
rejects a redacted answer that also carries values. These fields are display
data, not an alternate input-response or durable message authority.
Structured rows and patch mutations may each carry an optional Target (ActivityTargetRef) identifying their own observed resource. Targets survive cloning, result merges, finalization and journal replay. Paths are navigation facts, never authorization or a guarantee that the resource still exists; hosts must authorize current access. Omitted targets preserve existing JSON behavior. Top-level targets and targets on structured inputs, result rows, and patch mutations retain exact Path and URI values in canonical history and host-facing live observations. Authorized Activity display preserves host-authored source text without guessing paths in prose or code; credential protection still applies. Diagnostic traces redact navigation paths at every target location without changing canonical facts. This boundary does not rewrite or reconstruct previously redacted history.
Structured activity may include bounded, ordered Rows containing
host-sanitized text, Markdown, or code. Floret validates and preserves these
display rows without interpreting product tools or accepting arbitrary JSON
payloads. Optional Inputs retain safe invocation details independently of result
rows. RowsProvided distinguishes a captured empty result from missing historical
output. Code rows support a syntax Language, up to 64 KiB of content, and an
explicit Truncated preview marker. Redacted and InvalidUTF8Replaced
report credential protection and invalid-byte replacement independently of
truncation. Other row text remains bounded at 8,000 runes.
Activity presentation is cumulative for one tool invocation. A result may add terminal status and output, while non-empty display facts from the matching tool call remain available in events, canonical views, and reopened threads.
tools.TerminalActivityPayload adds optional operation, sent-byte count,
output cursors, remaining-output flag, total bytes, public execution location,
and timeout facts. Hosts author the label and description and retain only safe
command display text; raw stdin and credentials are never display fields.
Read cursor snapshots replace their cursors and has_more together, so a final
page can clear the flag. Status-only updates preserve the prior snapshot.
SubAgent management activity uses a dedicated operation payload that preserves the exact action, ordered child targets, and bounded outcome counts. The existing single-SubAgent payload remains the durable child-thread fact; hosts do not need to infer management actions from labels or collapse multi-child results.
tools/webfetch.New supplies the product-neutral web_fetch implementation.
It reads a known URL independently of whether a search tool is configured.
It performs GET-only public HTTP/HTTPS reads, revalidates redirects, DNS, and
dial targets, rejects non-text bodies, and returns Markdown or text under fixed
limits. Its typed Activity carries the requested URL, response metadata, a
2,000-character preview; complete content remains in the tool result and
artifact. It does not discover or request page icons. Hosts own static tool
iconography, visibility, current product permission policy, and UI.
Authentication, custom headers, non-GET requests, binary downloads, and browser
rendering remain separate host capabilities.
runtime.Host belongs in the composition root. Host.ThreadService returns the
single typed lifecycle boundary. Title snapshots expose Title, TitleStatus, and
TitleGeneration; hosts order them independently of body updates and activity.
See the title snapshot contract. Its Create, Fork, Delete, SetTitle,
List, View, History, Send, Respond, Cancel, Retry,
queue, import, and Subscribe methods all operate on stable thread and request
identities. Child agents are ordinary child threads with explicit parent
identity, so they use the same current-view and command contracts.
The optional runtime.ThreadToolResultReader.LookupToolResult reads confirmed
local tool arguments and output from the active journal path using exact thread,
turn, run, and tool-call identity. Hosts authorize and interpret that private
output; the query neither runs a tool nor changes history.
The built-in backend resolves the exact call/result source-locator pair and
validates current active-path membership before reading their bodies. It does
not project or scan unrelated historical messages. Custom journal repositories
without this internal capability retain the published complete-read adapter.
Live and historical items retain their creation times, including original
occurrence times in forks.
Hosts may pin a committed assistant answer with the optional ForkThreadInput.SourceItemID; the runtime resolves its canonical journal boundary and rejects unknown or conflicting anchors.
The optional runtime.ThreadQueryReader implements Query, Read, and
Aggregate using threadquery types. It searches canonical active-path threads,
user/assistant messages, and persisted local/hosted tool facts through the
canonical owner's transactional source-locator metadata. Hosts provide an exact readable ThreadID set
and an authority key on every call; reference snapshots never grant access.
Filters combine with AND (values within one field use OR), support literal
Unicode substring/keyword/phrase search, and use UTC half-open time ranges.
All sorts use stable identity ties. Queries default to 50 records (maximum 200);
Read explicitly continues UTF-8 chunks up to 16 KiB in responses up to 64 KiB.
Counts and grouping use the same authorized filter. Cursor snapshots last up to
five minutes within a 64 MiB global budget, survive append/completion/rename,
and fail explicitly after scope changes, deletion, expiration or restart.
See the thread query contract for keys and limits.
runtime.MessageReferenceThread adds a lightweight admitted snapshot using
ReferencedThreadID, Label, and Text. The provider receives the explicit
referenced identity as data; hosts retain read authorization. Existing reference
rendering and input fingerprints stay byte-identical when this field is absent.
The optional runtime.ThreadSendReader.LookupSend returns original admitted
input for a request key, including after queue edits, promotion, removal, or
restart. Hosts can validate transport retries against canonical input without
refreshing context or resolving attachments again.
Host.MediaInventory(ctx) exposes opaque media descriptors retained by every
canonical journal, including archived threads, inactive paths, and queue facts,
and reports whether every retained execution is terminal.
Hosts use this read-only inventory to retain their immutable media bytes instead
of inferring absence from a current view. It grants no resource access. Hosts
must hold their tool-media write gate before reading this snapshot and collect
only when Idle is true, or before deferred execution is activated. Other
not-yet-admitted uploads require their existing owner protection. Floret owns no
media byte store. Host.ThreadMediaInventory(ctx, threadID) returns the same
retention facts for one thread so hosts can process large stores incrementally
without retaining a cross-thread media snapshot in memory.
The optional runtime.ThreadQueueController supports EditQueued with a text
precondition and SendQueuedNow to stop gracefully and start one chosen queued
input. Text editing preserves attachments, references and context. Complete editing
uses paired ExpectedInput and Input to replace text, attachments, references
and context atomically while preserving identity and position.
Already admitted or concurrently edited input is rejected without replacement.
ThreadQueueEditReader.LookupQueuedEdit reads immutable before/after content
from those canonical facts to validate retries after promotion or restart.
DeleteQueuedInput.ExpectedInputSHA256 optionally requires the complete pending input
to match the lowercase SHA-256 hex digest of its encoding/json representation
before removal, returning ErrRequestConflict for missing, started or
changed items. Hosts can use this boundary to take a queued message back into an
ordinary draft without racing automatic promotion. Exact committed retries succeed.
See the queue control contract.
Each thread has one in-memory runtime owner. Send first commits canonical turn
acceptance, then publishes and returns the user item and active current view
before provider dispatch. The canonical journal is the only durable fact
source. Provider and tool I/O execute outside the thread lock.
Cancel is idempotent for every known thread. Its default immediate mode
preserves synchronous terminal settlement. Interactive hosts can opt into
CancelInput.Mode: runtime.CancelModeGraceful: Floret commits the stop request,
fences new execution, cancels the execution context, and returns acceptance.
In-flight tools share one five-second window to commit confirmed results through
the normal output and artifact path. The terminal is cancelled when all effects
are confirmed; real tool errors and completed effects remain visible. A stop does
not roll back earlier changes. Queued input remains queued until a later explicit
submission or promotion. CancelInput.IncludeDescendants also stops the existing
child subtree, including children of an idle parent, while preserving independent
threads. Child creation and stop admission share one boundary; canceled child
creation cannot run after waiting for that boundary.
Retrying a failed turn uses its latest committed save point and retains completed tool results. Repeated failures and restart preserve that context without adding another user message. A completed-turn retry retains its regeneration behavior. Thread-level queue facts can interleave a waiting turn without invalidating its canonical history or preventing a response after restart.
ThreadView.Cancellation and ThreadSummary.Cancellation carry the canonical
source, exact execution identity, mode, and request time. Active views with that
fact are stopping; hosts must keep that indication until the authoritative view
becomes terminal, independently of the HTTP request. A dispatched effect with
unconfirmed outcome fails the turn with effect_outcome_unknown; only unresolved
dispatched tools become unknown, while undispatched calls are cancelled. Floret
never automatically replays unknown effects or permits retrying that turn. Late
results cannot change the terminal or a later turn. Use tools.CanceledResult
only when execution has actually ended; a bare context.Canceled is insufficient.
Schema v11 appends the v10 to v11 migration without rewriting historical records
or inventing missing stop provenance.
A completed tool may return tools.Result.InputRequired with a validated
tools.InputRequest. Completed success and error results may request input; errors retain their status.
Unconfirmed, canceled and declined results cannot request input. Floret commits the result and pauses before the next model
request, after every tool in the batch settles. The existing input interaction
survives restart; Respond must answer every question, and all batch interactions
must be resolved before continuation. The original tool is never replayed.
Prompts, options, and answers are durable, non-secret data. Use acknowledgment
choices for external user actions; collect passwords and tokens outside the
agent. Pending remains asynchronous host work and cannot be combined with input.
Domain schema v21 appends v20 to v21 while preserving the original v11 to v12
contract and all historical facts.
OutputPolicy.ArchiveAboveBytes independently archives complete Text above a positive byte threshold when PreserveFull is enabled, even without visible truncation. Zero retains archive-on-truncation behavior. Archival uses the existing atomic result/artifact settlement and never marks uncut Text as truncated.
Ask User runtime.InputPresentation exposes optional ReasonCode,
RequiredFromUser, and EvidenceRefs from the validated control signal in current,
summary, and historical views. Evidence associates facts; it grants no access or
permission. Absent historical fields remain absent.
Ask User runtime.InputQuestion preserves optional Header, WritePlaceholder,
ChoicesExhaustive, and rich Choices from the original validated call across
live updates, reads, and restart. Each InputChoice has an original ChoiceID,
Label, optional Description, and the established answer Value. Submit
Value through Respond; the original identifier is display identity, not a
new answer encoding. Existing v7 Options strings remain supported and match
rich choice values in order. Historical and tool-origin input without rich
metadata remains valid; hosts must not invent missing presentation content.
Respond resolves the matching approval or input interaction in place.
Public Ask User answers become one canonical user message and remain in every
later provider request. Secret answers are sent only to the current continuation;
the journal and later context retain a redacted marker, never the secret value.
runtime.NewAgent resolves the Agent profile, system prompt, Gateway, tools,
capabilities, reasoning policy, and execution policy. The first provider
checkpoint freezes that complete execution surface for one Turn. Ask User,
ordinary tool loops, retries, and restart recovery reuse it exactly. Provider
natural stop completes the Turn; there is no second completion protocol.
Assistant citations are canonical message facts. provider.Source keeps optional
StartIndex and EndIndex as end-exclusive Unicode code-point positions in the
complete response text. runtime.ThreadItem.Sources exposes detached, message-relative
ranges in current/history views. Unsafe URLs are dropped; malformed or cross-segment
ranges become unlocated sources. Hosts render exact citations and list unlocated
sources without inferring URLs from provider markers. Sources events remain live
observations; they are not a second durable source store. Existing schema-16 bytes
without sources remain unchanged.
Provider credentials and editable profile sources remain in the host.
An AgentFactory may select a new system prompt, tool surface, provider, model,
or reasoning policy for each new Turn. The canonical conversation remains
append-only. Floret maintains a content-addressed render lineage for each exact
execution surface, invalidates exact-surface continuation when that surface changes,
and compacts only when explicitly requested or when the selected model's
context window needs it. A waiting interaction, tool continuation, retry, or
restart remains frozen to the surface recorded for that Turn. Historical tool
calls remain readable when their definitions are removed; a new call to an
unavailable tool returns a safe ordinary tool result and the model loop
continues.
Hosts that need live capability changes can explicitly return
ToolSurface.RefreshProviderSurface: true from WithAgentDynamicToolSurface.
Each subsequent provider request then uses current system text and local/hosted
tool definitions. Provider, model, reasoning, context policy and compatibility
identity remain fixed by the first Turn checkpoint. Changed envelopes establish
a new render lineage without compaction or rewriting earlier checkpoints.
The zero-valued provider.State.ReusePolicy requires an exact surface. Adapters
may declare provider.StateReuseCanonicalHistory when they validate the complete
canonical prefix before replaying native history across tool or permission changes.
Unknown policies fail explicitly. Model/account identity changes, canonical
lineage resets, installed compaction and supplemental secret input still fence state.
Completed response state commits atomically with its canonical assistant and
tool-call output before tool dispatch or another provider request. Failure, Stop
and restart retain the last committed compatible state and its source Run/Turn;
terminal settlement never reinstalls a pre-compaction result. The default remains the frozen Turn surface.
Dispatch-time permission resolution and existing approvals remain independent:
refreshing model-visible tools does not authorize an invocation or settle a wait.
Gateways may declare Capabilities.ReasoningHistory as
provider.ReasoningHistoryCurrentUser to omit assistant reasoning before the
latest canonical user message from transport. Visible history and tool pairs
remain intact; tool loops and truncated output after that input retain their
reasoning. Ephemeral supplemental answers do not create a replay boundary.
Canonical storage and earlier checkpoints are unchanged. The default
ReasoningHistoryAll preserves all reasoning. Include the selected policy in
the gateway's state compatibility identity when changing an existing adapter.
Automatic provider recovery belongs to Floret. Agents default to four additional
attempts, with at most three timeout retries, jittered 2/4/8/10-second backoff and
a five-minute window from the first failure. WithAgentProviderRetryPolicy
accepts an explicit validated policy; use ProviderRetryPolicy{Disabled: true}
to disable recovery. SDK transport retries must be disabled.
Gateways may emit optional typed provider.EventTransport observations for
connection, send, receive, completion and failure phases. The Engine binds its
own logical request and attempt identity; ThreadRunProgress.Transport exposes
only the current request's memory-only snapshot. Planned transport changes remain
visible during backoff. These events never append model output, count tokens,
renew semantic timeouts, or authorize retries. Product transport selection and
connection pools remain gateway-owned. Retry preparations preserve the frozen
payload and estimate while refreshing the attempt's transport measurement prefix;
usage without matching transport evidence remains billable but cannot establish
an exact context anchor.
The Engine bounds each preparation context to one logical frozen request. That context survives output refits and all physical retries, then is cancelled when the request settles or is discarded. Compaction bounds each candidate and summary batch separately. Remote gateways can release frozen resources on cancellation; closing a single attempt still preserves replay during the preparation lifetime.
WithAgentProviderRequestTimeoutPolicy configures one physical request clock,
shared by ordinary requests, compaction and titles. Zero fields use
DefaultProviderRequestTimeoutPolicy: five minutes without first semantic output,
two minutes without further output, five minutes while a provider-hosted tool is
active, and fifteen minutes total per attempt. Negative durations are invalid.
Text, reasoning, argument fragments and accepted tool transitions advance the
clock; heartbeats, empty deltas and usage do not. Connection opening and reading
are bounded; local tools, approvals and user input are outside this boundary.
A deadline cancels only that attempt and enters the same recovery budget.
provider.RequestTimeoutError matches provider.ErrRequestTimeout and
context.DeadlineExceeded; it does not establish execution cancellation.
ThreadTurnFailure.ProviderTimeout optionally retains the stage, timing and
attempt identity through canonical terminal metadata and restart. It is an
additive diagnostic contract; schema 17 and all historical migrations remain
unchanged. ProviderRequestProgress.LastProgressAt lets hosts display stalled
output using their own presentation clock without inventing lifecycle timers.
Provider failure evidence is available through provider.FailureDetailsForError.
FailureDetails preserves the complete original message, wrapped cause texts,
HTTP status, request/response identifiers, and failed HTTP body or SSE data
payload. Bytes use base64 in JSON, including non-UTF-8 responses. A failed read
retains all received bytes and marks BodyComplete false. WithFailureDetails
keeps error identities and retry advice and persists a versioned envelope through
canonical failure messages. Hosts must render evidence as authorized literal
text and derive separate sanitized summaries for banners and logs; original
errors are untrusted data and may contain private provider content. Historical
failures without retained evidence cannot be reconstructed. Evidence never
permits replay or changes retry decisions.
Gateways expose structured provider.RetryAdvice through RetryAdviser and
WithRetryAdvice, preserving the original error cause. HTTPRetryAdvice
parses response-time server deadlines, exact machine codes and HTTP status.
At provider transport boundaries, provider.RetryAdviceForError shares the
Engine classifier, including ordinary and wrapped EOF as stream interruption.
The outermost explicit adviser wins even with empty advice. This helper does
not schedule recovery and must not classify storage, decoding or tool errors.
The exact basispoints_tool_arguments_stalled code, including HTTP 200 stream
errors, uses RetryStreamInterrupted and the same bounded recovery policy.
Unknown codes and error prose do not establish retry permission; permanent
statuses and explicit server retry prohibitions retain priority.
Authentication, billing, invalid contracts, unknown errors and unsafe hosted
requests are never automatically replayed. Declare HostedToolDefinition.ReplaySafe
only for verified read-only provider capabilities. Expanded prepared gateways
implement PreparedRequestReplay to create fresh single-use attempts from the
original immutable rendering without reopening attachments.
Recovery retains the same turn, run and agent step. It replaces only the failed
streaming draft, never confirmed tool effects. Event.Retry and
ThreadRunProgress.Retry expose count, limit, absolute next-attempt time, reason
and replaced attempt identity for a shared host countdown and working Stop.
Retry state is memory-only; restart uses existing interrupted/manual Retry rules.
provider.Request.ReusePolicy carries the Engine's effective cache namespace,
native-state permission, and continuation preference through direct and prepared
gateways. Gateways must not broaden this policy. Supplemental context disables
application reuse and native-state retention; nil preserves defaults for callers
outside the Engine. Queue admission and replay share one validated canonical
base, so queue-only edits preserve native history without ancestor fallback.
ToolSurfaceRequest.InitialProviderSurface supplies a detached copy of the first
checkpoint's system text and tool definitions, including after restart; it is nil
before the first request. Hosts can preserve unrelated capabilities from this
snapshot while refreshing only their live policy. It contains no executable
handlers and does not authorize tools or create a second persistence contract.
Current views contain one Floret-ordered sequence of directly renderable user,
thinking, assistant, tool, and interaction items, plus pending interactions and
the accepted queue. Each item has a stable ID and ordinal; live deltas grow the
same item in place, and tool approval, dispatch, and result state update the
original tool item. Canonical reload derives the same sequence without a
presentation ledger or draft mirror fields.
Every item and interaction carries its exact TurnID and RunID, so multi-turn
history and same-turn continuation never borrow identity from the current run.
Local-tool Activity execution starts at its recorded dispatch and ends at its
canonical result. These existing timestamps survive terminal refresh, history
reads, restart and forks; admission and approval waits do not become execution
time. A missing dispatch leaves the execution interval unavailable. SubAgent
management Activity describes the invocation's outcome and elapsed execution,
while a target's saved status describes the child at that operation's boundary.
ThreadView.Turns and HistoryPage.Turns expose canonical per-turn outcome,
start/end times, elapsed milliseconds, waiting milliseconds, and work duration.
Waiting deducts the union of user-input and approval intervals; queue time is
excluded. FinalBoundaryComplete distinguishes recorded accepted final-response
item IDs from unavailable legacy boundaries. Render every FinalItemIDs segment
in order; never infer final answers from text or the latest assistant item.
ThreadItem.CanonicalOrdinal and ParentEvent.CanonicalOrdinal (JSON
canonical_ordinal) are one-based source positions on the queried canonical
Path. Merge public items and parent events by this position, preserving item
order at ties; occurrence timestamps are display facts only. Tool updates retain
their first position. Zero means an uncommitted live item, whose tail order stays
unchanged. These positions are neither durable cursors nor execution identities.
Forks derive positions from their own Path and preserve all copied occurrence
timestamps; inherited event recipient identities remain unchanged.
ThreadTurn.IntermediateItemIDs (JSON intermediate_item_ids) contains ordered,
unique segmented assistant items superseded by a later local tool call, hosted
activity or semantic continuation in the same source Turn/Run. Confirmed membership
survives later runs of the same turn; the turn RunID identifies its latest execution.
Selected windows return only selected item memberships without reading additional
history. Accepted final references
are disjoint. Length continuation alone does not supersede text. Trailing partial
answers and unsegmented legacy text remain unclassified. Hosts may fold these
confirmed intermediate items independently of terminal outcome; unknown prose
must remain visible. These are read projections, with no journal rewrite or
schema change (current domain schema 32).
ThreadView.RunID identifies only the current execution; hosts must never use
it to fill historical items. RunProgress is the actor-owned, process-local phase
for an advancing run and is absent while awaiting interaction or after the run
settles.
ThreadRunProgress.Request reports the current provider attempt's start, first
output and estimated received output tokens (text, reasoning and local tool
arguments). Estimates are incremental ASCII/non-ASCII character heuristics, not
billable usage. Hosts can render waiting duration from the start timestamp without
asking the runtime to publish timer ticks.
ThreadView.ToolCallPreviews contains memory-only, unvalidated argument previews.
Tools may opt in through tools.Definition.NewArgumentPreview, a per-call bounded,
side-effect-free parser returning a safe display name and optional line counts.
Unknown counts remain absent; known zero remains explicit. Preview errors only
remove the preview. They never authorize, dispatch, read resources, reserve item
ordinals or enter the journal. Match admitted calls by exact execution identity
and CallID; actual results replace preview counts, including zero. Both request
progress and previews are attempt-fenced and discarded on replacement or finish.
ViewVersion is process-local notification ordering, not a durable replay
cursor. Production hosts leave runtime.Options.IDSource nil; deterministic
identity injection belongs to florettest.NewIDSource.
The service returned by Host.ThreadService implements the optional
ThreadContextCompactor. Call CompactContext with ThreadID, RequestKey,
and optional ContinueGoal; keep slash-command text, drafts, attachments, and transient host
context outside this operation. It accepts an idle thread with no queued input
or unresolved interaction and returns after durable admission, before resolving
its Agent or calling the provider. Busy threads return ErrThreadBusy.
TurnKindContextCompaction identifies this control turn in AgentRequest,
ThreadView, and ThreadSummary; the zero kind remains ordinary execution.
Factories resolve the thread's configured Agent for this kind without requiring
a user message. Omitted or false ContinueGoal retains pure compaction: real Turn
and Run identities, shared summary generation, and no ordinary answer or tools.
True atomically selects TurnKindGoalContinuation when the canonical Goal is active;
otherwise it remains pure compaction. Requested intent and effective kind are
canonical admission facts. A continuation completes mandatory compaction or noop,
then uses the existing Engine loop and Goal review in the same execution without
inventing user input. Preparation failure prevents business work. Automatic
compaction continues its admitted task as before.
Summary generation reads the complete eligible provider-history projection, including message formatting, tool arguments, references, and admitted runtime facts. It never replaces ordinary messages with fixed-length previews. One ordered batching loop carries only the latest candidate summary; oversized messages use lossless UTF-8 fragments with their message/tool metadata. Rendered request estimates and bounded overflow recovery determine batch size. All batches must succeed before installation, and incomplete or over-budget summaries fail without truncating or changing the effective context. Intermediate summaries are in memory only. The default summary ceiling remains 20,000 tokens; the 50,000-token compacted-context target is not a minimum summary length.
Manual compaction need not reach the automatic pressure threshold. Context below the configured target (50,000 tokens by default), a missing safe cut point, or insufficient savings produces an explicit noop. Failed, cancelled, and noop operations preserve the effective context and its provider continuation. Installation atomically commits the summary, context lifecycle, new estimate, and, for pure compaction only, its terminal; that committed terminal wins later cancellation. Goal continuation installation does not finish the execution. Stop still prevents subsequent work while retaining an installed summary. Success clears old continuation and confirmed usage. The next ordinary request supplies a new native measurement.
Replaying a request key returns the latest canonical view without executing or
installing again; reusing the key for another operation kind conflicts. Retry a
failed or cancelled pure compaction with a new compact request key. Ordinary
Retry returns ErrNoRetryTarget for that context-only kind. Goal continuation uses
ordinary Retry, question/approval recovery and restart. Canonical success/noop
preparation and confirmed tool results are retained; uncertain effects never
replay automatically. Deletion before the first business request ends preparation
without starting work; deletion after business admission suppresses subsequent
Goal review without acting as Stop. Goal edits apply at the next logical request,
and only a current review plus the atomic terminal can mark completion.
Schema 28 -> 29 introduces this explicit intent without reclassifying historical
pure compactions; old writers reject the new envelope. Context snapshots expose one
result per operation and its canonical AfterItemID presentation anchor; an
empty history has no artificial anchor. Stop, shutdown, restart, and fork use
the existing thread lifecycle. Domain schema v17 retains the automatic v12 -> v13
typed-turn edge and v13 -> v14 canonical run-identity edge without
reclassifying historical slash-command conversations or using observation
metadata as runtime authority. The v14 -> v15 edge adds typed thread references
without rewriting historical messages or request fingerprints.
Compaction sends canonical user images and confirmed tool-result images to the selected summary model as native image attachments, beside source labels. One ordered batch cursor covers full text, UTF-8 fragments and indivisible images. The complete prepared request, including resolved image cost, must fit; an image that cannot fit fails explicitly. Transport retries replay frozen input and output refits never reopen attachments. No partial summary is installed.
runtime.MessageAttachment.Locator() returns a stable media:v1:<sha256> identifier
of the complete descriptor, including optional text statistics. It is independent
of thread and entry identity and grants no access. Model labels expose the
locator, name, MIME and size, never the opaque ResourceRef. Hosts authorize
current canonical membership before resolving original bytes. ThreadItem.Attachments
contains both user attachments and confirmed tool-result attachments; scoped
thread search includes their names/MIME and chunked reads return safe labels.
Checkpoints preserve recent user attachment labels and explain that summaries are lossy: exact text, numbers and positions require rereading the original by locator. Recent tail images retain normal native input. Older images remain discoverable through canonical history, without an unbounded checkpoint catalog. The context projection revision advances to v10 with an explicit lineage reset. Schema 19, original attachment descriptors, stored bytes and old checkpoints are unchanged; old summaries gain no invented visual facts.
The public accounting contract describes one frozen request. Use
observation.ReconcileContextStatus for canonical and live observations. Keep
the last confirmed native input total, visible character distribution and recent
cache usage together until model, policy or successful compaction invalidates
that sample. Current request estimates remain Engine pressure inputs.
TokenEstimate.Characters and RequestEstimate.Characters use
prepared_characters_v1 and unicode_code_points. The existing collector counts
decoded text without trimming or Unicode normalization, and deterministic JSON
for tool definitions, arguments and response schemas. Categories and optional
details add exactly to TotalCharacters; transport envelopes, protocol framing,
controls, ciphertext and binary/media proxies contribute no characters. Visible
media labels count normally. Hidden content records coverage limitations only.
Characters have no arithmetic relationship with provider tokens.
Reconciliation validates character units, counts and frozen request identity,
returns detached character data, and preserves trustworthy native totals when
optional attribution is invalid. Missing historical characters stay unavailable;
there is no reconstruction or token conversion. Render measured tokens with =,
visible content with chars and shares of visible characters. A measured zero is
available; output-only usage does not establish an input measurement.
Legacy token breakdown and remainder fields remain compatible budget diagnostics,
but are deprecated for content distribution. They are not a character fallback.
TokenEstimate.Coverage=complete_request still means complete preparation, not
complete attribution. Unknown models retain explicitly approximate vocabulary
estimates. Opaque proxies, margins and output reserves serve budgets only.
Adapters declare Usage.InputTokensReported and InputTokenScope from the
protocol (request_input, provider_execution, or unknown). Only qualified
request input with complete visible coverage can calibrate pressure. Historical
anchors without qualification, hosted/opaque execution usage and unknown scopes
cannot establish exact window occupancy. Existing estimates, bounded compaction
and explicit provider overflow recovery continue to govern execution. No online
count is added before sending.
ContextStatus.PayloadFingerprint identifies final sent bytes after output
refitting. Frozen retries preserve input and character statistics.
Usage.OutputIncludesReasoning and TotalTokensReported preserve protocol
relationships and native totals, including explicit zero, without double-counting
reasoning or cached input. Published token field meanings are unchanged.
runtime.ModelContextSnapshot contains complete ModelContextSection values
with stable Key, display Title, and full Text. Supply an optional snapshot
in TurnInput.ModelContextSnapshot for atomic user-input admission, and in
ToolSurface.ModelContextSnapshot at provider_request or compact boundaries
through WithAgentDynamicToolSurface. Use one host collector with the same
resolved permissions as the tool surface. Network retries replay frozen input.
Nil supplies no update; a non-nil empty collection clears all managed sections.
Missing keys remove prior facts. Floret copies, sorts unique keys, and rejects
more than 128 sections, 64,000 characters per section or 256 KiB of encoded data.
Facts cannot contain secrets or grant resource access. Existing UserInput.Context
keeps its message-attached semantics; managed snapshots are a separate contract.
One canonical owner appends changed full snapshots and projects a full baseline, then changed sections and explicit removals as marked user-role context messages. They never become user bubbles, title inputs or retry anchors. System text keeps stable behavior rules. Each logical request applies steering, resolves the live surface, admits changes, budgets/compacts and freezes rendering. Storage failure prevents dispatch; physical retries replay frozen requests. Ordinary updates take effect at the next request without interrupting generation.
Compaction stores the exact snapshot at its cut and replays retained updates in order. That baseline consumes fixed input capacity and cannot be summarized or dropped. Retry, fork and restart use the same projection. Domain migration 16 -> 17 preserves historical bytes and never infers sections from old prose; the next live request admits a typed baseline. Old writers reject the upgraded envelope in the existing physical namespace.
ThreadContextSnapshot.ModelContext exposes admitted facts, canonical position,
changed/removed keys and the latest request using that exact record. Hosts read
it through the existing authorized boundary and normal thread subscriptions.
Wrap required failures with runtime.ErrModelContextUnavailable; the terminal
model_context_unavailable failure releases execution and permits safe explicit
retry after repair. Confirmed effects remain committed and unknown effects remain
non-retryable.
ThreadService.View returns one complete replaceable current view.
The thread runtime installs ThreadView.Context with canonical items before
publishing ViewVersion. Views and legacy subscriptions include a complete snapshot,
even when no context facts exist. Committed context changes publish while a Turn
is active; text deltas reuse the installed snapshot. Failed assembly returns an
error and the next explicit read retries, without blocking execution settlement
or cancellation. ThreadContextReader.Context uses that same projection.
ThreadContextCompaction.CanonicalOrdinal is the first lifecycle entry's one-based
position on the queried Path, independent of timestamps and terminal updates.
AfterItemID remains the insertion boundary; explicit Turn/Run identity defines
ownership. Forks reproject canonical order on the destination Path.
Compaction lifecycle records optionally expose a typed observation.CompactionDecision. It records the actual frozen trigger candidate (even when never sent), the decision pressure, and the validated replacement. Budget estimates, calibrated pressure and message-context before/after values remain distinct measurements. Missing snapshots are unavailable; manual preflight does not fabricate a request. The snapshot carries only budget diagnostics and fingerprints, never raw prompts or source distributions. The same canonical lifecycle supplies View, Context, reconnect and restart. Domain schema 25 -> 26 preserves historical payloads and rejects older writers.
The value returned by Host.ThreadService also implements
ThreadContextReader; Context returns Floret's canonical context policy,
usage, and one latest lifecycle record per compaction operation, including
terminal state restored after runtime restart. The snapshot also exposes
conversation-wide disjoint input, output, cache-read, and cache-write totals
folded from canonical final provider usage records.
Forked snapshots retain historical Turn and Run identity while reporting the
destination Thread identity. Floret owns this projection and automatically
migrates affected v8 stores; hosts do not patch context records.
Each successfully committed final provider_usage runtime event also carries
ThreadUsageTotals. It is the live form of the same canonical fold; projected
requests, stream-only usage, rejected attempts, and failed writes omit it.
ThreadContextSnapshot.ContextUsage and runtime.Event.ContextUsage expose the
same committed ThreadContextUsage: Confirmed holds the latest native usage,
while Estimate holds the current prediction. Hosts can keep measurements stable
while separately showing request pressure. Matching model and budget policies
retain the measurement across Turns and restart; changed policies and successful
compaction clear it. Failed, cancelled, and noop compactions do not clear it.
Missing native usage updates only the estimate. Existing Usage and
ContextStatus fields retain their latest-status semantics.
The optional ThreadWaiter.WaitThreads observes a frozen scoped target set with
one positive timeout. Results distinguish missing, attention_required,
completed and timed_out, in that priority order. Timeout is a normal snapshot;
caller cancellation, read failure and Host shutdown remain errors. Opt-in pending
parent-event observation also returns canonical receipts with an events reason
without resuming idle parents. Terminal receipts wait for the matching active
execution to install its complete terminal view before an event result returns.
This uses the existing subscription and deadline without consuming receipts.
Subscriptions wake a fresh authoritative read, including after deletion; they are not replay.
A tool may return tools.BoundedWait only for a full normal timeout with
unfinished, nonempty targets. The dispatcher measures that handler, excluding
approval and batch delay. Engine's single batch guard permits repetition only
when every call demonstrates a full bounded wait or changed polling progress.
Ordinary effects, early returns and errors retain the existing repeat limit.
ThreadTurnFailure.Reason derives safe loop-blocking classifications from the
canonical code and exact fixed Engine reason, including historical reads and
restart. Unknown failures have no guessed reason. No durable schema changes are
required; codes, retry savepoints and unknown-effect restrictions stay intact.
ThreadService.Subscribe publishes workspace summary and current-view updates;
reconnecting clients refresh summaries and the currently visible view. There is
no durable cursor, replay ledger, materialized projection, or second lifecycle
authority.
The optional runtime.ThreadBodyReader reads exact canonical fields without materializing the complete entry. Supply a freshly authorized threadquery.Scope on every call, including resumed reads. ThreadBodyInput identifies the thread, entry and field, with a UTF-8 byte offset and at most 16 KiB per chunk. Each response stays below 64 KiB encoded, reports total source bytes and the complete field's SHA-256, and preserves CRLF and Unicode exactly. A supplied SHA256 pins the source across reads and restarts. Locators never grant access; inactive-path entries and revoked scopes are unavailable. Tool arguments and reasoning are private facts and require the same host policy as ThreadQueryReader. Display previews must never become provider context or silently replace full content.
The optional runtime.ThreadBodyManifestReader resolves a committed assistant or reasoning ThreadItem.ID into immutable body parts without materializing text or a ThreadView. Supply fresh scope and private-fact authorization on every page. Retain the returned LeafID on continuation; ordinary append preserves that cut, while an incompatible active-path change rejects it. Content parts concatenate in order; identical repeated reasoning contributes one part. Pages contain at most 150 parts and 64 KiB encoded data. Empty pages may still have HasMore when inactive branches consume the bounded scan budget. Resume with NextEntryID. Control output uses ThreadBodyControlOutput and preserves raw whitespace, including an empty field; presentation alone supplies its historical empty label. For omitted control output, ThreadItemBody.Bytes describes raw source bytes; the preview preserves the complete view's trimmed text and empty-label behavior. Read every part through ThreadBodyReader with its SHA256. The leaf and source locators grant no access and introduce no independent lifecycle version.
The optional runtime.ThreadBodySearcher searches exact case-sensitive UTF-8 source without loading the full field. Each call scans at most 64 KiB and returns at most 100 overlapping match offsets. Queries are limited to 4 KiB. Resume with NextOffsetBytes and SHA256 while HasMore is true, including pages with no matches. Every page requires fresh scope and private-fact authorization. Cancellation abandons only the read, never the Agent run; source hashes prevent mixed results.
The service also implements optional runtime.ThreadCommandService. Its *Ack
methods accept the existing command inputs and use the same admission, validation
and idempotency owner as full-result commands. ThreadCommandAck returns the
canonical trimmed RequestKey, thread identity and available Turn, Run and view
version without materializing a complete result. An omitted view version means
no presentation baseline was observed. Once acknowledged, a failed presentation
read does not undo the command and must not cause it to be submitted again under
a new request key. Full-result APIs retain their existing complete-view semantics.
Goal mutations also work before the first presentation read, including after
Ack creation and restart; they preserve the canonical thread identity and lifecycle.
For streaming hosts, the same service implements optional
runtime.ThreadUpdateSource without adding methods to ThreadService.
Subscribe before reading View, discard updates through the snapshot version,
then apply only continuous BaseVersion -> ViewVersion batches. Item mutations
are explicit add, replace, remove, or UTF-8-byte-offset text append operations;
component wrappers distinguish unchanged from cleared values. Ordinary growth
is coalesced for at most 25ms, with immediate semantic boundaries and bounded
buffering (64 batches and 1MiB of encoded updates per observer). Overflow releases
pending payloads immediately; it never truncates canonical output. Snapshots flush pending growth to establish an exact baseline.
Overflow, canonical invalidation, or a version gap requires a fresh subscription
and authoritative view, never replay or inferred missing events. The old
subscription materializes complete isolated views only for existing legacy
consumers. See native thread updates.
Optional runtime.ThreadFactsSource.SubscribeFacts observes only runtime facts
for in-process host cleanup. It uses the same actor versions, bounded queue and
invalidation rules, never reads bodies or clones presentation components, and
cannot acquire window interest. Hosts authorize facts before public exposure.
Optional runtime.ThreadWindowSource uses the same actor publication
channel and versions for authorized item windows. Subscribe with an explicit
scope, then call SetWindow with freshly authorized scope. The channel delivers
a replacement Window baseline before subsequent deltas; a baseline can use
the current version, and must be accepted even when that version is already
known. Replacing an interest consistently withdraws its undelivered item, turn
and order detail, including resident mutations, while preserving semantic
components and accepted explicit baselines in order. Obsolete source reads are
canceled without canceling execution or adding historical reads.
Pages select at most 150 items and 512 KiB encoded item data. Text previews
are exact UTF-8 prefixes of at most 64 KiB; partial text is raw preview, never a
standalone Markdown document. Committed text locators resolve through the body
reader or manifest. Live text is borrowed from the Engine attempt's output owner.
Optional runtime.ThreadItemBodyReader.ItemBody resolves an active-path item's
current text locator without reading a preview or opening a subscription. Its
scope is freshly authorized and its PreviewBytes is zero. Use this boundary to
open full text independently of the page's preview allowance: a small item can
be partial in a crowded page and complete when read alone. This operation never
changes window interest, truncates source content or grants subsequent access.
Optional runtime.ThreadItemTextReader.ReadItemText continues exact presentation
text by item/source identity and UTF-8 offset for both canonical and live sources.
Each freshly authorized call returns at most 16 KiB decoded and 64 KiB encoded,
without assembling complete text. It preserves normalized control presentation.
Recent frozen manifest pages are retained in a bounded in-memory cache; no new
durable index is created. Source replacement requires refreshing the locator.
ThreadWindowInput.PreviewBytes optionally bounds each item before hydration
(128–65,536 bytes; zero preserves the existing default). Hosts can choose a
viewport-sized initial window and fetch visible remaining text through ranges.
The actor retains only an exact byte extent and bounded summary, rather than a
second accumulated string. Optional runtime.ThreadLiveBodyReader reads that
display source by ThreadID, RunID, SourceID and frozen ThroughBytes.
Each read freshly authorizes the scope and private-fact policy, returns at most
16 KiB source and 64 KiB encoded, and preserves UTF-8 and CRLF. A live locator
expires on retry, canonical installation, deletion or restart; refresh the item
and use its canonical locator after installation. Canceling a read never stops
execution. Existing path-reference redaction is preserved by a budgeted display
tail, sharing the unchanged raw prefix. Diagnostic observers never retain the
internal output-body reference.
Optional runtime.ThreadLiveBodySearcher searches the same frozen displayed
prefix with exact case-sensitive UTF-8 matching. Each page scans at most 64 KiB
source and returns at most 100 overlapping matches. Resume with the unchanged
source identity and ThroughBytes plus NextOffsetBytes; later appends do not
extend the search. Commit, retry, deletion or restart explicitly expires it.
Live and canonical search share one overlap and progress implementation.
Pending approvals and input requests remain accessible outside the selected
history. Window turn membership includes only selected items. Append preserves
history anchors; reordering replaces bounded geometry. An unavailable accepted
anchor is reported explicitly with a replacement at the available tail. Tail
interest evicts through an in-place bounded replacement after three pages rather
than reconnecting the workspace. ClearWindow releases queued item detail without
cancelling execution. Queue reads and clear operations share one lock and never
wait while owning it. Revocation requires the host to close the scoped stream.
Accepted ordinary user, steering, reasoning and assistant text is released from actor/reducer storage after installation. Exact canonical extents restore explicit complete reads; window reads hydrate only bounded prefixes. Complete legacy publications freeze text before enqueueing, independently of later deletion. Transformed control labels and structured metadata retain their existing ownership. Each active provider attempt shares a 4 MiB source-memory budget across raw output and any transformed display tail. Larger draft bytes spill to private disposable temporary files, released on every attempt exit. Failed appends preserve the accepted prefix; graceful stop commits it through the existing canonical owner. Completion still materializes full output once for the existing provider-context/transactional commit, so its peak is not bounded by the draft budget. Source-byte accounting is not a JS heap or process RSS claim.
Current-schema startup checks published thread metadata, journal count, leaf locator and query manifest before scheduling historical work. Prepared threads are not revalidated or rewritten on every restart. Missing or stale query metadata still requires complete canonical validation before rebuilding. Parent event recovery scans child metadata and validates its source closure before publishing a missing receipt. Migration and explicit inspection retain full validation; ordinary reads verify requested immutable sources. Readiness is not a full-store integrity audit. See startup residency diagnostics.
Built-in stores initialize window observers from exact item membership and its canonical dependency closure. Append maintains source positions, public ranks, context references and numeric aggregates in the canonical write transaction. Reads validate the selected sources at one leaf, including late tool results, pending controls, Retry sources and compaction anchors. These disposable indexes contain no transcript or independent lifecycle. Explicit full reads and execution promote the same actor only after complete reconstruction succeeds; failures keep the accepted window and its version.
Released stores missing these indexes still require validated historical preparation before their first window. Preparation uses short private batches and publishes readiness anchors after the frozen source is verified. It does not make the first upgrade read constant-time. Queue, context, Goal and restored-input components retain complete semantics and may exceed the observation queue budget. Oversized observation fails explicitly. Full execution residency, missing-index preparation and complete production-chain qualification remain requirements before claiming extreme-history or subsecond opening acceptance.
Context failures carry distinct ThreadTurnFailure codes: context_budget_invalid
when output headroom leaves no input capacity, context_fixed_overhead when
non-compressible input cannot fit, and context_compaction_limit when a rebuilt
request remains too large. Invalid budgets and known fixed overhead fail before
automatic compression. Hosts should offer budget/model changes before explicit
retry; the same failure survives restart. These messages contain numeric budget
diagnostics, never prompt bodies or credentials.
The optional runtime.ThreadActivityFieldReader reads a single string identified by its JSON pointer in an authorized canonical ActivityPresentation source. Offsets and extents use decoded UTF-8 bytes. Each call revalidates thread scope, active-path membership and optional source/field hashes, and returns at most 16 KiB. ActivityStructure resolves sources from the logical item; source identities never grant access. Resident string paths return an opaque SourceID and RunID for frozen field reads. Collection pages retain no sibling strings. The actor retains at most 256 selected fields, 8 MiB of resident strings and 256 MiB of temporary spill data per thread; reacquire the selected field after eviction or restart. Live append and canonical completion do not change bytes behind an accepted source identity.
ThreadActivityFieldInput.AlignStart optionally rounds a decoded offset inside a UTF-8 rune backward by at most three bytes. The returned OffsetBytes is the actual start and the same response limits apply. This permits reverse range reads after earlier UI chunks have been evicted; omitted/false keeps strict offset validation. Consumers must join ranges using returned offsets, not the requested offsets, and must never combine distinct source identities.
Floret records JSON offsets and independently verifiable decoded boundaries in the canonical write transaction. Prepared reads do not parse preceding text or sibling fields. Released sources missing that rebuildable metadata require one owner-controlled preparation; this is not a first-upgrade latency guarantee. The existing complete ThreadBodyActivityJSON contract remains unchanged.
For ordinary hosts, storage.Source is an opaque value consumed exclusively by
runtime.Open:
runtime.Open(ctx, runtime.Options{Storage: storage.Memory()})
runtime.Open(ctx, runtime.Options{Storage: storage.SQLite("agent.db")})Hosts may observe Floret's product-neutral startup phases without reading physical records:
host, err := runtime.Open(ctx, runtime.Options{
Storage: storage.SQLite("agent.db"),
StartupProgress: runtime.StartupProgressFunc(func(phase runtime.StartupPhase) {
// Present migrating or verifying without exposing stored content.
}),
})The callback runs synchronously on Floret's startup worker and must return
promptly. runtime.Open returns the Host before domain migration and final
verification finish. Use Host.StorageMigrationStatus to observe the worker,
Host.Readiness to check a thread, and Host.PrepareThread for a cancellable
wait. Segmented v6–v31 sources prepare each requested thread and its explicit
canonical dependencies, preserving every contiguous historical transform. Body
staging and query metadata preparation release the backend between bounded
batches; the complete validated thread publishes atomically. Foreground
preparation takes priority over background history. Already published threads
and new conversations remain usable if another historical thread fails.
Historical browsing preparation runs on demand through the existing Host-owned preparation gate. Ordinary startup does not build hidden activity detail trees. Large new activities (over 64 KiB encoded) publish bounded summary metadata in their canonical transaction; explicit field access prepares the complete source locators once, with restartable bounded batches. Existing full locators remain valid and are reused. No canonical bytes or physical schema are changed. ThreadReadiness.DisplayReady separately reports complete browsing preparation; Ready keeps its canonical runtime meaning. Hosts may explicitly call Host.PrepareDisplayThread to prepare all retained branches for a selected thread. Cancellation stops that operation and shutdown joins it. Window reads prepare only their dependencies. Missing optional readiness is never evidence of a sub-second prepared open.
Monolithic v2–v5 snapshots first scan immutable source bytes in resumable, bounded batches and reserve historical identities, including deleted identities and origin request keys. The Host and migration status remain available; new thread admission waits cancellably for this initial identity scan. The same canonical owner then publishes historical threads independently. Source locators and the private identity directory contain no transcript copies and never serve runtime reads. Cleanup checks the complete source inventory before retiring records in bounded batches. Failed preparation retains its source for retry.
Applications cannot use a Source as a lifecycle query path. Teams implementing
a physical backend use the advanced storage/spi contracts and their
conformance suite. SPI records remain opaque Floret data; a backend must not
decode them into a second Agent model. Memory, SQLite, and third-party backends
all run the same Floret-owned domain kernel.
Prompt-cache history is stored as append-ordered records per prompt scope and category. Dispatch checkpoints commit only new segments, toolsets, requests, and pending responses for the affected scopes; repeated request attempts retain their original order. Turn settlement and shutdown flush only pending facts. Compaction changes the effective model context independently of storage history.
SQLite physical format 5 contains canonical records and metadata only. The 4 -> 5 edge deletes the disposable search tables; all canonical bytes remain unchanged. Source metadata stores fixed first/previous/last entry boundaries without transcript copies, token terms or posting lists. Message appends update these locators without reading historical bodies. Query continuations retain at most 32 threads with a conservative 128 KiB allowance each. Cold or oversized continuations reconstruct from canonical metadata outside the write transaction, then recheck the thread and query manifest before committing. Chronological reconstruction uses fixed metadata windows; it does not retain transcript bodies.
All physical edges 1 -> 2 -> 3 -> 4 -> 5 remain automatic. Startup also migrates prompt history and the permanent session-tree lineage. Logical storage version 11 recognizes resumable domain schema 32 preparation. Source recognition and logical publication commit together; each complete thread then publishes in its own transaction, and retained sources are removed only after full inventory verification. Released KV term documents are removed; current metadata uses its own namespace. Inspection reports required upgrades without writing the source.
New SQLite stores use incremental auto-vacuum so deleted pages can be reclaimed
without rebuilding the database. A host that owns an older SQLite file may call
storage.MaintainSQLite before runtime.Open. The maintenance boundary checks
the exact Floret physical schema and database integrity, refuses an open
runtime, and uses SQLite's native VACUUM or incremental_vacuum; it never
copies records or exposes their contents.
Hosts with multiple stores can call runtime.InspectSQLite before any writable
open and storage.BackupSQLite while all writers are stopped. Inspection checks
the supported migration path in memory without creating a runtime Host. A backup
includes committed WAL records and never overwrites its destination.
Inspection and migration retain complete canonical and metadata validation.
Normal current-store startup reuses durable readiness anchors; explicit
runtime.InspectSQLite remains the full diagnostic boundary.
There is no full-text index, background rebuild or optional physical search
implementation. All backends use the canonical owner's metadata/source-locator
records in the same transaction as canonical changes. Explicit text queries
match authorized canonical sources on demand; their cost scales with the
selected content. Metadata-only browsing hydrates only the requested page and
keeps frozen source locators in bounded in-memory pagination snapshots. The
published optional SPI index types remain deprecated for v7 source compatibility
but are no longer called by Floret.
Open with runtime.Options{Storage: source, DeferExecution: true} when product
stores or authorization must be prepared first. Reads and pending-input import
cannot start execution until host.Activate(ctx) succeeds. Default startup
remains automatic. ErrExecutionDeferred identifies commands attempted before
activation; ErrStoreTooNew identifies a newer logical storage contract.
For a restored snapshot, call host.PrepareRestore(ctx) on the staged, deferred
Host before activating or publishing the storage set. It stops unfinished turns,
resolves old interactions, and removes queued work from execution while exposing
its original input through ThreadView.RestoredInputs. ErrRestoredTurn prevents
retrying a stopped turn. Users must submit a new request under current authority.
Restore does not undo external side effects. The application owns consistent
multi-store snapshots, confirmation, retention, and recoverable file replacement.
Floret exclusively owns admitted messages and references, thread/turn/run lifecycle, titles, approvals, todos, tool invocation and outcome, pending-work settlement, artifacts, control signals, context and compaction, provider ledgers and state, prompt cache, SubAgent hierarchy, and Activity projections.
Hosts may persist product authorization and audit, routing, credentials,
editable persona sources, resource catalogs, read state, unadmitted commands,
upload staging, and transport diagnostics. Those records must not contain a
serialized Floret DTO or support reconstruction of Agent state. Canonical
message references and admitted runtime snapshots are durable model history.
Only material explicitly scoped to the current turn, such as secrets, belongs
in SupplementalContext; it never becomes history or continuation state.
Host.Shutdown(ctx) stops admission, cancels Host-managed provider and tool
execution, waits for it to finish, and then closes storage. If the context
expires, Shutdown returns ctx.Err() and Host remains closing; a later call
continues waiting. After completion, every retained handle returns
ErrHostClosed.
Use provider.NewDeepSeek(provider.DeepSeekOptions{...}) for deepseek-flash
(DeepSeek V4.1 Flash 1017, text and images) and deepseek-v4-pro (text only).
The official deepseek-v4-flash and deepseek-v4-flash-vision-exp aliases
remain accepted with Flash capabilities; Floret preserves the selected ID and
opaque state identity. All support off, low, high, and max reasoning
with high as the default. Catalog ceilings are 1,000,000 context tokens and
393,216 output tokens; callers still choose their request budget.
Set Model, BaseURL (normally https://api.deepseek.com), APIKey, and an
explicit StateCompatibilityKey. The gateway calls /responses and streams
text and reasoning. Pro supports hosted web_search; Flash ignores hosted
search and uses the independent Search API. provider.DeepSeekModelCapabilities
returns the reviewed exact-model capability; unknown models are unavailable.
The gateway retains the published hosted-input and opaque replay contracts.
tools/websearch provides NewDeepSeekClient, NewBraveClient and NewTool.
Clients bind one host-selected endpoint and key; tools cannot select credentials
or sources. DeepSeek search validates 1–128 Unicode query characters and 1–50
results, defaults to 10, sends need_content=false, preserves model summaries
separately from UI snippets, and treats an empty result list as success.
tools/webfetch.NewDeepSeek is an explicit paid Markdown fetch alternative to
webfetch.New (Direct); it never falls back or invents page response metadata.
Both remote APIs use the connection key, bounded responses, cancellation, no
API redirects, and typed tool-service errors independently of model failures.
Search and Fetch currently cost $0.75 per 1,000 successful nonempty requests;
hosts must make activation explicit and must not infer billed totals from tokens.
See the official Search/Fetch contract
and the web tools API guide.
Web Activity preserves Operation (search, open_page, find_in_page),
Query (ordered queries separated by newlines), URL, Pattern, and source
Title, URL, and Snippet. Each source requires a URL; title and snippet are
optional provider facts and are never synthesized. ResultsProvided distinguishes an explicitly
returned empty list from unavailable details. An empty operation remains
unknown. Hosts render these facts from canonical Activity, including after
restart; answer citations are not per-call search results. These additive v7.4
contracts serve Redeven's shared Flower UI and other public Activity consumers.
Image support is a property of the selected model. Set the optional
DeepSeekOptions.ResolveAttachment callback to resolve an authorized opaque
provider.Attachment into image bytes. The gateway validates the model's image
capability and MIME type, freezes the expanded payload during Prepare, and
includes it in request estimates. Pure text models reject image input. The host
owns resource authorization; Floret never reads files or fetches attachment URLs.
Opaque state retains image references and content digests, never image bytes.
Subsequent requests resolve the content again under current host authorization.
This additive v7 option preserves existing descriptor-only callers.
Non-successful DeepSeek HTTP responses return provider.ProviderHTTPError with
the status code and sanitized provider error details. Context-overflow responses
continue to return provider.ErrContextOverflow.
DeepSeek is stateless. Floret retains provider-native response items in opaque
state, validates them against the canonical conversation, and returns the full
input history on each call, including search receipts and reasoning. Hosts must
not inspect or rebuild this state. Exact saved canonical signatures preserve
assistant boundaries when a Retry follows retained reasoning with a tool call;
adjacent fragments cannot absorb already bound history. When Runtime groups
adjacent assistant records, exact saved signatures also identify boundaries
inside the grouped strings. Matching is bounded and cancellable; changed history
still fails explicitly. Supplemental-context Turns retain their
existing no-continuation-state privacy boundary. Prepared estimates include the complete wire
payload using the offline official DeepSeek V4 tokenizer, 10% text headroom,
and 1024 tokens per actual image. These are conservative predictions, not native
usage. Canonical history fingerprints validate native calibration across Turns;
message ID reassignment does not invalidate it. See the
estimator provenance and limits.
Missing terminal events fail; truncated responses continue through the
normal runtime limit policy. The existing NewOpenAICompatible constructor
continues to select Chat Completions explicitly.
Local tool input schemas render root properties in their existing required array
order, followed by remaining properties alphabetically. tools.InputPropertyOrder
is the single ordering rule; it does not mutate schemas or constrain model argument
order. StrictObject retains its existing alphabetically sorted required array.
Hosts that need a declaration order can supply that array directly.
Custom transports call provider.OrderToolSchemas after their final protocol encoding,
before estimation, fingerprinting and request freezing. It covers Chat Completions,
Responses (including namespace functions), Anthropic Messages and generic model-input
JSON. Hosted tools, nested schemas, historical messages and argument strings retain
their content. Invalid ordering declarations fail explicitly. Official adapters use
the same renderer for final requests and raw tool segments. Network retries preserve
frozen bytes; output-budget refits retain tool declarations.
The internal tool-schema rendering revision advances render lineage through the existing provider-surface boundary. It stops old exact-envelope continuation reuse without changing provider identity, canonical history, valid native history, cache namespaces or domain schema 31. Historical rendered facts remain immutable.
provider.EstimateRenderedRequest lets custom transports estimate the exact frozen
Chat Completions, Responses, or Anthropic Messages JSON they send. It counts model
input rather than HTTP controls or host metadata, including tool definitions and
structured-output schemas. Recognized OpenAI models use embedded official
cl100k/o200k vocabularies. Unknown models use an explicitly identified multilingual
BPE proxy; OpenAI-compatible transport alone does not select an OpenAI tokenizer.
Images use separate dimension/model budgets, while opaque files remain conservative.
RequestFormatJSON supports opaque host transports without claiming exact server
rendering. These offline predictions never replace native measurements. See
provenance, coverage, and limitations.
The reviewed Moonshot catalog includes Kimi K3.1 Pro and Highspeed, using wire
IDs kimi-k3.1-pro and kimi-k3.1-pro-highspeed. The existing
provider.NewOpenAICompatible gateway with Provider: "moonshot" sends Chat
Completions to the host-selected Moonshot API root. Hosts declare the public
reasoning capability: low, high, max, default max, without Off support.
The adapter uses max_completion_tokens, omits fixed sampling controls, and
replays canonical assistant reasoning and tool exchanges. Catalog context and
output ceilings are both 1,048,576 tokens; hosts choose a feasible request budget.
Catalog image metadata does not expand the descriptor-only public adapter's
attachment contract. Kimi Code subscription credentials and routing remain host
concerns; this catalog update does not add a subscription transport or native
Moonshot search. See the official K3.1 guide
and catalog maintenance.
Ollama hosts can use provider.ParseOllamaReasoningCapability with /api/show
metadata and provider.OllamaReasoningEffort for validated compatible requests.
Explicit config.ReasoningLevelOn is distinct from the omitted Default and from
effort levels; only declared toggle capabilities accept it.
The engine uses a generated, offline models.dev snapshot with official protocol corrections. Hosts own credentials, enabled models, and discovery. Updating the snapshot does not select a model for an existing conversation or add a public catalog API. See catalog maintenance.
Public API compatibility starts at the published v7.16.2 release. That release and compatible additions published afterward are protected within v7; source/API compatibility with earlier releases is no longer promised. Consumers upgrading from an older release must adopt the v7.16.2 API. Existing conversation data continues through the permanent automatic domain-schema migration lineage.
GOWORK=off go test ./...
GOWORK=off go vet ./...
GOWORK=off go test -race ./...
scripts/check_v7_api_compatibility.sh
scripts/check_candidate_release_adoption.shRepository workflow and compatibility rules are defined in AGENTS.md. Architecture and maintenance knowledge lives in okf/.
tools.Define decoders may validate operation-dependent requirements that a flat
provider schema cannot express. Keep decoders deterministic and side-effect-free:
their rejections join schema failures in the correction path before Activity,
resource resolution or authorization, including tools without Activity callbacks.
Execution-state checks remain in resource resolution or handlers; their errors
do not become input correction merely because they mention invalid arguments.
Invalid tool arguments, including malformed non-empty JSON, remain strict errors.
Adapters retain the exact argument text; only the Engine decides argument
rejection and correction. Missing call identity, missing arguments, duplicate
identities, and incomplete or corrupt provider envelopes remain protocol errors.
The Engine records each rejected
call and its validation result and allows at most two regeneration opportunities
per correction episode. Each invalid tool batch counts once; a fully committed
validation-clean batch ends the episode, including ordinary business-error results.
Valid siblings of rejected calls retain their results without resetting the episode.
Text, transport retries, compaction, steering and Stop Hook continuation do not
reset it. New Runs start at zero. This is not an additional whole-Run limit.
Rejected calls cannot execute tools, request authorization, or open an Ask User
interaction. Technical feedback stays in canonical history and diagnostics while
Activity omits it. Exhausted control correction retains control_error; failures
inside control or Activity projectors and storage fail immediately. Both ordinary
and control exhaustion expose ThreadTurnFailureToolArgumentCorrectionExhausted
through ThreadTurnFailure.Reason, including exact released historical failures
without rewriting records. Hosts can offer explicit Retry or model configuration;
confirmed results remain canonical and uncertain effects must never auto-replay.
Schema v10 adds durable context without rewriting existing journal entries or provider request records. The automatic v9 to v10 edge preserves older migration edges. Provider projection v8 establishes an explicit boundary for existing threads: already saved references become visible; missing historical ephemeral material is never reconstructed. Ordinary requests retain their canonical prefix; compaction, canonical retry, projection upgrades, and execution configuration changes use the existing observable request boundary.
Hosts may opt into runtime.ThreadSteeringController. Steer durably accepts an instruction and interrupts the current provider attempt or cancellable tool batch while preserving the same task and execution identity. SteerQueued atomically consumes an exact queued item. Cancelled steering carries a reason code (stopped, effect_outcome_unknown, task_ended, or fork); hosts may offer explicit resubmission after stopped, and must not automatically replay uncertain effects. Ordinary Send remains queued while a thread is active; steering requests are idempotent by request key and stale queue content returns ErrRequestConflict.
Prompt-cache plans retain source intervals from the current canonical projection, including cache reuse and frozen network retries. Wire snapshots never own or persist these transient attribution intervals.
The additive v7.47 API decision serves Redeven Flower. TokenEstimate.Breakdown
is produced by the same frozen-request extraction and vocabulary count as the safety
budget. Message.Attribution carries optional typed model-context/compaction source
spans; renderers map them to RenderedRequest.Attribution JSON Pointer paths.
These fields are observation metadata, excluded from model payloads. UTF-8 spans
partition decoded text; token ownership uses the first byte and never retokenizes
sources. Missing sources remain unattributed. Invalid optional maps suppress only
that distribution and emit the bounded attribution_mismatch diagnostic.
ContextBreakdown.Tokenizer identifies the actual vocabulary, independently of the
wire protocol and configured provider instance identity. Quality=token_estimate
allows approximate token amounts only with complete known text coverage;
relative_weight and the empty historical quality allow shares only, including
accessible labels and tooltips. FramingTokens is protocol markup, not native-usage
reconciliation. Display shares use the content-weight total, never scaled native
usage. Safety margins/media bounds remain in budgets. No new durable store or
lifecycle is introduced; the existing request identity, history and source-version
calibration invalidation continue to apply.
See qualification evidence and unified counter.
Optional ThreadSummaryReader reads canonical summaries without full history or thread actor creation. Built-in cold reads stream frozen metadata pages and read only the latest nonempty message preview plus required failure/input fields; large transcript and ordinary activity bodies are not hydrated. The remaining metadata scan and interaction/lifecycle state are still proportional to history for unprepared paths. Prepared bounded-window actors retain a canonical summary source and do not rescan historical metadata for the preview. Options.StartupWorkProgress reports real completed thread projections and known totals. StartupPhaseIndexing is deprecated and never emitted.
Set tools.Result.EffectOutcome to tools.EffectOutcomeUncertain only when a handler returns a trustworthy error result whose external effect is unconfirmed. It requires IsError, no DispatchErr, no Pending and no InputRequired. Floret commits the result and archived output atomically, then lets the model inspect current state and decide what to do. Do not blindly repeat an uncertain action. Repeated invocation identity replays the committed result, and retry preserves the post-result boundary. Crashes, panics, unsettled cancellation and result persistence failure retain the terminal ErrEffectOutcomeUnknown contract. When a result commits before its batch savepoint, retry retains the complete settled terminal path instead of an earlier savepoint. Incomplete tool exchanges fail closed.
Schema 20 -> 21 preserves historical facts and requires current writers.
Search and DeepSeek Fetch clients may use ResolveAPIKey to resolve live credentials immediately before dispatch. The callback must enforce current host authorization; its errors remain explicit and do not switch services. Credentials are never part of a tool definition or checkpoint.
The optional runtime ThreadActivityStructureReader resolves a canonical tool item into paged effective activity fields, preserving call/result merge and historical defaults. It returns source references for strings rather than hidden input/output contents. ThreadActivityFieldReader reads decoded UTF-8 ranges with fresh authorization, source identity checks, and a 64 KiB encoded response bound. Historical sources missing field metadata are prepared by the canonical storage owner before these bounded reads become available. ThreadActivityValueReader selects a byte/node-bounded subtree and can return up to eight frozen direct string locators from the same snapshot. Every field read reauthorizes the caller; locators are never access grants.
Selected string locators may include TextExtent, the byte interval between
the first and last non-whitespace Unicode characters. Offsets are relative to
the decoded field slice; the source, hash and full byte count remain unchanged.
An empty interval represents whitespace-only text. Absence means the source
predates this optional metadata, not that its text is empty. Display clients
must preserve significant indentation and choose formatting themselves.
Window consumers may opt into ThreadWindowInput.ActivityFields to receive typed activity summaries and exact immediate field shapes/counts without hidden presentation bodies. Field shapes distinguish absent details from unread content; acquire string sources at their exact path before reading. Read visible fields through ThreadActivityStructureReader and ThreadActivityFieldReader. The default window and complete View contracts retain their existing behavior.
For a single mutation, summary Values may include the exact canonical paths
/payload/mutations/0/display_name and /payload/mutations/0/change_type, at
most 2 KiB each. Canonical reads inspect at most 16 KiB of the existing array
prefix without preparing detail indexes; multi-file summaries use the array
count. Missing values mean unread or unavailable, never absent. Display names
do not authorize navigation. Canonical bytes and storage formats are unchanged.
Explicit windows may set ThreadWindowInput.IncludeSummary to receive
ThreadWindowSnapshot.Summary with the accepted baseline. Activity facts and
preview share the window's actor snapshot. Hosts use that summary for its read
watermark instead of a later independent Summary call. Automatic replacements
omit it. Thread identity and title metadata are sampled before the baseline.
An optional ThreadWindowInput.RequestID (valid UTF-8, at most 128 bytes) is
echoed only by the explicit replacement baseline in ThreadWindowSnapshot.
Use it to correlate a pending SetWindow while one consumer continues reading
the same ordered Next channel. Automatic replacements omit the token. It is
ephemeral correlation, never authorization, execution identity or a version.
Window consumers can set ThreadWindowInput.ItemIDs to one to 150 unique item identities instead of an interval. Omit AnchorID, Direction and Limit in that mode. The baseline sets ItemSelection and orders items canonically; gaps are intentional and are not a complete-history claim. The same observation interest publishes selected changes and all pending controls. Failed selections preserve the prior interest, and explicit selections do not implicitly follow the tail.
The optional runtime ThreadItemRangeReader reads source-bound counts and fixed
safety facts for a maximal canonical same-turn/run range. It returns a frozen
LeafID, never an actor version or live subscription. It does not materialize
hidden member bodies or define product grouping policy. Hosts must supply fresh
read authorization and account for resident drafts separately; unprepared
historical metadata still requires owner-controlled preparation.
Window subscriptions optionally combine a before/after seek with ThreadWindowInput.SkipRange and RetainItemIDs. The canonical owner resolves the range and bounded union at one leaf, retains both endpoints, and installs the result as a finite identity selection. IntermediateAssistant admits only canonically superseded response segments; SettledActivities keeps mutable tools outside a skip. SkippedRange is baseline-only metadata, not a live count. The combined request budget is 150 identities including two endpoint slots.
Prepared bounded windows retain the latest canonical summary source alongside membership. Sidebar Summary after a historical or tool-only window reads no historical metadata scan. Only source positions are durable; preview text is read from canonical bodies on demand. Missing historical metadata still needs canonical preparation and is not a subsecond first-upgrade guarantee.
ThreadWindowInput.AnchorOffset optionally seeks visible membership positions relative to AnchorID for an around read. It cannot be combined with ItemIDs. The accepted baseline binds stable item identities; subsequent live changes do not repeat the offset. This keeps large reading-gap seeks bounded without changing canonical execution context.
Domain schema 29 -> 30 stores immutable content, reasoning, tool arguments, summaries and error text as content-addressed 16 KiB byte blocks. Entry records carry field references and their original canonical raw hash. Complete reads reconstruct the exact canonical message and validate that hash; no host reads opaque records. Equal fields and Fork prefixes share blocks, with ownership counts updated in the same transaction as entry admission and deletion. Startup validates all body ownership, key sets, lengths and content hashes. Missing, orphaned or corrupt blocks fail without mutation; cancellation, panic and write failure roll back the entire migration. Current restart is byte-stable.
Historical journals retain immutable body locators, and detached complete reads use a shared 128 MiB verified source cache. Prepared presentation windows resolve source membership without rebuilding the complete actor. First-upgrade index preparation and execution/full-view residency remain history-sized. See the qualification limits in history performance.
The contiguous domain 30 -> 31 migration moves typed tool ActivityPresentation
JSON into the same verified body-block store. It preserves canonical raw bytes,
hashes, tool pairing and all existing migration edges; old writers reject the
new entry envelope. Completed ordinary tool payloads are released from the actor
and its shared reducer. Explicit full views and legacy subscriptions reconstruct
the exact ordered presentation through the same tools.MergeActivityPresentations
implementation. Bounded windows inline at most the source preview budget, then
return ActivityBodies locators and ThreadBodyActivityJSON chunks for complete
reading. An empty historical source includes its canonical DefaultPresentation
in that source position; merge it in order without reading full history. The
optional field does not change source bytes, hashes or existing complete views.
Partial JSON must never be rendered as a complete typed presentation.
Goal's derived presentation, active tools and provider context retain their
existing authority. Field-only summaries retain Goal operation, applied status,
version and outcome while deferring Goal text and review evidence. This does not complete the extreme-history qualification.
Custom storage transactions may implement storage/spi.BoundedRecordReader to provide RecordSize and ReadRecordRange for bounded historical snapshot reads. Built-in Memory and SQLite backends implement this optional capability. The migrator reads at most 64 KiB per range request, checks cancellation and exact lengths, and preserves Get compatibility for custom backends without it. A capability error is returned; it never triggers an unbounded fallback read.
Hosts can opt into temporary file references with provider.NewDeepSeekImageFiles
and DeepSeekOptions.ImageFiles. Keep one bounded in-memory owner per endpoint
and credential lifetime, choose explicit retention (one hour to thirty days),
and resolve authorized original attachments on every new preparation. File IDs
never enter canonical history. Frozen retries replay identical payloads; explicit
file_not_found / file_expired rejections permit one new Engine preparation.
Image references still contribute the normal visual token budget.
observation.CompactionDecision.Capacity distinguishes host request-byte limits
from server HTTP 413 rejection. It does not assert that the model token window is
full. Host evidence contains exact bytes; unavailable server counts stay absent.
Aggregate image count and decoded-byte failures expose the optional
RequestCapacityLimit() (kind string, actual, limit int64) error method. The Engine recovers through its existing safe
compaction boundary even when token pressure is low. Individual dimension,
invalid-format and source-size errors are not token overflow and require image
preparation or corrected input. Summary batches shrink without skipping images;
current user images remain exact. A replacement must pass provider preparation
and token validation before any checkpoint is installed. Recovery is bounded to
one preflight compaction and one response compaction per provider step; unchanged
transport retries always replay the frozen request.
Schema 33 to 34 appends an atomic manifest fence for typed image-capacity evidence. Existing original media, messages, tool exchanges and released migration edges remain unchanged. Quantity evidence uses image counts, never byte/token fields.
The schema 32 to 33 edge atomically changes only the manifest fence; existing conversation records retain their bytes and remain available through the same canonical owner. Media validation and upload failures do not trigger compaction.
runtime.ThreadItemPageReader supplies demand-only canonical presentation pages
without installing a live reading interest. AncestorLeafID verifies continued
membership of the source path while allowing ordinary append; each response
reports its actual leaf. Pages include selected items and turn facts, with at
most 150 items and 512 KiB of JSON. Activity details remain deferred. Hosts keep
live state with observation, authorize every page, and choose finite presentation
boundaries instead of chasing an advancing tail. This adds no storage schema.
The zero-value provider.ResponsesOutput collects completed items for one request. Add rejects conflicting duplicate events. Complete preserves completed reasoning ciphertext and fills absent ciphertext from a matching terminal item. Different nonempty ciphertext is not a semantic conflict. Other fields remain strict; omitted snapshots use completed events. Output is ordered and bounded to 8 MiB. ResponsesOutputError exposes safe codes, conflict indexes and known field names, never provider values.
provider.PrepareResponsesHistory owns native Responses replay for protocol
adapters. ResponsesHistory.Input returns complete native history for estimation
and stateless replay. Continuation returns a validated response ID and only
its subsequent input, used when endpoint support and Engine policy permit.
Commit binds confirmed terminal output, including exact snapshots from length
truncation, to its canonical visible projection;
adapters publish both atomically and retain immutable prepared retries. Model,
account, endpoint and supplemental-secret isolation remain Gateway/Engine fences.
This additive API serves Redeven's API-key and ChatGPT adapters. It reads the published ChatGPT native_output envelope without rewriting conversations. Changed canonical prefixes prune stale native suffixes and server IDs; visible output drift, malformed state, unsupported items and history above 8 MiB fail explicitly. Search evidence is never reconstructed from UI activity.
Runtime Responses adapters use CommitAssistant with complete emitted text and ordered canonical function calls, sharing the runtime's assistant grouping. Presentation fragments do not define history boundaries. Published split text bindings remain readable when exact concatenation (or native-proven spacing) validates; native output remains unchanged and real content/tool drift fails. ResponsesHistoryError exposes safe reason codes, record positions, counts and known field names without conversation content. Preparation never retries a request or executes tools.
The public provider.NewAnthropic gateway prepares and streams one frozen native Messages request. Effective reuse policy controls ephemeral prompt caching; native signed thinking is retained independently through the existing opaque provider state. AnthropicOptions accepts an authorized attachment resolver, request-byte limit, temperature and top-p. Retries reuse the exact request and never reopen attachments. See the provider contract for usage qualification, historical projection and lifecycle guarantees.
Responses native output reconciliation preserves completed hosted-search records when only valid terminal source lists differ. Operation conflicts remain errors. Hosts can use provider.ResponsesOutput.CompleteWithDiagnostics for bounded field paths, source counts and selection facts without logging provider values.
The optional runtime.ThreadHostWorkService keeps confirmed host-owned work
facts in the canonical thread journal. Bind a stable work ID to an authorized
local invocation before starting its effect; complete it with bounded result
JSON, a short notice and optional retained output and final Activity. This is a
host API, not an additional model tool. tools.Result.ObservedHostWork marks a
result already presented by an explicit observation tool, preventing duplicate
completion admission. See host-work lifecycle.
A terminal observation whose effect outcome cannot be confirmed uses
observation.ActivityStatusUnknown. It is a warning requiring attention,
counted by ActivityCounts.Unknown and ActivityAttentionUnknown; it is not
success, active work, failure evidence, or permission to replay. Consumers must
support unknown in item and summary statuses and attention reasons. Range
queries expose it through ThreadItemRangeUnknownActivity and unknown counts.
Resource extractors may return tools.PreparationError with a safe Code and Message (and an optional wrapped Cause). The result retains structured error facts and execution:{phase:"resource_extraction",started:false} before effect authorization. Text and Structured expose the same JSON facts to the model and retained result. Activity keeps the typed code; this is not retry authority.