tools

package
v1.801.490 Latest Latest
Warning

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

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

Documentation

Overview

Package tools is everything your org can call, in one list: connector actions, functions, agents, skills and your own MCP servers.

It is the ONE tool plane for Hanzo Cloud's PER-TENANT capabilities — a single registry where every callable thing an ORG owns is a Tool with a Source, a JSON-Schema, a per-(org,project) activation state, and an optional price.

Per-tenant is the whole boundary. Cloud's OWN typed ops are not here and never were a Source: they are code, known at build time, and the fleet publishes them as MCP tools straight from the typed-op registry onto the host's one door (plugin/<app>/mcp.json → zip.Plugin.Tools). What lives here is ROWS — a tool whose existence, price and activation depend on which org is asking — reached from that same door through the typed POST /v1/tools/call.

Decomplected on the Rich Hickey seam: a Source knows how to LIST its tools and DISPATCH one; the registry knows nothing about how any single source works. Each source REGISTERS a Provider into the registry from its own Mount — no source duplicates listing or dispatch logic, and the registry never grows a per-source branch. Adding a source is: implement Provider, call tools.Register.

Every dispatch flows through ONE per-principal plane: the caller's VALIDATED org (principal.Org) gates the call, the tool must be ACTIVATED for that (org,project) or the call is 403, a priced tool settles through the explicit x402 Charger seam, and the platform meters one unit. One plane, one policy, every source.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotActivated — the tool exists for the scope but is not activated for this
	// (org,project). The activation API (task 5) toggles it on.
	ErrNotActivated = errors.New("tools: not activated for this org/project")
	// ErrUnknownTool — no source offers a tool by this name for the scope.
	ErrUnknownTool = errors.New("tools: unknown tool")
	// ErrNotDispatchable — the tool is discovery/activation-only (e.g. a skill).
	ErrNotDispatchable = errors.New("tools: not dispatchable")
	// ErrPaymentRequired — a priced tool could not be settled through the Charger.
	ErrPaymentRequired = errors.New("tools: payment required")
	// ErrChargerUnset — a priced tool was called but no x402 Charger is wired; the
	// call fails CLOSED (a paid tool is never served free).
	ErrChargerUnset = errors.New("tools: payment seam not configured")
)

Sentinel dispatch outcomes. The HTTP layer maps these to status codes: a not-activated tool is 403 (the tool plane never serves an unactivated tool), an unknown tool is 404-in-JSON-RPC, payment-required is 402, not-dispatchable is 422.

Functions

func Door added in v1.801.350

func Door() zip.Source

Door is the per-caller tool source this subsystem contributes to its own MCP door. The composition root hands it to cloud.Serve (plugin/tools/main.go), which is the one place a subsystem's contributions to the binary are stated.

func Mount

func Mount(app cloud.Router, deps cloud.Deps) error

Mount registers the tool plane on app.

func Register

func Register(p Provider)

Register adds a source Provider to the process-wide registry. Each source calls this ONCE from its Mount (only enabled subsystems mount, so a disabled source is simply absent). Order does not matter: List/Dispatch run at request time.

func SetCharger

func SetCharger(c Charger)

SetCharger installs the x402 payment seam on the process-wide registry. The subsystem that owns the price table calls this once from its Mount (apps/marketplace); until it does, a tool with a declared price fails closed.

func Shutdown

func Shutdown(_ context.Context) error

Shutdown closes the stores. Idempotent.

Types

type ActivationStore

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

ActivationStore is the per-(org,project,tool) activation plane: the durable toggle hanzo.chat / hanzo.app read to decide which skills/plugins/connectors an org has turned on. It is the tool-plane twin of the entitlements (org,product) enablement store — a row exists iff the tool is EXPLICITLY activated for that scope, and dispatch fails closed (403) on any tool without one.

Isolation is the (org, project, tool) composite key plus a mandatory `WHERE org=? AND project=?` on every statement. org/project are the VALIDATED principal values, never client input. One SQLite file (all orgs, org column), MaxOpenConns(1), WAL — the shared cloud store discipline.

func OpenActivationStore

func OpenActivationStore(dir string) (*ActivationStore, error)

OpenActivationStore opens (and migrates) the activation store under dir.

func (*ActivationStore) Activate

func (s *ActivationStore) Activate(ctx context.Context, org, project, tool string, source Source, byUser string) error

Activate turns a tool on for (org, project). Idempotent on the composite key. source + byUser are recorded for the audit/console view.

func (*ActivationStore) Close

func (s *ActivationStore) Close() error

Close closes the underlying database.

func (*ActivationStore) Deactivate

func (s *ActivationStore) Deactivate(ctx context.Context, org, project, tool string) error

Deactivate turns a tool off for (org, project). Idempotent (no row ⇒ no-op).

func (*ActivationStore) IsActivated

func (s *ActivationStore) IsActivated(ctx context.Context, org, project, tool string) bool

IsActivated reports whether tool is activated for (org, project). It is nil-safe: a nil store (pre-Mount / split deploy) reports NOT activated, so dispatch fails closed rather than serving an unactivated tool.

func (*ActivationStore) List

func (s *ActivationStore) List(ctx context.Context, org, project string) ([]string, error)

List returns the activated tool names for (org, project), sorted.

type AuthoredPlugin added in v1.801.350

type AuthoredPlugin struct {
	// ID is the plugin's id within the org, and the id a delete addresses.
	ID string `json:"id"`
	// Org is the org that built the plugin — the validated caller's.
	Org string `json:"org"`
	// Name is the plugin's name: one lowercase path segment, the id it runs by.
	Name string `json:"name"`
	// Provider is the connectors provider whose credential this plugin uses at
	// run time. Absent for a plugin that needs none. The credential itself is
	// never here — it stays under KMS custody in the connectors plane.
	Provider string `json:"provider,omitempty"`
	// Source is the TypeScript as authored (or as generated from a spec).
	Source string `json:"source"`
	// Bundled is the CommonJS the bundler produced, which the runtime executes.
	// Never rendered to a client.
	Bundled string `json:"-"`
	// CreatedAt is when the plugin was last built, Unix seconds.
	CreatedAt int64 `json:"createdAt"`
}

AuthoredPlugin is one org-authored connector plugin: the TypeScript a person (or the generator) wrote, plus the CommonJS the bundler produced from it.

It holds NO credential. A plugin declares WHICH connector provider it needs and the credential stays in the connectors plane, where it is already under KMS custody — so a generated plugin is safe to read, diff, and re-bundle, and rotating a key never means editing code.

type AuthoredStore added in v1.801.350

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

AuthoredStore is the per-org registry of authored plugins (one SQLite file, org column, the shared cloud store discipline). Isolation is a mandatory `WHERE org=?` on every statement; org is the validated principal value.

func OpenAuthoredStore added in v1.801.350

func OpenAuthoredStore(dir string) (*AuthoredStore, error)

OpenAuthoredStore opens (and migrates) the authored-plugin store under dir.

func (*AuthoredStore) Close added in v1.801.350

func (s *AuthoredStore) Close() error

Close closes the underlying database.

func (*AuthoredStore) Delete added in v1.801.350

func (s *AuthoredStore) Delete(ctx context.Context, org, id string) error

Delete removes one of the org's plugins. Deleting what is not there is not an error — the caller's intent is "gone", and it is.

func (*AuthoredStore) Get added in v1.801.350

func (s *AuthoredStore) Get(ctx context.Context, org, id string) (AuthoredPlugin, error)

Get returns one plugin INCLUDING its bundled artifact — the runtime needs it.

func (*AuthoredStore) List added in v1.801.350

func (s *AuthoredStore) List(ctx context.Context, org string) ([]AuthoredPlugin, error)

List returns the org's authored plugins, newest first. Bundled is omitted from JSON by its tag, so a list response carries the source but not the artifact.

func (*AuthoredStore) Put added in v1.801.350

Put inserts or replaces a plugin under (org, name). Re-building the same name supersedes it rather than accumulating versions: the store answers "what does this org run now", and a build that is not the current one has no reader.

type CatalogStore added in v1.801.350

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

CatalogStore is the canonical copy of the public registries. One SQLite file, no org column: a catalog is the same for every tenant, and what a tenant does with an entry is a row in the org-scoped server store instead.

func OpenCatalogStore added in v1.801.350

func OpenCatalogStore(dir string) (*CatalogStore, error)

OpenCatalogStore opens (and migrates) the catalog under dir.

func (*CatalogStore) Close added in v1.801.350

func (s *CatalogStore) Close() error

Close closes the underlying database.

func (*CatalogStore) Count added in v1.801.350

func (s *CatalogStore) Count(ctx context.Context) (int, error)

Count is how many listings the canonical copy holds.

func (*CatalogStore) Curate added in v1.801.350

func (s *CatalogStore) Curate(ctx context.Context, id string, c Curation) (MCPListing, error)

Curate applies a patch to one listing and returns the result. Setting Official marks the row curated, so no later sync re-derives over the admin's answer — which is the whole difference between a default and a decision.

func (*CatalogStore) Get added in v1.801.350

func (s *CatalogStore) Get(ctx context.Context, id string) (MCPListing, error)

Get returns one listing by id. A hidden listing is returned — the caller decides whether it may be shown, because a detail page and a curation edit address the same row.

func (*CatalogStore) List added in v1.801.350

func (s *CatalogStore) List(ctx context.Context, q Query) ([]MCPListing, int, error)

List returns one page of the matching listings, featured first then name, with the total the filter matched — which is what lets a storefront say "showing 50 of 9,216" rather than implying the shelf ends where the page does.

func (*CatalogStore) Sync added in v1.801.350

func (s *CatalogStore) Sync(ctx context.Context) (added, updated int, err error)

Sync walks the upstream registry and writes what it publishes into the canonical copy, returning how many rows were new and how many changed.

It is IDEMPOTENT by construction: the id is the publisher's own name, so a second pass over an unchanged registry updates the same rows in place and reports added=0, updated=0. Nothing is ever deleted here — a listing that vanishes upstream is a listing an org may already have enabled, and removing its description would not remove its server.

The CURATION columns are not in the write list at all. That is not a rule to remember, it is the statement: a sync cannot un-hide, un-feature or re-brand anything, because it never names those columns.

type Charger

type Charger interface {
	Charge(ctx context.Context, tool string) error
}

Charger settles one tool call over the x402 payment rail. The tool plane hands it the TOOL NAME and the request context and NOTHING else, because nothing else is the tool plane's to know: who pays is the attested principal already on the context, and what a call costs and who is paid live in the payment layer's own price table — the marketplace listing the x402 Registry is published from. A Charge value carrying cents and a payout wallet would be the commerce graph smuggled into the tool plane, and a payer passed down would be a second answer to a question principal.Ledger already answers.

Every dispatch is offered to the Charger, including free ones: "is this priced" is one lookup in that same table, and asking twice is how a gate and a settlement come to disagree. A FREE tool settles for nothing and returns nil.

Charge returns nil once the call is paid for, ErrPaymentRequired when it is not (the x402 challenge is on the response headers), or another error on an unavailable rail. A nil Charger falls back to the internal plane (charge_peer.go), which is how the shipped fleet — one binary per app — reaches a rail that is never in this process; only a deployment with neither a rail nor a price table in it answers ErrChargerUnset, and there a tool with a DECLARED price fails closed. A paid tool is never served free on any of those paths.

type Curation added in v1.801.350

type Curation struct {
	Hidden   *bool
	Featured *bool
	Official *bool
}

Curation is the set of decisions a SuperAdmin makes about a listing. Every field is a POINTER because this is a patch: nil leaves what is there, which is what lets "feature this" not silently un-hide something.

type MCPListing added in v1.801.350

type MCPListing struct {
	// ID addresses the listing in a URL. It is the reverse-DNS NAME with its one
	// slash written as an underscore — reversible, because a namespace never
	// contains an underscore — so the id is readable and stable rather than a
	// hash that means nothing to whoever reads a link.
	ID string `json:"id"`
	// Name is the publisher's reverse-DNS name, e.g. "com.stripe/mcp".
	Name string `json:"name"`
	// Vendor is the namespace half of Name — the publisher, e.g. "com.stripe".
	Vendor string `json:"vendor"`
	// Title is the human-readable display name, when the entry carries one.
	Title string `json:"title,omitempty"`
	// Description is the publisher's one-line summary.
	Description string `json:"description"`
	// Repo is the source repository URL, when the entry names one.
	Repo string `json:"repo,omitempty"`
	// Site is the project's homepage, when the entry names one.
	Site string `json:"site,omitempty"`
	// Version is the published version of this listing.
	Version string `json:"version"`
	// Transports are the distinct transports this server can be reached over,
	// sorted: some of "stdio", "streamable-http", "sse". A listing with
	// "streamable-http" is one an org can enable here and now; a listing that is
	// only "stdio" needs a process to run it.
	Transports []string `json:"transports"`
	// Packages are the runnable package forms — npm, pypi, oci — each with the
	// runtime that launches it and the transport it then speaks.
	Packages []MCPPackage `json:"packages,omitempty"`
	// Remotes are the hosted endpoints the publisher serves the server at.
	Remotes []MCPRemote `json:"remotes,omitempty"`
	// Registry is the upstream this row was synced from.
	Registry string `json:"registry"`
	// Synced is when this row was last confirmed against upstream, Unix seconds.
	Synced int64 `json:"synced"`
	// Hidden keeps the listing out of the org-visible catalog. Curation: a sync
	// never changes it. Only a SuperAdmin sets it, and only a SuperAdmin sees a
	// hidden entry listed.
	Hidden bool `json:"hidden"`
	// Featured puts the listing on the front of the shelf. Curation.
	Featured bool `json:"featured"`
	// Official is whether this is the vendor's OWN server rather than someone
	// else's copy of it. Derived on every sync (see isOfficial) until a
	// SuperAdmin sets it explicitly, after which the admin's answer stands.
	Official bool `json:"official"`
	// the entry carries one, or the one an admin set. Curation.
	Logo string `json:"logo,omitempty"`
}

MCPListing is one upstream MCP server as we hold it: what the registry published, plus what we decided about it.

func (MCPListing) Endpoint added in v1.801.350

func (l MCPListing) Endpoint() string

Endpoint is the listing's streamable-http URL, or "" when it has none. It is the ONE question enablement asks of a listing: an org can enable what can be reached, and a package that has to be RUN first cannot be until there is somewhere to run it (see apps/tools/LLM.md).

type MCPPackage added in v1.801.350

type MCPPackage struct {
	// Registry is where the package is fetched from: npm, pypi, oci, nuget, mcpb.
	Registry string `json:"registry"`
	// Identifier is the package name or download URL.
	Identifier string `json:"identifier"`
	// Version is the exact published package version.
	Version string `json:"version,omitempty"`
	// Runtime is the publisher's hint for what launches it: npx, uvx, docker.
	Runtime string `json:"runtime,omitempty"`
	// Transport is what the launched process speaks: usually "stdio".
	Transport string `json:"transport"`
}

MCPPackage is one runnable form of a server: what to fetch, what runs it, and what it speaks once running.

type MCPRemote added in v1.801.350

type MCPRemote struct {
	// Transport is "streamable-http" or "sse".
	Transport string `json:"transport"`
	// URL is the endpoint.
	URL string `json:"url"`
}

MCPRemote is one hosted endpoint the publisher serves the server at.

type MCPServer

type MCPServer struct {
	// ID is the server's id within the org. It also PREFIXES every tool name the
	// server contributes, which is what keeps two servers' "search" apart.
	ID string `json:"id"`
	// Org is the org that registered the server — the validated caller's.
	Org string `json:"org"`
	// Name is the org's label for the server.
	Name string `json:"name"`
	// URL is the server's JSON-RPC endpoint. Always a public http(s) host: the
	// registration boundary and the dialer both refuse anything else.
	URL string `json:"url"`
	// AuthHeader is the request header the KMS-held credential is injected into,
	// e.g. "Authorization". Absent when the server needs no credential.
	AuthHeader string `json:"authHeader,omitempty"`
	// HasSecret is whether a credential is sealed in KMS for this server. The
	// VALUE is never returned by any route.
	HasSecret bool `json:"hasSecret"`
	// Listing is the catalog entry this server was enabled from, when it was.
	// Empty means the org typed the URL in itself.
	Listing string `json:"listing,omitempty"`
	// Source is where the registration came from: "catalog" when it was enabled
	// off the shelf, "org" when the org registered the URL itself. It is DERIVED
	// from Listing rather than stored, because two columns for one fact is two
	// chances to disagree.
	Source string `json:"source"`
	// CreatedAt is when the server was registered, Unix seconds.
	CreatedAt int64 `json:"createdAt"`
}

MCPServer is one org-registered external MCP server. AuthHeader/HasSecret record how to authenticate; the secret itself is in KMS at authRef(org, id).

type MCPServerStore

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

MCPServerStore is the per-org registry of external MCP servers (one SQLite file, org column, the shared cloud store discipline). Isolation is a mandatory `WHERE org=?` on every statement; org is the validated principal value.

func OpenMCPServerStore

func OpenMCPServerStore(dir string) (*MCPServerStore, error)

OpenMCPServerStore opens (and migrates) the external-server store under dir.

func (*MCPServerStore) Close

func (s *MCPServerStore) Close() error

Close closes the underlying database.

func (*MCPServerStore) Delete

func (s *MCPServerStore) Delete(ctx context.Context, org, id string) (bool, error)

Delete removes a server for (org, id). Returns whether a row was removed.

func (*MCPServerStore) Get

func (s *MCPServerStore) Get(ctx context.Context, org, id string) (MCPServer, error)

Get returns one server for (org, id).

func (*MCPServerStore) List

func (s *MCPServerStore) List(ctx context.Context, org string) ([]MCPServer, error)

List returns an org's registered servers, sorted by name.

func (*MCPServerStore) Resolve added in v1.801.350

func (s *MCPServerStore) Resolve(ctx context.Context, org, listing, want string) (id string, fresh bool, err error)

Resolve answers what id a registration WOULD get, without writing anything.

It exists because a registration is two writes — the row and the credential — and the credential's KMS ref is keyed on the id. Resolving first lets the seal happen BEFORE the row, which is the only ordering with no undo in it: a failed seal leaves the store exactly as it was, rather than leaving a row asserting a credential that was never stored. (It did leave one. A row with has_secret=1 and nothing in KMS makes every dispatch fail inside listRemote, which mcpProvider skips — so the server's tools SILENTLY vanish from the org's plane with no error anywhere. That is worse than the refusal it should have been.)

want is a PREFERRED id, not a demand. Empty gets a random handle, which is what a hand-registered server has always had. A catalog enablement asks for the vendor's own handle instead, because the id PREFIXES every tool name the server contributes. Taken names are suffixed: two servers from one vendor is a thing an org is allowed to have. Re-enabling a listing the org already has resolves to THAT row's id, so the tool names an agent already learned do not move under it.

func (*MCPServerStore) Write added in v1.801.350

func (s *MCPServerStore) Write(ctx context.Context, srv MCPServer, fresh bool) (MCPServer, error)

Write stores one registration at an id Resolve produced. It is the ONE place a registration comes into being — typed in or enabled off the shelf — and it touches no KMS: by the time it runs, the credential is already sealed.

type Price

type Price struct {
	// Amount is what ONE call costs, EXACTLY: an 18-decimal USD value, so a
	// per-call price of $0.0025 is $0.0025 and not a cent-floored zero. Cents
	// cannot hold a per-token price, and a tool plane is where per-token prices
	// live.
	Amount money.Amount `json:"amount"`
	// Currency is the ISO 4217 code, e.g. "USD". Empty means USD.
	Currency string `json:"currency"`
	// Recipient is the payout wallet ref the marketplace seller is paid at.
	Recipient string `json:"recipient"`
}

Price declares what a monetized tool call costs and who is paid. Enforcement is the x402 Charger seam (registry.go) — this is only the DECLARATION a marketplace listing carries. A nil Price means the tool is free (no x402 settlement).

type Principal

type Principal struct {
	Org     string
	Project string
	User    string
	Owner   string
	IsAdmin bool
}

Principal is the VALIDATED caller a dispatch runs as — resolved once from the request and threaded to every source. It is the IAM-native identity and nothing else: cloud's SanitizeIdentity strips minted authority headers on ingress and re-mints them ONLY from a re-validated credential, so by the time a dispatch sees a Principal the authority question is already settled upstream.

func PrincipalFrom

func PrincipalFrom(c *zip.Ctx) (Principal, bool)

PrincipalFrom resolves the validated caller from a request context. It returns ok=false (the caller must answer 403) unless a validated principal carries a non-empty org — the SAME gate principal.Org enforces.

type Provider

type Provider interface {
	// Source is the provider's source tag (a provider serves exactly one source).
	Source() Source
	// List returns the tools this source offers for scope. It is scope-aware:
	// a connector source lists an org's connected connectors; the external-MCP
	// source lists tools from the org's registered servers.
	List(ctx context.Context, scope Scope) ([]Tool, error)
	// Dispatch invokes the named tool with JSON args, bound to the principal, and
	// returns the JSON-encodable result. A source that only lists (skills) returns
	// ErrNotDispatchable.
	Dispatch(ctx context.Context, p Principal, name string, args map[string]any) (any, error)
}

Provider is one tool SOURCE. It lists the tools it offers to a (org,project) and dispatches a call to one of them bound to the principal. The registry composes providers; it never learns how any single source lists or runs its tools. A source implements this once and calls Register — that is the whole contract.

type Query added in v1.801.350

type Query struct {
	// Text matches the name, title or description, case-insensitively.
	Text string
	// Featured, Official keep only listings with that flag when true.
	Featured, Official bool
	// Hidden includes the hidden listings. Only a SuperAdmin ever passes true —
	// the org-visible view is the same query with it false, so "what an org sees"
	// and "what an admin sees" are ONE query and cannot drift apart.
	Hidden bool
	// Limit bounds the page. Zero or less means catalogPage; more than catalogMax
	// is clamped to it.
	Limit int
	// Offset skips that many rows.
	Offset int
}

Query narrows a catalog listing. The zero value lists everything visible.

type Registry

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

Registry is THE tool plane: the set of registered source Providers, the shared per-(org,project) activation store, and the x402 Charger seam. It composes providers and enforces the ONE dispatch policy (activation gate → price gate → dispatch); it knows nothing about how any source lists or runs a tool.

func Default

func Default() *Registry

Default returns the process-wide registry (for marketplace + the HTTP surface).

func NewRegistry

func NewRegistry() *Registry

NewRegistry builds an empty registry. The process-wide one is std (see Default); tests build their own with fake providers.

func (*Registry) Activate

func (r *Registry) Activate(ctx context.Context, org, project, tool, byUser string) error

Activate turns a tool on for (org, project), recording its resolved source. This is the ONE activation write the marketplace "install" and the /v1/tools/activation API both drive, so activation is one store reached one way.

func (*Registry) Activated

func (r *Registry) Activated(ctx context.Context, org, project string) ([]string, error)

Activated returns the activated tool names for (org, project).

func (*Registry) Deactivate

func (r *Registry) Deactivate(ctx context.Context, org, project, tool string) error

Deactivate turns a tool off for (org, project).

func (*Registry) Dispatch

func (r *Registry) Dispatch(ctx context.Context, p Principal, name string, args map[string]any) (any, error)

Dispatch is the ONE per-principal dispatch path, enforcing the ONE policy:

  1. resolve the winning tool (precedence) — ErrUnknownTool if none.
  2. ACTIVATION gate — the tool MUST be activated for (org,project) or ErrNotActivated (403).
  3. PAYMENT gate — every call is offered to the x402 seam, which owns the price table: a free tool settles for nothing, a priced one settles or the call fails closed (ErrPaymentRequired). With NO rail REACHABLE the seam asks the table instead (charge_peer.go), and only a deployment holding neither reaches ErrChargerUnset, where a tool that DECLARES a price fails closed — a paid tool is never served free.
  4. dispatch to the winning source's provider, bound to the principal.

The scope is the principal's own (org, project) — a caller can only ever dispatch its own tools. Metering + audit are the HTTP layer's job (one unit per call).

func (*Registry) Exists

func (r *Registry) Exists(ctx context.Context, scope Scope, name string) bool

Exists reports whether any source offers a tool by name to scope. Used by the marketplace to refuse a phantom listing/install.

func (*Registry) List

func (r *Registry) List(ctx context.Context, scope Scope) []Tool

List returns every tool offered to scope, deduped by name under source precedence (the lowest-rank source wins a collision), sorted by name. Each tool's Activated flag is filled from the activation store. A provider that errors is skipped (its tools are simply absent) — one failing source never blanks the whole plane.

func (*Registry) Register

func (r *Registry) Register(p Provider)

Register adds a provider. Duplicate sources are allowed (each lists its own tools); precedence resolves any name collision across sources.

func (*Registry) SetActivation

func (r *Registry) SetActivation(a *ActivationStore)

SetActivation installs the activation store (called by tools.Mount once DataDir is known). A nil store fails every dispatch closed (nothing is activated).

func (*Registry) SetCharger

func (r *Registry) SetCharger(c Charger)

SetCharger installs the payment seam.

type Scope

type Scope struct {
	Org     string
	Project string
}

Scope is the (org, project) a listing is resolved for. project == "" or the literal default project both denote the org's default scope.

type Skill added in v1.801.350

type Skill struct {
	// ID is the skill's id within the org. It is DERIVED from Name, so writing
	// the same name again revises that skill rather than adding another.
	ID string `json:"id"`
	// Org is the org that authored the skill — the validated caller's, never a
	// value the body supplied.
	Org string `json:"org"`
	// Name is the skill's name: one lowercase path segment (a-z0-9, _ or -).
	Name string `json:"name"`
	// Description is the one-line summary discovery shows for the skill.
	Description string `json:"description"`
	// Content is the SKILL.md body, markdown.
	Content string `json:"content"`
	// CreatedAt is when the skill was last written, Unix seconds.
	CreatedAt int64 `json:"createdAt"`
}

Skill is one org-authored skill: discovery + activation metadata plus the SKILL.md body. Like the brand's skills it is NOT dispatchable — a skill is attached to an agent, not called.

type SkillStore added in v1.801.350

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

SkillStore is the per-org registry of authored skills (one SQLite file, org column, the shared cloud store discipline). Isolation is a mandatory `WHERE org=?` on every statement; org is the validated principal value.

func OpenSkillStore added in v1.801.350

func OpenSkillStore(dir string) (*SkillStore, error)

OpenSkillStore opens (and migrates) the authored-skill store under dir.

func (*SkillStore) Close added in v1.801.350

func (s *SkillStore) Close() error

Close closes the underlying database.

func (*SkillStore) Delete added in v1.801.350

func (s *SkillStore) Delete(ctx context.Context, org, id string) error

Delete removes one of the org's skills. Deleting what is not there is not an error — the caller's intent is "gone", and it is.

func (*SkillStore) List added in v1.801.350

func (s *SkillStore) List(ctx context.Context, org string) ([]Skill, error)

List returns the org's skills, name-sorted.

func (*SkillStore) Put added in v1.801.350

func (s *SkillStore) Put(ctx context.Context, sk Skill) (Skill, error)

Put inserts or replaces a skill. The id is derived from the name so writing the same name twice REVISES that skill rather than accumulating duplicates that would then collide in the tool registry.

type Source

type Source string

Source names WHERE a tool comes from. It is the ONE dimension precedence and activation-default policy key on, so it is a closed set of values, not free text.

const (
	// SourceConnector is a connector action from clients/automations.
	SourceConnector Source = "connector"
	// SourceFunction is a user-defined function from clients/functions.
	SourceFunction Source = "function"
	// SourceZAPService is a zap-proto service route (tunneled over /zap).
	SourceZAPService Source = "zap-service"
	// SourceAgent is an org agent from clients/agents, callable as a tool.
	SourceAgent Source = "agent"
	// SourceSkill is an agent skill (apps/skills): discovery + activation
	// metadata, attached to agents rather than called directly.
	SourceSkill Source = "skill"
	// SourceMCP is a tool on an org's own registered EXTERNAL MCP server.
	SourceMCP Source = "mcp"
)

type Tool

type Tool struct {
	// Name is the tool's id in the flat, fleet-wide tool namespace — the value a
	// tools/call passes. Unique across sources: a collision is resolved by source
	// precedence before the caller ever sees it.
	Name string `json:"name"`
	// Source is where the tool comes from: connector, function, zap-service,
	// agent, skill or mcp.
	Source Source `json:"source"`
	// Description is the prose a model reads to decide whether to call the tool.
	Description string `json:"description"`
	// Schema is the JSON Schema of the call arguments — the MCP inputSchema.
	// Absent for a tool that takes none.
	Schema json.RawMessage `json:"inputSchema,omitempty"`
	// Price is what a call costs and who is paid, absent for a free tool.
	// Enforcement is the x402 settlement seam; this is the declaration.
	Price *Price `json:"price,omitempty"`
	// Dispatchable is whether the tool can be CALLED. False for a listing-only
	// entry: a skill is activated and attached to an agent, never called.
	Dispatchable bool `json:"dispatchable"`
	// Activated is filled by the registry from the activation store for the
	// requesting (org,project); providers leave it zero. An unactivated tool is
	// discoverable but refused 403 at dispatch.
	Activated bool `json:"activated"`
}

Tool is the ONE description of a callable capability, uniform across sources. Schema is the JSON-Schema of the call arguments (MCP inputSchema); Dispatchable is false for a listing-only entry (a skill is activated + attached, not called).

Jump to

Keyboard shortcuts

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