Documentation
¶
Overview ¶
Package ext holds optional sandbox.Pack implementations that are generically useful but don't belong in the core sandbox package.
sandbox's built-in packs (require, http, fetch, markdown, ai, help, skills) are the minimal set every agentloop deployment needs. The packs here — email, secret, document search, a document store — are common but optional: most of the applications this was extracted from use two or three of them, never all four, and a new deployment starts with none.
Each pack follows the same decoupling the core packs use: it takes a callback or a small interface (EmailPack's send func, SecretPack's get func, SearchPack's search func, StoresPack's StoresBackend) rather than a concrete dependency, so this package stays free of any mail/secrets/search-backend import. An application wires its own backend in when it builds the agentloop.Capability that installs the pack — see the package examples and DefaultCapabilities in the agentloop package for the pattern.
Index ¶
- func EmailPack(ctx context.Context, send func(to, subject, body string) error) sandbox.Pack
- func OpenAPIPack(spec *openapi3.T, cfg OpenAPIConfig) (sandbox.Pack, error)
- func SearchPack(search func(query string, topK int) ([]SearchHit, error)) sandbox.Pack
- func SecretPack(ctx context.Context, get func(name string) (string, error)) sandbox.Pack
- func StoresPack(backend StoresBackend) sandbox.Pack
- type OpenAPIConfig
- type SearchHit
- type StoreDoc
- type StoresBackend
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EmailPack ¶
EmailPack exposes a synchronous `sendEmail({to, subject, body})` primitive. It takes a send callback rather than a concrete mailer so this package stays transport-agnostic — the application's Capability closes the callback over its configured sender + from address.
Every call is policy-gated with toolName "sendEmail"; sandbox.DefaultPolicy denies it unless granted via DefaultPolicy.AllowTools. ctx is the per-session context the check shares with the run.
The argument is an object so the call site is self-documenting and resilient to added optional fields. Returns true on success; a send error surfaces as a catchable JS throw.
func OpenAPIPack ¶
OpenAPIPack turns an OpenAPI 3 document into a require()-able skill: one JS function per operation (path + method), named after the operation's operationId (sanitized) or derived from the method and path when it has none.
Each generated function calls the sandbox's own internal _http primitive — the same one require('http') wraps (see pack_fetch.go in the sandbox package) — rather than a new HTTP client. That's the whole design: OpenAPIPack only generates JavaScript source (a string), so every call a generated function makes is still policy-gated exactly like fetch()/require('http') already are, with no new Go-side networking code to audit. _http is used directly rather than require('http')'s get/post/put/del because it uniformly supports every method via its `method` option, including PATCH, which the http module has no wrapper for.
Following the skill-lazy-loading pattern the rest of agentloop's skill mechanism uses (see sandbox.SkillDiscoveryPack's doc comment), the returned Pack's Prompt is a single short line — the API's name, operation count, and a pointer to skillGet(name)/require(name) — not the full API surface; a spec can have far more operations than are worth inlining into every turn. The full per-operation documentation is TypeScript ambient declarations (`declare function ...`), in the same style the core packs' Prompt fields already use, registered as a HelpEntry under Name so skillGet(name) returns it on demand.
Parameters are passed as a single options object rather than positionally — `functionName(params)`, with params.<name> for each path/query parameter and params.body for the request body — since OpenAPI operations vary too much in parameter count and optionality for a positional signature to stay readable. Required-ness is documented but not enforced client-side; the server is still free to reject a missing required parameter.
Returns an error if the spec resolves to zero generated operations (no BaseURL and no servers, no paths, or every operation filtered out by Methods) — a skill with nothing callable is a config mistake, not something to silently install.
func SearchPack ¶
SearchPack exposes a synchronous `documentSearch(query, topK?)` primitive backed by a semantic-search / RAG retriever. It takes a search callback rather than a concrete retriever so this package stays free of that dependency — the application's Capability closes the callback over its own retriever and the per-session scope.
topK defaults to 5 when omitted or <= 0.
func SecretPack ¶
SecretPack exposes a synchronous `secret(name)` primitive that reads a decrypted secret by name. It takes a getter callback rather than a concrete secrets service so this package stays free of that dependency — the application's Capability closes the getter over its own secrets backend and the per-session scope.
Every read is policy-gated with toolName "secret"; sandbox.DefaultPolicy denies it unless granted via DefaultPolicy.AllowTools. ctx is the per-session context the check shares with the run.
Lookup failures (unknown name, decrypt error) surface as a thrown JS error so a skill can try/catch; they do not crash the run.
func StoresPack ¶
func StoresPack(backend StoresBackend) sandbox.Pack
StoresPack exposes a `stores` object with `list()` and `read(id)` for inspecting the indexed document corpus from inside the sandbox.
Types ¶
type OpenAPIConfig ¶
type OpenAPIConfig struct {
// Name is the skill's name — the string passed to require(name) and
// shown in skillList(). Defaults to a slug of spec.Info.Title, or
// "api" if the spec has no title.
Name string
// Description is the skillList() one-liner. Defaults to
// spec.Info.Title, or a generic fallback if the spec has none.
Description string
// BaseURL overrides the spec's first `servers` entry. Required if
// the spec declares no servers.
BaseURL string
// Headers are applied to every request this skill's functions
// make — the place to put a static API key or bearer token.
// OpenAPI's securitySchemes are not interpreted; this is the whole
// auth story OpenAPIPack has.
Headers map[string]string
// Methods restricts which HTTP methods become functions. Nil
// generates GET, POST, PUT, PATCH, DELETE (the common REST verbs);
// HEAD/OPTIONS/TRACE/CONNECT are never generated regardless.
Methods []string
}
OpenAPIConfig configures OpenAPIPack.
type SearchHit ¶
type SearchHit struct {
DocumentID string `json:"documentId"`
DocumentTitle string `json:"documentTitle"`
ChunkIndex int `json:"chunkIndex"`
Content string `json:"content"`
Score float64 `json:"score"`
}
SearchHit is one semantic-search result surfaced to the sandbox. The JSON tags drive the JS-side key names (the pack converts hits to plain maps so the runtime sees camelCase keys).
type StoreDoc ¶
type StoreDoc struct {
ID string `json:"id"`
Title string `json:"title"`
ChunkCount int64 `json:"chunkCount"`
}
StoreDoc is one indexed document surfaced to the sandbox by the stores primitive.
type StoresBackend ¶
type StoresBackend interface {
// List returns every indexed document in the current scope.
List() ([]StoreDoc, error)
// Read returns the full text of one document (its chunks joined in
// source order). An unknown id yields an empty string, no error.
Read(documentID string) (string, error)
}
StoresBackend is the read surface the stores primitive needs. An application adapts its own document catalog to it (scoped to the session); this keeps this package free of that dependency.