floret

module
v0.3.9 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2026 License: MIT

README ΒΆ

Floret

A Go runtime for interactive, tool-using AI agents.
Floret owns the agent loop, durable thread runtime, context pressure, tool dispatch, and sanitized observation. Your product owns the UI, users, permissions, secrets, and domain tools.

Go Reference License Go Version

Runtime host Bring your UI Fake providers

Why Floret Β· At a glance Β· Quick Start Β· Projected Turns Β· Boundaries Β· Runtime Flow Β· Quality Gate Β· License

Floret is a reusable Go runtime for applications that need interactive agent conversations without rebuilding the same provider loop, durable thread state, tool execution, context management, compaction, and event projection in every host. It is not a graph workflow framework and not a multi-agent orchestration framework. The intended integration path is a small host facade: configure a host, register tools, start a thread, run turns, and render snapshots or observations.

✨ Why Floret

Most agent products end up with the same hard plumbing: provider request shaping, stream parsing, tool-call validation, approval hooks, durable conversation state, long-context pressure, retries, usage metrics, and UI-friendly runtime events. Floret packages those concerns behind a compact public API so product code can stay focused on product behavior.

  • Agent loop: continue after tool calls, enforce loop limits, track finish reasons, and return clear turn results.
  • Durable threads: start, read, retry, and delete hosted conversations through runtime.Host.
  • Tools: register strict schemas with tools.Registry, declare effects, ask for approval, and dispatch domain handlers.
  • Storage: choose runtime.NewMemoryStore for tests or runtime.OpenSQLiteStore for Floret-managed durable runtime storage.
  • Observation: stream sanitized runtime.EventSink records and use observation DTOs for context and compaction UI.
  • Deterministic tests: use the fake provider path to test host flows without real model calls.

🧭 At a glance

You need to... Use...
Configure a provider and agent persona config.Config or config.Load
Build a durable conversation host runtime.NewHost
Run one turn from a host-owned transcript projection runtime.RunProjectedTurn
Supply product-owned model transport runtime.ModelGateway
Keep Floret runtime data in memory runtime.NewMemoryStore
Keep Floret runtime data in SQLite runtime.OpenSQLiteStore
Expose product-specific actions tools.Registry and typed tool handlers
Render progress and diagnostics runtime.EventSink plus observation DTOs

πŸ“¦ Stable downstream API

Production downstream projects should import only these packages:

github.com/floegence/floret/config
github.com/floegence/floret/runtime
github.com/floegence/floret/tools
github.com/floegence/floret/observation

Everything under internal/ is Floret implementation. Downstream applications should not bypass the runtime facade to build turn requests, call Floret implementation contracts, manage Floret journal tables, or parse prompt-cache and provider-ledger records. If the product owns model transport, implement runtime.ModelGateway and let Floret construct the turn request, own the loop, dispatch tools, and record runtime facts. Product data such as owners, workspaces, pinned state, read watermarks, and billing metadata belongs in the host database keyed by runtime.ThreadID. Any package outside the stable list above is contributor or runtime implementation, not a downstream contract.

πŸš€ Quick Start

Install Floret:

go get github.com/floegence/floret/config github.com/floegence/floret/runtime github.com/floegence/floret/tools github.com/floegence/floret/observation

Create a host with the fake provider:

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/floegence/floret/config"
	"github.com/floegence/floret/runtime"
	"github.com/floegence/floret/tools"
)

type echoArgs struct {
	Text string `json:"text"`
}

func main() {
	ctx := context.Background()

	cfg := config.Config{
		Provider:     config.ProviderFake,
		Model:        "fake-model",
		FakeResponse: "hello from floret",
		AgentProfile: config.AgentProfile{
			ID:           "example-agent",
			Name:         "Example Agent",
			SystemPrompt: "You are a concise example assistant.",
		},
	}

	registry := tools.NewRegistry()
	err := registry.Register(tools.Define[echoArgs](
		tools.Definition{
			Name:        "echo",
			Title:       "Echo",
			Description: "Return the supplied text.",
			InputSchema: tools.StrictObject(map[string]any{
				"text": tools.String("Text to echo."),
			}, []string{"text"}),
			ReadOnly: true,
		},
		nil,
		nil,
		func(ctx context.Context, inv tools.Invocation[echoArgs]) (tools.Result, error) {
			return tools.Result{Text: inv.Args.Text}, nil
		},
	))
	if err != nil {
		log.Fatal(err)
	}

	store := runtime.NewMemoryStore()
	host, err := runtime.NewHost(runtime.HostOptions{
		Config: cfg,
		Store:  store,
		Tools:  registry,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer host.Close()

	thread, err := host.StartThread(ctx, runtime.StartThreadRequest{ThreadID: "thread-1"})
	if err != nil {
		log.Fatal(err)
	}

	result, err := host.RunTurn(ctx, runtime.RunTurnRequest{
		ThreadID: thread.ID,
		TurnID:   "turn-1",
		Input:    "Say hello in one short sentence.",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(result.Output)
}

Use runtime.OpenSQLiteStore(path) when the host wants Floret-managed durable runtime storage. Treat runtime.Store as an opaque handle; do not reach into its tables or implementation details from downstream code.

πŸ”€ Projected Turns

Use runtime.RunProjectedTurn only when the product already owns conversation rows and needs Floret to execute one turn from a host-built transcript projection. Durable Floret-managed conversations should use runtime.Host.

Projected turn requests must carry explicit RunID, ThreadID, TurnID, TraceID, and PromptScopeID. History accepts only user, assistant, and tool messages; system instructions belong in config.Config. The returned Transcript is the provider-visible projection for the next turn, not a sanitized UI display row. When ProjectedTurnOptions.ModelGateway is set, Floret passes a runtime.ModelRequest to the host-owned model transport and continues to own tool dispatch, loop control, ledgers, and events.

βš™οΈ Configuration

config.Load reads .env.local and environment variables. A host may also build config.Config directly in code.

FLORET_PROVIDER=fake
FLORET_MODEL=fake-model
FLORET_FAKE_RESPONSE=ok
FLORET_CONTEXT_WINDOW_TOKENS=256000
FLORET_RESERVED_OUTPUT_TOKENS=64000
FLORET_RECENT_TAIL_TOKENS=12000

For a custom OpenAI-compatible gateway:

FLORET_PROVIDER=openai-compatible
FLORET_MODEL=your-model
FLORET_BASE_URL=https://api.example.com/v1
FLORET_API_KEY=your-api-key

Provider secrets should be resolved by the host configuration path and passed to Floret configuration. Events, snapshots, and observation DTOs must not be used as secret stores.

πŸ› οΈ Tools

Hosts register domain tools with tools.Registry. Floret validates JSON arguments, extracts generic resource and effect information, asks the configured approver when required, dispatches the handler, shapes output, and records runtime facts. Tool handlers still enforce product-specific permissions such as user, tenant, workspace, environment, and target ownership.

Tool concern Floret handles Host handles
Schema strict provider-visible JSON shape domain argument meaning
Permission generic approval hook and effect metadata product authorization policy
Execution scheduling, panic recovery, result projection the actual domain action
Output model/UI projection and artifact references product-specific display choices

Important tool rules:

  • Read-only tools may run in parallel only when ParallelSafe is explicitly valid.
  • Mutating, shell, network, destructive, or open-world tools must declare permission behavior.
  • Provider-native hosted capabilities are not local tools and are not dispatched by tools.Registry.
  • Large outputs should be represented by artifact references when the model or UI does not need full inline content.

🧱 Responsibility boundary

Area Floret owns Host application owns
Agent execution provider loop, tool continuation, loop limits, finish reasons choosing when a user can start, retry, or cancel work
Provider access adapters, request shape, stream parsing, usage, continuation state user-level provider profile, secret source, allowed model policy
Storage thread journal, prompt material, provider ledger, artifacts, runtime metadata product metadata keyed by runtime.ThreadID
Tools schema validation, generic effects, approval hook, dispatch, result projection domain handlers and final product permission checks
UI sanitized events, snapshots, observation DTOs layout, workflows, interaction states, recovery actions

πŸ‘οΈ Observation

Use runtime.EventSink to receive sanitized runtime events from a host. Use observation DTOs for context pressure and compaction state when building UI surfaces. Observation records are not raw provider payloads and should not contain prompt text, tool arguments, tool results, local paths, or secrets.

πŸ” Runtime Flow

Host UI/API
  |
  | StartThread / RunTurn / RetryTurn / DeleteThread
  v
runtime.Host
  |
  | owns loop control, journal projection, tool dispatch, context pressure
  v
Floret runtime implementation
  |
  +--> tools.Registry for local domain tools
  +--> runtime.Store for Floret-owned runtime data
  +--> runtime.EventSink and observation DTOs for host rendering

A normal hosted conversation uses runtime.ThreadID as the durable journal identity. runtime.TurnID identifies one user-visible turn. runtime.RunID identifies one provider execution. runtime.PromptScopeID is the prompt-cache and provider-ledger reuse boundary. Code must not rely on those identities being equal.

πŸ§ͺ Contributor Test Console

Floret includes a local test console for contributor inspection:

go run ./cmd/floret-test-ui

The console can run fake-provider sessions, inspect sanitized events, run provider smoke checks, and exercise tool scenarios. It is not the downstream integration contract.

βœ… Quality Gate

go test ./...

The test suite covers host facade behavior, Floret-owned provider stream contracts, tool validation and permissions, context pressure, compaction, prompt-scope ownership, storage cleanup, and architecture boundaries that keep Floret internals out of downstream APIs.

πŸ“„ License

Floret is licensed under the MIT License.

Directories ΒΆ

Path Synopsis
cmd
floret-test-ui command
internal
agentharness
Package agentharness exposes the host/UI durable conversation API.
Package agentharness exposes the host/UI durable conversation API.
engine
Package engine implements the low-level prompt-first turn executor.
Package engine implements the low-level prompt-first turn executor.
engine/compaction
Package compaction adapts provider-backed summary generation for engine context compaction.
Package compaction adapts provider-backed summary generation for engine context compaction.
event
Package event defines presentation-neutral runtime events.
Package event defines presentation-neutral runtime events.
provider
Package provider defines the normalized model streaming contract.
Package provider defines the normalized model streaming contract.
provider/cache
Package cache records provider-visible prompt segments and request ledgers.
Package cache records provider-visible prompt segments and request ledgers.
session
Package session defines the provider-visible transcript shape and low-level ephemeral transcript store.
Package session defines the provider-visible transcript shape and low-level ephemeral transcript store.
sessiontree
Package sessiontree stores durable conversation journals.
Package sessiontree stores durable conversation journals.
Package observation defines host-facing runtime observation DTOs.
Package observation defines host-facing runtime observation DTOs.
Package tools defines local tool registration, permission checks, and execution.
Package tools defines local tool registration, permission checks, and execution.

Jump to

Keyboard shortcuts

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