PAIPAI

defineCapability()

Named typed requirement tools declare and createPai binds.

A capability is a declaration. The common one is sandbox: tools say capabilities: { sandbox }, and createPai binds sandboxCapability().

import { defineCapability } from "@pai/core";

export const sandbox = defineCapability<Sandbox>()({
  id: "sandbox",
  description: "Command and filesystem execution environment.",
});

Apps almost never call this. They use @pai/sandbox.

Import

import { defineCapability } from "@pai/core";

Signature

function defineCapability<TFacade>(): <const TId extends string>(input: {
  id: TId;
  description?: string;
}) => Capability<TFacade, TId>;

Parameters

The inner factory:

input: { id: TId; description?: string }

id: string

Binding key in createPai / createAgentRuntime.

description?: string

Returns

A Capability<TFacade, TId>.

Token tools declare; bind a facade at createPai.

CapabilityScope

A binding's scope decides which operations share one instance. Core derives an opaque instance key from it; the binding maps keys to resources. Capability packages such as sandboxCapability() take it as an option, and createCapabilityBinding({ scope }) defaults to "thread".

type CapabilityScope =
  | "thread"
  | "rootThread"
  | "user"
  | "scope"
  | "global"
  | ((input: CapabilityScopeInput) => string);
ScopeOne instance perDisposed on thread delete
"thread"thread; a subagent's child thread gets its ownwhen that thread is deleted
"rootThread"top-level thread, shared by every thread delegated from it at any depthwhen the top-level thread is deleted; deleting a delegated thread does not
"user"scopeKey + userKeynever
"scope"scopeKeynever
"global"provider keyspacenever

PAI finds a thread's root by following its stored parentThreadId. The walk only runs for "rootThread" and custom scopes.

CapabilityScopeInput

A custom scope function receives:

threadId: ThreadId

Thread the operation runs in. For a subagent, its child thread.

rootThreadId: ThreadId

Top-level thread reached by following parentThreadId. Equals threadId for a top-level thread.

scopeKey: ScopeKey

userKey?: UserKey

identity: unknown

The app identity; narrow it yourself.

// One instance per user per top-level conversation, shared with subagents.
scope: ({ scopeKey, userKey, rootThreadId }) =>
  JSON.stringify([scopeKey, userKey, rootThreadId]),

Learn more

On this page