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
- Variables
- func MCPURL(taskBaseURL, bank string) string
- type Client
- type HTTP
- func (c *HTTP) FailedOperations(ctx context.Context, limit int) ([]Operation, error)
- func (c *HTTP) Forget(ctx context.Context, id string) error
- func (c *HTTP) List(ctx context.Context, cursor string, limit int) ([]Memory, string, error)
- func (c *HTTP) Ready(ctx context.Context) error
- func (c *HTTP) Recall(ctx context.Context, query string, limit int) ([]Memory, error)
- func (c *HTTP) Retain(ctx context.Context, item Item) error
- type Item
- type Memory
- type Operation
- type Options
Constants ¶
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.
const DefaultLimit = 50
DefaultLimit is how many memories a page holds when the caller does not say.
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.
const MaxLimit = 200
MaxLimit caps a page. Hindsight's own default is 100.
const OperationFailed = "failed"
OperationFailed is the terminal status that means no fact was written and none will be.
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 ¶
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".
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.
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 ¶
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 ¶
New validates the options and returns a client. It makes no request: a conductor must start with Hindsight down.
func (*HTTP) FailedOperations ¶
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 ¶
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 ¶
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 ¶
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 ¶
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.
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.