agentbench

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package agentbench runs multi-turn harness benchmarks aligned with industry agent/memory/tool evaluation shapes (LoCoMo-style memory, multi-hop QA, τ-bench-style domain end state, plan+interrupt, web-augmented).

Case definitions and seed worlds live in Go (see cases_*.go), not external JSONL.

Index

Constants

View Source
const (
	SuiteMemory        = "memory"
	SuiteMultihopQA    = "multihop_qa"
	SuiteToolDomain    = "tool_domain"
	SuiteWebAugmented  = "web_augmented"
	SuitePlanInterrupt = "plan_interrupt"
)

Suite identifiers.

View Source
const DefaultEmbedModel = "text-embedding-3-small"

DefaultEmbedModel is used when OPENAI_EMBEDDING_MODEL / -embed-model is unset.

View Source
const SharedSystemPrompt = `` /* 623-byte string literal not displayed */

SharedSystemPrompt steers plan + brain + web tool use without domain hardcoding.

Variables

View Source
var (
	IDProjectOrion = uuid.MustParse("11111111-1111-1111-1111-111111111101")
	IDPersonAlex   = uuid.MustParse("11111111-1111-1111-1111-111111111102")
	IDPersonSam    = uuid.MustParse("11111111-1111-1111-1111-111111111103")
	IDNoteAsync    = uuid.MustParse("11111111-1111-1111-1111-111111111104")
	IDNoteLegal    = uuid.MustParse("11111111-1111-1111-1111-111111111105")
	IDNoteNoise    = uuid.MustParse("11111111-1111-1111-1111-111111111106")
	IDChunkLegal   = uuid.MustParse("11111111-1111-1111-1111-111111111107")
)

fixed IDs for multihop evidence gold (stable across runs).

AllSuites is the default suite list for -suite all.

Functions

func ApplySeed

func ApplySeed(ctx context.Context, eng *brain.Engine, scope brain.Scope, world SeedWorld) error

ApplySeed puts objects and links under scope. Fills nil IDs with new UUIDs in-place on a copy of the seed so gold ids in Cases that set fixed UUIDs remain stable.

func DefaultGates

func DefaultGates() map[string]float64

DefaultGates are v1 success-rate floors (non-skipped cases only).

func EvaluateGates

func EvaluateGates(rep Report, hasExa bool) (bool, []string)

EvaluateGates returns whether gates pass and human-readable notes.

func FormatMarkdown

func FormatMarkdown(rep Report) string

FormatMarkdown returns a compact scorecard for stdout.

func KindSpecs

func KindSpecs() []brain.KindSpec

KindSpecs used for all seeded worlds.

func ListCases

func ListCases(w io.Writer, suite string)

ListCases prints case ids for -list.

func WriteJSON

func WriteJSON(w io.Writer, rep Report) error

WriteJSON writes the scorecard as JSON.

Types

type Case

type Case struct {
	ID    string
	Suite string
	// RequiresExa skips the case when EXA_API_KEY is empty (not a failure).
	RequiresExa bool
	// RestoreSession: after the first N-1 turns, rebuild agent from session for the last turn.
	RestoreSession bool
	Turns          []string
	// InterruptChoiceTitle is matched against ask_user_choice options (case-insensitive contains).
	// When empty, selectionIdx 0 is used.
	InterruptChoiceTitle string
	// InterruptSelectionIdx used when title is empty or unmatched.
	InterruptSelectionIdx int
	Seed                  SeedWorld
	Expect                Expect
}

Case is one multi-turn benchmark scenario with in-memory seed and rule expects.

func AllCases

func AllCases() []Case

AllCases returns every built-in benchmark case (seed data embedded in Go).

func CasesForSuite

func CasesForSuite(suite string) []Case

CasesForSuite filters AllCases by suite id (empty / "all" → all).

type CaseResult

type CaseResult struct {
	ID      string   `json:"id"`
	Suite   string   `json:"suite"`
	Skipped bool     `json:"skipped,omitempty"`
	SkipWhy string   `json:"skip_why,omitempty"`
	Success bool     `json:"success"`
	Notes   []string `json:"notes,omitempty"`
	// Scores are named 0/1 or fractions for aggregation.
	Scores map[string]float64 `json:"scores,omitempty"`
	Turns  []TurnTrace        `json:"-"` // omit heavy traces from default JSON unless verbose
}

CaseResult is the judged outcome of one case.

type Config

type Config struct {
	Suites      []string
	CaseFilter  string // optional exact case id
	ModelURL    string
	ModelAPIKey string
	ModelName   string
	// EmbedURL defaults to ModelURL. EmbedAPIKey defaults to ModelAPIKey.
	// EmbedModel defaults to DefaultEmbedModel / OPENAI_EMBEDDING_MODEL.
	EmbedURL    string
	EmbedAPIKey string
	EmbedModel  string
	// LexicalOnly disables the dense channel (no WithEmbedder).
	LexicalOnly bool
	ExaAPIKey   string
	Timeout     time.Duration // per case
	DryRun      bool
}

Config configures a benchmark run.

type Expect

type Expect struct {
	// FinalContainsAny: final assistant text must contain at least one (case-insensitive).
	FinalContainsAny []string
	// FinalContainsAll: every string must appear.
	FinalContainsAll []string
	// MustTools: each inner list is an OR group; every group must match some tool name used.
	MustTools [][]string
	// MustNotTools: none of these tool names may appear.
	MustNotTools []string
	// MustInterrupt: at least one ask_user_choice (or any interrupt) must have fired.
	MustInterrupt bool
	// BrainKindContains: after the case, FindObjects or list kinds via search for this kind
	// with query substring must return ≥1 hit (empty Query → any of that kind via find with kind filter + broad query).
	BrainKind  string
	BrainQuery string
	// BrainTitleContains: some object of BrainKind (or any if empty) has title containing this.
	BrainTitleContains string
	// GoldEvidenceIDs: at least one must appear in tool args or results text (evidence hit).
	GoldEvidenceIDs []uuid.UUID
}

Expect is a rule-based judge. All set fields must pass for Success.

type OpenAIEmbedder

type OpenAIEmbedder struct {
	BaseURL    string
	APIKey     string
	Model      string
	HTTPClient *http.Client
}

OpenAIEmbedder implements brain.QueryEmbedder via POST {baseURL}/embeddings (OpenAI-compatible, including Azure OpenAI with base …/openai/v1).

func (*OpenAIEmbedder) Embed

func (e *OpenAIEmbedder) Embed(ctx context.Context, text string) ([]float32, error)

Embed returns a dense vector for text. Empty text returns nil, nil (Put skips embed).

type Report

type Report struct {
	Model      string                 `json:"model"`
	EmbedModel string                 `json:"embed_model,omitempty"`
	StartedAt  time.Time              `json:"started_at"`
	Duration   time.Duration          `json:"duration_ms"` // wall; JSON via custom if needed
	Suites     map[string]SuiteResult `json:"suites"`
	GatesOK    bool                   `json:"gates_ok"`
	GateNotes  []string               `json:"gate_notes,omitempty"`
}

Report is the full scorecard written to -out.

func Run

func Run(ctx context.Context, cfg Config) (Report, error)

Run executes suites and returns a scorecard.

type SeedEdge

type SeedEdge struct {
	From, To uuid.UUID
	Relation string
	Note     string
}

SeedEdge is a Link between two seed object ids (must exist in Objects).

type SeedObject

type SeedObject struct {
	ID       uuid.UUID
	Kind     string
	Title    string
	Summary  string
	Content  string
	ParentID *uuid.UUID
	Position *int
	Props    map[string]any
}

SeedObject is a brain row to Put before the case runs.

type SeedWorld

type SeedWorld struct {
	// Objects with fixed IDs (for multihop evidence gold). Empty ID → generated on seed.
	Objects []SeedObject
	Edges   []SeedEdge
}

SeedWorld is applied under a fresh namespace before the first turn.

func WorldMeetingPrep

func WorldMeetingPrep() SeedWorld

WorldMeetingPrep is a small “notes app” graph for multihop / domain cases.

type SuiteResult

type SuiteResult struct {
	Suite       string       `json:"suite"`
	N           int          `json:"n"`
	Skipped     int          `json:"skipped"`
	Passed      int          `json:"passed"`
	Failed      int          `json:"failed"`
	SuccessRate float64      `json:"success_rate"` // among non-skipped
	IllegalRate float64      `json:"illegal_rate"`
	Cases       []CaseResult `json:"cases"`
}

SuiteResult aggregates cases in one suite.

type ToolCallRecord

type ToolCallRecord struct {
	Name      string
	Arguments string
	Result    string // best-effort from tool_result content
}

ToolCallRecord is one observed tool invocation from the stream.

type TurnTrace

type TurnTrace struct {
	Prompt       string
	Assistant    string
	Tools        []ToolCallRecord
	Interrupts   int
	Error        string
	Duration     time.Duration
	RestoredSess bool
}

TurnTrace is one user turn of a case.

Jump to

Keyboard shortcuts

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