Documentation
¶
Overview ¶
Package agentlooptest provides reusable conformance harnesses for the agentloop store contracts. An application implementing agentloop.StepStore / SessionStore against its own schema runs these from its own _test.go as an acceptance gate, so every implementation is held to the same behavioural guarantees the loop relies on.
It imports "testing" because it is consumed only from tests.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func SessionStoreContract ¶ added in v0.4.0
func SessionStoreContract(t *testing.T, h SessionStoreHarness)
SessionStoreContract asserts the behavioural contract every agentloop.SessionStore must satisfy.
func TestPgxSessionStore_Contract(t *testing.T) {
agentlooptest.SessionStoreContract(t, agentlooptest.SessionStoreHarness{
NewStore: func() agentloop.SessionStore { return freshStore(t) },
})
}
The load-bearing guarantees are that an unknown id is not an error and does not bring a session into being — the loop calls Get before every run and treats "no session yet" as normal, so a store that created one there would make Exists meaningless — and that Get reflects the most recent UpdateData, which is how an agent's working memory survives across Run boundaries.
Deliberately unspecified: whether Finalize creates a session that does not exist. The interface offers no way to read a summary back, so the contract can only require that recording one succeeds; a store free to upsert there (to make its own session listing complete, say) stays conformant.
func StepStoreContract ¶
func StepStoreContract(t *testing.T, h StepStoreHarness)
StepStoreContract asserts the behavioural contract every agentloop.StepStore must satisfy.
func TestPgxStepStore_Contract(t *testing.T) {
agentlooptest.StepStoreContract(t, agentlooptest.StepStoreHarness{
NewStore: func() agentloop.StepStore { return freshStore(t) },
EnsureSession: func(id string) { seedSession(t, id) }, // FK prerequisite
})
}
The load-bearing guarantee is LastN's chronological (oldest-first) order: the loop replays it straight into the LLM context, so a store that returns rows newest-first would silently corrupt multi-turn history. The second is that ToolArgs survives a round trip: a compaction checkpoint keeps its marker there, and a store that drops the field turns every checkpoint into an unusable row — which shows up not as an error but as a session quietly paying to re-summarize itself on every run.
Types ¶
type SessionStoreHarness ¶ added in v0.4.0
type SessionStoreHarness struct {
// NewStore returns a FRESH, empty SessionStore on each call.
NewStore func() agentloop.SessionStore
}
SessionStoreHarness configures the SessionStoreContract for a particular implementation.
type StepStoreHarness ¶
type StepStoreHarness struct {
// NewStore returns a FRESH, empty StepStore on each call.
NewStore func() agentloop.StepStore
// EnsureSession is called once per session id before any step is
// appended for it. Relational stores whose steps table has a
// foreign key to a sessions table use it to create the prerequisite
// session row; in-memory stores leave it nil. It receives the
// session ids below.
EnsureSession func(sessionID string)
}
StepStoreHarness configures the StepStoreContract for a particular implementation.