agenttools

package
v0.18.5 Latest Latest
Warning

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

Go to latest
Published: Sep 16, 2026 License: Apache-2.0 Imports: 26 Imported by: 0

Documentation

Overview

Package agenttools exposes the Encounter engine to LLM agents as a catalog of callable tools.

The catalog is the single source of truth shared by every agent surface in this repository: the PicoClaw agent embedded into the iOS app through gomobile (mobile/encxmobile) and the MCP server served by encli. Each tool implements PicoClaw's toolshared.Tool interface, so a catalog can be registered directly into a *tools.ToolRegistry.

Unlike the legacy agent path in cmd/encli, tools here are free of CLI coupling: they never write to stdout, never panic to report failure, and never mutate package-level state. Results are returned as JSON so the same tool works for an in-app chat, an MCP client, and a test.

Engine mutations (submitting codes, taking penalty hints, joining a game) are gated by a Policy. Under PolicyApprove — the default — every mutating call has to be confirmed through a Confirmer before it reaches the engine.

Index

Constants

View Source
const DefaultPolicy = PolicyApprove

DefaultPolicy is applied when a caller leaves Options.Policy empty.

View Source
const DefaultRequestInterval = 350 * time.Millisecond

DefaultRequestInterval is the floor between engine requests. It matches the pacing the iOS app already applies to its own traffic.

Variables

This section is empty.

Functions

This section is empty.

Types

type Catalog

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

Catalog is the engine toolset bound to one engine and one access policy.

func NewCatalog

func NewCatalog(engine Engine, opts Options) (*Catalog, error)

NewCatalog builds the engine toolset.

func (*Catalog) All

func (c *Catalog) All() []*Tool

All returns every tool the catalog knows about, including the ones the policy hides.

func (*Catalog) InvalidateCache

func (c *Catalog) InvalidateCache()

InvalidateCache drops every memoized read.

Callers that serve discrete requests should call this between them: the game moves while the player reads, and answering a new question from a cached level is worse than a slower fresh read.

func (*Catalog) Lookup

func (c *Catalog) Lookup(name string) (*Tool, bool)

Lookup finds a tool by name, ignoring policy visibility.

func (*Catalog) Policy

func (c *Catalog) Policy() Policy

Policy returns the access policy the catalog was built with.

func (*Catalog) Register

func (c *Catalog) Register(registry *tools.ToolRegistry)

Register adds the exposed tools to a PicoClaw registry.

func (*Catalog) SystemPromptAddendum

func (c *Catalog) SystemPromptAddendum() string

SystemPromptAddendum describes the engine and the active policy to the model.

func (*Catalog) Tools

func (c *Catalog) Tools() []*Tool

Tools returns the tools an agent may see. Under PolicyReadonly the mutating tools are withheld so the model is never tempted to call them.

type ConfirmRequest

type ConfirmRequest struct {
	Tool string         `json:"tool"`
	Args map[string]any `json:"args,omitempty"`
}

ConfirmRequest describes a mutating call awaiting the user's decision.

type Confirmer

type Confirmer interface {
	ConfirmToolCall(ctx context.Context, req ConfirmRequest) (bool, error)
}

Confirmer approves or declines a mutating tool call. Implementations are expected to block until the user answers or ctx is cancelled.

type ConfirmerFunc

type ConfirmerFunc func(ctx context.Context, req ConfirmRequest) (bool, error)

ConfirmerFunc adapts a function to the Confirmer interface.

func (ConfirmerFunc) ConfirmToolCall

func (f ConfirmerFunc) ConfirmToolCall(ctx context.Context, req ConfirmRequest) (bool, error)

ConfirmToolCall implements Confirmer.

type Engine

type Engine interface {
	GetDomainGames(ctx context.Context) ([]encx.DomainGame, error)
	GetGameList(ctx context.Context, page ...int) (*encx.GameListResponse, error)
	GetGameModel(ctx context.Context, gameId int, formValues ...url.Values) (*encx.GameModel, error)
	GetGameModelLevel(ctx context.Context, gameId, levelNumber int) (*encx.GameModel, error)
	GetGameStatistics(ctx context.Context, gameId int) (*encx.GameStatisticsResponse, error)
	GetTimeoutToGame(ctx context.Context, gameId int) (*int, error)
	GetProfile(ctx context.Context) (*encx.Profile, error)
	GetTeamManagementInfo(ctx context.Context, teamID int) (*encx.TeamManagementInfo, error)
	FetchResource(ctx context.Context, rawURL string, opts ...encx.ResourceOptions) (*encx.Resource, error)
	EnterGame(ctx context.Context, gameId int) (string, error)
	SendCode(ctx context.Context, gameId, levelId, levelNumber int, code string) (*encx.GameModel, error)
	SendBonusCode(ctx context.Context, gameId, levelId, levelNumber int, code string) (*encx.GameModel, error)
	GetPenaltyHint(ctx context.Context, gameId, penaltyId int) (*encx.GameModel, error)
}

Engine is the slice of the Encounter client the tool catalog depends on. Narrowing the dependency keeps the tools testable without a live domain.

type Options

type Options struct {
	// Policy decides what the agent may do with the engine. Empty means
	// DefaultPolicy.
	Policy Policy
	// Confirmer authorizes mutating calls under PolicyApprove.
	Confirmer Confirmer
	// ReadCacheTTL memoizes read-tool results for this long. Zero disables
	// caching. Callers that drive discrete turns should also call
	// InvalidateCache between them.
	ReadCacheTTL time.Duration
}

Options configures a catalog.

type Paced

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

Paced wraps an Engine so concurrent tools cannot burst requests at Encounter.

An LLM runtime executes the tool calls of one turn in parallel, so a single question can fire half a dozen engine requests at once. Encounter answers a burst with its anti-spam page rather than JSON, which surfaces to the player as a broken session on an account that is perfectly fine.

func NewPaced

func NewPaced(engine Engine, interval time.Duration) *Paced

NewPaced spaces out requests to engine. A non-positive interval means DefaultRequestInterval.

func (*Paced) EnterGame

func (p *Paced) EnterGame(ctx context.Context, gameId int) (string, error)

func (*Paced) FetchResource

func (p *Paced) FetchResource(
	ctx context.Context, rawURL string, opts ...encx.ResourceOptions,
) (*encx.Resource, error)

func (*Paced) GetDomainGames

func (p *Paced) GetDomainGames(ctx context.Context) ([]encx.DomainGame, error)

func (*Paced) GetGameList

func (p *Paced) GetGameList(ctx context.Context, page ...int) (*encx.GameListResponse, error)

func (*Paced) GetGameModel

func (p *Paced) GetGameModel(
	ctx context.Context, gameId int, formValues ...url.Values,
) (*encx.GameModel, error)

func (*Paced) GetGameModelLevel

func (p *Paced) GetGameModelLevel(ctx context.Context, gameId, levelNumber int) (*encx.GameModel, error)

func (*Paced) GetGameStatistics

func (p *Paced) GetGameStatistics(ctx context.Context, gameId int) (*encx.GameStatisticsResponse, error)

func (*Paced) GetPenaltyHint

func (p *Paced) GetPenaltyHint(ctx context.Context, gameId, penaltyId int) (*encx.GameModel, error)

func (*Paced) GetProfile

func (p *Paced) GetProfile(ctx context.Context) (*encx.Profile, error)

func (*Paced) GetTeamManagementInfo

func (p *Paced) GetTeamManagementInfo(ctx context.Context, teamID int) (*encx.TeamManagementInfo, error)

func (*Paced) GetTimeoutToGame

func (p *Paced) GetTimeoutToGame(ctx context.Context, gameId int) (*int, error)

func (*Paced) SendBonusCode

func (p *Paced) SendBonusCode(
	ctx context.Context, gameId, levelId, levelNumber int, code string,
) (*encx.GameModel, error)

func (*Paced) SendCode

func (p *Paced) SendCode(
	ctx context.Context, gameId, levelId, levelNumber int, code string,
) (*encx.GameModel, error)

type Policy

type Policy string

Policy decides what an agent is allowed to do with the engine.

const (
	// PolicyReadonly hides mutating tools from the catalog and refuses them if
	// they are called anyway.
	PolicyReadonly Policy = "readonly"
	// PolicyApprove exposes mutating tools but routes every call through a
	// Confirmer first. This is the default.
	PolicyApprove Policy = "approve"
	// PolicyFull lets the agent mutate engine state without asking.
	PolicyFull Policy = "full"
)

func ParsePolicy

func ParsePolicy(s string) (Policy, error)

ParsePolicy converts a textual policy name, accepting the empty string as the default.

type Tool

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

Tool is one engine capability exposed to an LLM agent.

func (*Tool) Description

func (t *Tool) Description() string

Description implements toolshared.Tool.

func (*Tool) Execute

func (t *Tool) Execute(ctx context.Context, args map[string]any) *toolshared.ToolResult

Execute implements toolshared.Tool. Mutating tools are authorized first; the engine result is returned as JSON.

func (*Tool) Mutating

func (t *Tool) Mutating() bool

Mutating reports whether the tool changes engine state and therefore needs authorization.

func (*Tool) Name

func (t *Tool) Name() string

Name implements toolshared.Tool.

func (*Tool) Parameters

func (t *Tool) Parameters() map[string]any

Parameters implements toolshared.Tool. The returned schema is a copy, so a caller handing it to a provider cannot corrupt the catalog.

Jump to

Keyboard shortcuts

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