memory

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 13, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package memory is the conductor's client of Hindsight, the agents' shared memory. Podium stores no memory of its own: this file is a few hundred lines of net/http against Hindsight's REST API and that is the whole of Podium's memory code.

Everything read back out of here is CONTENT. A memory was written by a task, from material a human or a repository or a ticket supplied, and nothing in Podium interprets it — the API hands it to the UI and the UI shows it to a person, whose job is to notice a memory that should not be there and forget it.

Index

Constants

View Source
const (
	FactWorld       = "world"
	FactExperience  = "experience"
	FactObservation = "observation"
)

Fact types Hindsight classifies a memory as. Only world and experience are curatable; an observation is derived by consolidation and disappears with the facts under it.

View Source
const DefaultLimit = 50

DefaultLimit is how many memories a page holds when the caller does not say.

View Source
const DefaultTimeout = 15 * time.Second

DefaultTimeout bounds one call. Recall runs an embedding and a rerank; retain hands work to Hindsight's own worker and returns immediately.

View Source
const MaxLimit = 200

MaxLimit caps a page. Hindsight's own default is 100.

View Source
const OperationFailed = "failed"

OperationFailed is the terminal status that means no fact was written and none will be.

View Source
const RedactionMarker = "[redacted"

RedactionMarker is the prefix both redaction paths share: the node's log redaction writes `[redacted:NAME]` (internal/node/redact.go) and the runtime's clone output writes a bare `[redacted]`. Matching the common prefix catches both.

Variables

View Source
var ErrNotFound = errors.New("no such memory")

ErrNotFound is a 404 for a named memory. Hindsight answers a list of an unknown bank with an empty page rather than a 404, so this only ever means "no such memory".

View Source
var ErrRedacted = errors.New("content carries a redaction marker")

ErrRedacted is what Retain answers when the content carries a redaction marker. A marker means a secret was in that text and the node caught it on the way out; whatever the sentence around it says, it is not a durable fact about the organisation, and a memory every future turn reads is the last place it should end up.

View Source
var ErrUnauthorized = errors.New("hindsight refused the memory API key")

ErrUnauthorized is a 401 or 403 from Hindsight: the API key is wrong, or there is no key and the tenant extension is on. It is separated because it is the one failure an operator fixes by editing .env rather than by reading a log.

Functions

func MCPURL

func MCPURL(taskBaseURL, bank string) string

MCPURL is the endpoint a task container connects its MCP client to, built from a base URL that is NOT this client's: the conductor and a task see Hindsight from different places. The trailing slash and the bank in the path are what put Hindsight in single-bank mode, where the tools are bank-scoped and take no bank argument.

Types

type Client

type Client interface {
	// Retain hands one item to Hindsight for extraction. It returns once Hindsight has
	// accepted the work, not once the facts exist.
	Retain(ctx context.Context, item Item) error
	// Recall is the semantic search behind SearchMemories.
	Recall(ctx context.Context, query string, limit int) ([]Memory, error)
	// List is the newest-first page behind ListMemories. The cursor is opaque; an empty
	// one starts at the beginning and an empty return means there is no further page.
	List(ctx context.Context, cursor string, limit int) (items []Memory, next string, err error)
	// Forget excludes one memory from every future recall. Hindsight has no
	// single-memory delete: this is its curation tombstone, which keeps the row for audit
	// and is reversible from Hindsight's own API.
	Forget(ctx context.Context, id string) error
	// FailedOperations is the work Hindsight accepted and then could not finish. Retain
	// reports only that the work was taken, so without this a total extraction outage —
	// a rejected model key, a model that no longer exists — is invisible to Podium.
	FailedOperations(ctx context.Context, limit int) ([]Operation, error)
	// Ready reports whether Hindsight and its database are reachable.
	Ready(ctx context.Context) error
}

Client is the part of Hindsight the conductor uses. It is an interface so the turn loop can be tested with a recorder and so an outage is easy to simulate.

type HTTP

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

HTTP is the Hindsight client.

func New

func New(opts Options) (*HTTP, error)

New validates the options and returns a client. It makes no request: a conductor must start with Hindsight down.

func (*HTTP) FailedOperations

func (c *HTTP) FailedOperations(ctx context.Context, limit int) ([]Operation, error)

FailedOperations is the newest page of work Hindsight gave up on.

exclude_parents is what keeps the count honest: a retain is recorded twice, once as the batch that wraps it and once as the chunk inside, and both go to failed together. The parent carries no error the child does not.

func (*HTTP) Forget

func (c *HTTP) Forget(ctx context.Context, id string) error

Forget invalidates one memory. Hindsight excludes an invalidated memory from recall, from consolidation and from the graph, prunes the observations derived from it, and keeps the row in an archive — which is why the UI's word is "forget" and not "delete".

func (*HTTP) List

func (c *HTTP) List(ctx context.Context, cursor string, limit int) ([]Memory, string, error)

List is one newest-first page. The cursor is Hindsight's offset, rendered as a string so nothing outside this package depends on it being one.

func (*HTTP) Ready

func (c *HTTP) Ready(ctx context.Context) error

Ready is the /readyz probe. It is Hindsight's own /health, which reports its database too and answers 503 when that is unreachable. GET / is a 404 on this service; do not probe it.

func (*HTTP) Recall

func (c *HTTP) Recall(ctx context.Context, query string, limit int) ([]Memory, error)

Recall is Hindsight's semantic search. The limit is applied here: recall is budgeted in tokens rather than rows, so it can return more than was asked for.

func (*HTTP) Retain

func (c *HTTP) Retain(ctx context.Context, item Item) error

Retain hands one item over. It is asynchronous on Hindsight's side on purpose: extraction is an LLM call of unbounded duration, and a turn is already finished by the time this runs. A synchronous retain would make a slow extraction look like a memory outage.

type Item

type Item struct {
	// Content is the text facts are extracted from. Required.
	Content string
	// Context is a sentence about where the content came from.
	Context string
	// Tags are recorded for a later scoping step and never filtered on here.
	Tags []string
	// Metadata is provenance. It survives verbatim onto every fact extracted from Content
	// and is what the UI's provenance chips read.
	Metadata map[string]string
	// DocumentID groups the facts and is the idempotency key: retaining the same
	// DocumentID again replaces what was there rather than adding a duplicate.
	DocumentID string
}

Item is one thing to remember. Hindsight extracts facts from Content with an LLM, so Content is prose rather than a structured record.

type Memory

type Memory struct {
	ID   string
	Text string
	// FactType is world, experience or observation.
	FactType string
	Tags     []string
	Metadata map[string]string
	// Entities are the people, systems and concepts Hindsight linked the memory to.
	Entities []string
	// Context is the retaining caller's own note about where the memory came from.
	Context string
	// DocumentID is what the retainer grouped the memory under. The conductor sets it to
	// the turn id, so this is the provenance that cannot be edited away.
	DocumentID string
	// LearnedAt is Hindsight's mentioned_at: when the memory was learned. There is no
	// created_at on the wire; updated_at is the fallback.
	LearnedAt time.Time
}

Memory is one thing the organisation remembers, as Podium shows it.

Hindsight reports the same memory differently on the list and recall paths — the fact type is `fact_type` on one and `type` on the other, and entities are a comma-joined string on one and an array on the other. This struct is the single shape the rest of Podium sees.

type Operation

type Operation struct {
	ID string
	// Type is Hindsight's task_type: retain, batch_retain, consolidation, and so on.
	Type string
	// Status is pending, processing, completed, failed or cancelled.
	Status string
	// DocumentID is what the retainer grouped the work under — the conductor's turn id, for
	// a retain it started. Empty on the maintenance tasks Hindsight schedules itself.
	DocumentID string
	// ErrorMessage is Hindsight's own words about why it gave up, after its retries.
	ErrorMessage string
	RetryCount   int
	UpdatedAt    time.Time
}

Operation is one unit of work Hindsight took on. It matters because Retain is asynchronous: it returns once the work is ACCEPTED, and whether any fact came out of it is decided later, by a worker this process never hears from. An operation is the only place that outcome is recorded.

type Options

type Options struct {
	// BaseURL is Hindsight's base URL as this process reaches it. Required.
	BaseURL string
	// Bank is the memory bank. Required.
	Bank string
	// APIKey is the bearer. Required: Hindsight ships with no authentication, so a client
	// with no key is a client talking to something that should not exist.
	APIKey string
	// HTTPClient lets a test point at an httptest server. Nil means one with DefaultTimeout.
	HTTPClient *http.Client
}

Options is what New needs.

Jump to

Keyboard shortcuts

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