Remote Skills
API reference
SDK constructors, parameters, return values, data types, and errors.
Reference for @remote-skills/client, Python's remote_skills, the Vercel AI SDK integration, the Mastra integration, the TanStack AI integration, and the LangChain and DeepAgents integration. Method tables show awaited return values: TypeScript methods return promises, and Python async methods are awaited. For a runnable integration, see Consume skills.
Client creation
createRemoteSkills(config, dependencies?) returns a RemoteSkillsClient.
import { createRemoteSkills } from "@remote-skills/client";
const client = createRemoteSkills({
origins: {
team: { url: "https://skills.example.com" },
},
});RemoteSkillsConfig fields:
| Field | Type | Default | Description |
|---|---|---|---|
origins | OriginMap | Required | Map of local aliases to origin settings. At least one origin. |
defaults | CatalogDefaults | Built-in defaults | Shared timeoutMs, retries, and catalogBytes. Per-origin values take precedence. |
cache | CacheSelection | "disk" | "disk", "memory", or a custom CacheBackend. |
cacheOptions | DiskCacheOptions or MemoryCacheOptions | Backend defaults | Options for the selected built-in cache. |
limits | ActivationLimits | Defaults below | Per-skill download and extraction limits. |
The optional second argument, RemoteSkillsDependencies, supplies transport, resolution, timing, and session-nonce hooks. Normal use needs only config.
Origin settings
All fields except url are optional. Origins use HTTPS; URL credentials, query strings, and fragments are rejected. Discovery uses the host-root /.well-known/agent-skills/index.json, regardless of a path in url.
Each origins entry is an OriginConfig.
| Field | Type and default | Description |
|---|---|---|
url | string or URLRequired | Host base URL. |
headers | String-to-string map Default: {} | Headers for requests to this host. |
artifactHeaders | Host-to-header-map Default: {} | Separate headers for exact artifact hosts, including ports when present. |
scope | string Default: unset | Requested catalog view; see scoped catalogs. |
timeoutMs | integer Default: 30000 | Request timeout in milliseconds; 1–300000. |
retries | integer Default: 2 | Retry count; 0–10. |
catalogBytes | integer Default: 1048576 | Maximum catalog bytes; 1–52428800. |
stale | StaleCatalogConfigDefault: disabled | { maxAgeMs: number } enables age-bounded stale-catalog fallback for new sessions. |
allowLoopbackHttp | boolean Default: false | Allows HTTP for explicitly configured loopback development. |
networkPolicy | NetworkPolicyConfigDefaults below | Address exceptions and redirect limit. |
Network policy
| TypeScript field | Python argument | Default and accepted value |
|---|---|---|
networkPolicy.allowedAddresses | NetworkPolicy(allowed_addresses=...) | Empty collection. Exact IP address exceptions, not hostnames or CIDR ranges. |
networkPolicy.maxRedirects | NetworkPolicy(max_redirects=...) | 5; integer from 0 to 5. |
Address checks apply to each connection and redirect. Trust and security explains the policy; Authentication and authorization covers credential handling.
Client methods
catalog
| Language | Signature | Resolves to |
|---|---|---|
| TypeScript | client.catalog(options?: CatalogOptions) | AggregateCatalog |
| Python | await client.catalog(strict=False) | AggregateCatalog |
| Parameter | Default | Behavior |
|---|---|---|
options.strict / strict | false / False | When enabled, any origin failure throws an aggregate error instead of returning partial results. |
The result contains entries and failures. Each failure includes originAlias (TypeScript) or origin_alias (Python) and error. Strict-mode exceptions are CatalogAggregateError in TypeScript and AggregateCatalogError in Python, both exposing failures.
session
| Language | Signature | Resolves to |
|---|---|---|
| TypeScript | client.session(originAlias: string) | RemoteSkillsSession |
| Python | client.session(origin_alias, stale=None) | RemoteSkillsSession when awaited; also supports async with. |
| Parameter | Default | Behavior |
|---|---|---|
originAlias / origin_alias | Required | Alias from the client's configured origins, not a URL. |
Python stale | None | StaleCatalog(max_age_seconds=...) permits a verified cached catalog within that age bound. |
TypeScript configures stale fallback through OriginConfig.stale.maxAgeMs. Both default to requiring an online catalog unless an acceptable fresh cached catalog is available. See Caching and updates for fallback conditions.
refresh
| Language | Signature | Resolves to |
|---|---|---|
| TypeScript | client.refresh(originAlias?: string) | void |
| Python | await client.refresh(origin_alias=None) | None |
Revalidates the selected origin's catalog, or all configured origins when omitted. Affects future sessions only; existing sessions and their selected skills stay unchanged.
Session methods
catalog
| Language | Signature | Resolves to |
|---|---|---|
| TypeScript | session.catalog() | readonly CatalogEntry[] |
| Python | await session.catalog() | tuple[CatalogEntry, ...] |
Returns the session's fixed catalog snapshot without loading skill instructions.
activate
| Language | Signature | Resolves to |
|---|---|---|
| TypeScript | session.activate(name: string, requestedRange?: string) | ActivatedSessionSkill |
| Python | await session.activate(skill_name, version_range=None) | ActivatedSkill |
| Parameter | Default | Behavior |
|---|---|---|
name / skill_name | Required | Skill name from the catalog. |
requestedRange / version_range | No restriction | Selects the highest advertised release matching the range; prereleases require explicit inclusion. An unversioned current skill is allowed only without a restriction or with *. |
Downloads and verifies the complete artifact, then pins the chosen bytes for the session. Later activation calls for the same skill return that pinned selection, even if a different range is passed. Range syntax and prerelease rules are in Versions and history.
close
| Language | Signature | Resolves to |
|---|---|---|
| TypeScript | session.close() | void |
| Python | await session.close() | None |
Releases the session's cache pins. Further catalog, activation, and resource operations fail with session_closed. TypeScript also supports async disposal; Python's async with closes the session automatically.
Session metadata
| TypeScript | Python | Meaning |
|---|---|---|
metadata.originAlias | metadata.origin_alias | Configured origin alias. |
metadata.confirmedScope | metadata.confirmed_scope | Host-confirmed scope, if any. |
metadata.requestedScope | — | Requested scope, if configured. |
metadata.stale, stale | metadata.stale, stale | Whether stale-catalog fallback was used. |
metadata.staleAgeMs, staleAgeMs | metadata.catalog_age_seconds | Catalog age for stale fallback, in milliseconds or seconds respectively. |
| — | closed | Whether the Python session is closed. |
Returned data
Catalog entries
| TypeScript | Python | Type and meaning |
|---|---|---|
originAlias | origin_alias | String; configured origin alias. |
name, description | name, description | Strings; discovery metadata. |
artifactType | artifact_type | "skill-md" or "archive". |
url, digest | url, digest | Strings; resolved artifact URL and SHA-256 digest. |
version | version | String when versioned; otherwise absent or None. |
releases | releases | Advertised release descriptors, when provided. Each has version, artifact type, URL, and digest. |
Activated data
| TypeScript | Python | Type and meaning |
|---|---|---|
name, description | name, description | Strings; selected skill metadata. |
instructions | instructions | String; Markdown instructions from SKILL.md. |
frontmatter | frontmatter | Read-only mapping of parsed skill metadata. |
version, digest | version, digest | Selected version, if any, and the exact pinned digest. |
originAlias | origin_alias | Configured origin alias. |
confirmedScope | confirmed_scope | Confirmed catalog scope, if any. |
descriptor | pin | Selected artifact descriptor (TypeScript) or activation identity (Python). |
descriptor.artifactType, descriptor.url | artifact_type, url | Selected artifact format and URL. |
| — | stale | Whether the Python activation came from a stale catalog. |
Resource methods
TypeScript methods return promises. Python methods are awaited. All reads use already verified local files; they do not make additional network requests or execute scripts.
| TypeScript | Python | Resolves to |
|---|---|---|
skill.list(prefix?: string) | await skill.list(prefix=None) | Array or tuple of resource metadata. |
skill.read(path: string) | await skill.read(path) | UTF-8 text string. |
skill.readBytes(path: string) | await skill.read_bytes(path) | Uint8Array or bytes. |
| Parameter | Accepted value |
|---|---|
prefix | Optional resource path or directory prefix. Omitted means all resources; a non-empty prefix with no matches returns resource_not_found. |
path | Required skill-relative file path, such as references/welcome.md. |
Each listed resource has path, size (bytes), and media_type. Listings describe files; they do not include file contents or grant permission to use them.
Activation limits
Configured through limits in TypeScript or ActivationLimits(...) passed as Python's limits argument. Values are positive integers; byte limits are measured before text decoding.
| TypeScript | Python | Default | Limit |
|---|---|---|---|
archiveBytes | archive_bytes | 52428800 (50 MiB) | Compressed artifact download. |
extractedBytes | extracted_bytes | 104857600 (100 MiB) | Total extracted bytes per skill. |
files | files | 1000 | Files per skill. |
fileBytes | file_bytes | 10485760 (10 MiB) | Individual file, including standalone Markdown skills. |
Catalog size is controlled separately by the origin's catalog-byte limit.
Scoped catalogs
| Contract | Value |
|---|---|
| Request header | Remote-Skills-Scope: <name>, on catalog requests. |
| Portable name | Non-secret ASCII, 1–128 bytes, without whitespace, control characters, or commas; accepted by both SDKs. |
| Successful response | Exactly one matching Remote-Skills-Scope header on 200 and 304. |
| Invalid confirmation | Missing, duplicate, or mismatched confirmation returns catalog_invalid. |
| Artifact requests | The scope header is not automatically included and is not an access credential. |
The provider authorizes catalog views and artifact downloads using the caller's identity. Authentication and authorization covers both sides of this contract.
Catalog version history
Optional wire extension for version selection; Versions and history covers authoring and publishing.
| Field or rule | Contract |
|---|---|
| Skill version | metadata.version in SKILL.md. |
| Catalog extension | x-remote-skills, with advertised releases for each versioned skill. |
| Release descriptor | Version, artifact type, URL, and digest. |
| History limit | 100 release descriptors per skill, including the current release. |
| Current release | Its descriptor agrees with the ordinary catalog entry. |
| Build input | Older releases are carried forward only from verified prior output. |
| Other discovery clients | Can ignore the extension and load the current release. |
Vercel AI SDK integration
remoteSkills(options: RemoteSkillsOptions): Promise<RemoteSkillsIntegration> is exported by @remote-skills/ai-sdk. For installation and a complete agent example, see Vercel AI SDK.
Source options
Exactly one source form is accepted:
| Form | Type | Behavior |
|---|---|---|
{ client, origin } | RemoteSkillsClient, string | Opens one session for a configured origin alias. |
{ client, origins } | RemoteSkillsClient, readonly string[] | Opens one session per alias. The list must be non-empty and contain no duplicates. All origins must open successfully. |
{ session } | RemoteSkillsSession | Uses a caller-owned session without taking ownership of it. |
Every form also accepts:
| Option | Type | Default | Behavior |
|---|---|---|---|
versions | Readonly<Record<string, string>> | Unset | Application-selected version constraints, passed to SDK activation. Keys name catalog skills: howdy for one origin, or team/howdy when multiple origins are opened. Unknown skill keys or empty constraints fail setup. |
Creation discovers metadata without activating skills. Authentication, scopes, cache, transport, timeouts, and limits come from the supplied client or session. If setup fails, sessions opened by the integration are closed; a caller-owned session stays open.
Returned integration
| Member | Type | Contract |
|---|---|---|
agentOptions | { instructions: string; tools: RemoteSkillsTools } | Settings to spread into ToolLoopAgent, generateText, or streamText. Does not configure a model or stop condition. |
tools | RemoteSkillsTools | The same skill and readFile tools exposed by agentOptions. |
sessions | readonly RemoteSkillsSession[] | Underlying sessions for catalog access and activation, with staleness and confirmed-scope metadata. |
sandbox | Sandbox from bash-tool | Read-only, remote-backed filesystem rooted at /workspace/skills/. Command execution and writes are unsupported. |
close() | Promise<void> | Disables tools, waits for pending operations, closes owned sessions, and removes temporary files. Safe to call repeatedly. Does not close a caller-owned session or clear the SDK cache. |
[Symbol.asyncDispose]() | Promise<void> | Same cleanup as close(); supports await using. |
The package also exports the types RemoteSkillsOptions, RemoteSkillsIntegration, and RemoteSkillsTools.
Model-facing tools
| Tool | Input | Result |
|---|---|---|
skill | { skillName: string } | Vercel's skill-loader result, including instructions and resource paths on success. Downloads and verifies the selected skill through the SDK before returning its instructions. |
readFile | Vercel's file-reader input, including path | UTF-8 file content from the verified skill. Binary reads return resource_not_text; binary access remains available through SDK sessions. |
Tool errors retain SDK error codes without diagnostic context. Unexpected tool failures return a fixed message; setup errors remain available to the application. Abort signals are checked around tool operations, but an already-started SDK download follows the client's timeout and session-close behavior rather than per-call cancellation.
LangChain integration
@remote-skills/langchain and Python's remote_skills_langchain connect an SDK session to native skills and filesystem middleware. For installation, model setup, and complete examples in both languages, see LangChain and DeepAgents.
LangChain source options
| Language | Signature | Awaited result |
|---|---|---|
| TypeScript | remoteSkills(options: RemoteSkillsOptions) | RemoteSkillsIntegration |
| Python | create_remote_skills_backend(session, *, root="/skills/", versions=None) | RemoteSkillsBackend |
| TypeScript option | Python argument | Default | Contract |
|---|---|---|---|
session | session | Required | One caller-owned SDK session. Neither adapter closes it. |
root | root | "/skills/" | Absolute virtual directory ending in /; each segment contains only ASCII letters, digits, _, or -. It is not a host filesystem path. |
versions | versions | Unset / None | Mapping of catalog skill names to nonempty version ranges. Unknown names or empty ranges fail setup. |
The TypeScript versions type is Readonly<Record<string, string>>; Python accepts Mapping[str, str]. Authentication, scopes, caching, request limits, and verification come from the supplied session's client. See origin settings. Invalid adapter options raise RemoteSkillsError with configuration_invalid in TypeScript, or ValueError in Python.
Version ranges restrict SDK activation to releases still advertised by the publisher. The first activation pins a release for the session; later adapter options cannot replace that pin. Use one version policy per session. Versions and history explains selection and retention.
LangChain returned adapter
| TypeScript member | Python member | Contract |
|---|---|---|
discoveryBackend | discovery | Native backend view of catalog-derived frontmatter. Used only for discovery; this projection is metadata, not the original SKILL.md. |
contentBackend | content | Native backend view of original verified files. The first content read or listing within a skill activates its complete artifact through the SDK. |
sources | sources | One configured virtual root: a string array in TypeScript, a tuple in Python. |
catalog | catalog | Read-only catalog metadata. TypeScript entries have name, description, and virtual path; Python entries have name, description, digest, and version. |
middleware | middleware() | Native skills middleware followed by native filesystem middleware. Python creates a new middleware list per call. |
deepAgentOptions | deep_agent_options() | Native backend, skills, and middleware settings to pass together to a DeepAgents constructor. |
close() | — | TypeScript disables the adapter and waits for its pending work. Repeated calls are safe; the borrowed session remains open. |
[Symbol.asyncDispose]() | — | Same TypeScript cleanup as close(); supports await using. Python cleanup belongs to the SDK session's async with. |
Discovery and root listings download no artifacts. Content reads activate and verify the complete artifact once; subsequent reads reuse those bytes. Native read_file retains text pagination and line numbering. Binary resources remain available through the content backend and SDK resource methods.
LangChain composition
| Agent | TypeScript | Python |
|---|---|---|
| DeepAgents | createDeepAgent({ model, ...remote.deepAgentOptions }) | create_deep_agent(model=model, **source.deep_agent_options()) |
| Plain LangChain | createAgent({ model, middleware: remote.middleware }) | create_agent(model=model, middleware=source.middleware()) |
| LangGraph | Add the native agent's compiled .graph as a subgraph node. | Add the native agent itself as a subgraph node. |
Keep DeepAgents' returned backend, skills, and middleware together. They connect discovery to metadata and file reads to verified content, including in the default general-purpose subagent. Using only the content backend with automatic skills loading downloads artifacts during discovery; using only middleware leaves the default subagent without its catalog. For custom named subagents, pass the same native middleware through their middleware option so they share the SDK session and its pins.
LangGraph support requires a native agent subgraph. Arbitrary raw model or tool nodes do not run LangChain middleware; there is no standalone middleware runtime supplied by this integration. The guide's LangGraph example shows the complete node composition.
LangChain lifetime and runtime
| Concern | Required behavior |
|---|---|
| Invocation | Keep the SDK session open until the native invocation finishes. Close the TypeScript adapter before closing its session. |
| Streaming | Consume the full stream before closing the adapter or session. |
| Python execution | Use ainvoke, astream, or astream_events on the event loop that created the adapter. Synchronous backend reads are unsupported. |
| Conversations and checkpoints | Bind one adapter, native agent, and checkpoint thread to one session, origin, and authorization context. Start a new adapter and checkpoint thread when that context changes. |
| Multiple origins | Use separate adapters and agents. Concatenating native middleware tuples creates duplicate middleware names. |
| TypeScript dependencies | Keep one shared copy of the LangChain peer dependencies and use the compatibility ranges in the adapter's package metadata. |
| TypeScript compiler | The currently supported DeepAgents declarations require skipLibCheck: true because of an upstream Zod declaration mismatch. Keep strict: true for application type checking. |
The native filesystem middleware exposes only ls and read_file. The adapter supplies no write, search, or command-execution tool and disables filesystem offloading because its content is read-only. It does not install files into an agent workspace. Digest verification establishes byte integrity; your application still controls content trust and tool authorization, including any tools a skill requests through allowed-tools.
Mastra integration
remoteSkills(options: RemoteSkillsOptions): Promise<RemoteSkillsIntegration> is exported by @remote-skills/mastra. For installation and a complete agent example, see the Mastra guide.
Mastra source options
Exactly one source form is accepted:
| Form | Type | Behavior |
|---|---|---|
{ client, origin } | RemoteSkillsClient, string | Opens a session for one configured origin alias and owns its lifetime. |
{ session } | RemoteSkillsSession | Uses a caller-owned session without taking ownership of it. |
Both forms also accept:
| Option | Type | Default | Behavior |
|---|---|---|---|
versions | Readonly<Record<string, string>> | Unset | Skill names mapped to SDK version constraints. Unknown names or empty constraints fail setup. Existing session pins remain authoritative. |
instructions | string | "Help the user using relevant skills." | Your agent's instructions, followed by guidance for skill selection, required reference reads, and named search. |
hooks | ToolHooks from @mastra/core/tools | Unset | Your tool hooks, composed with the required skill-loading hooks. |
Creation discovers catalog metadata without downloading skill contents. Authentication, scopes, cache policy, transport, timeouts, and limits come from the supplied client or session. One integration binds one origin and one credential context. If setup fails, a session opened by the integration is closed; a caller-owned session stays open.
Mastra integration members
| Member | Type | Contract |
|---|---|---|
agentOptions | { workspace: Workspace; hooks: ToolHooks; instructions: string } | Settings to spread into a Mastra Agent. Provides a skills-only Workspace, composed hooks, and skill guidance; does not configure a model or step limit. |
session | RemoteSkillsSession | Underlying session, including catalog access, selected versions, and confirmed-scope metadata. |
close() | Promise<void> | Disables new operations, waits for in-flight native skill calls and their hooks, destroys the Workspace, and closes an owned session. Safe to call repeatedly. Leaves a caller-owned session and the SDK cache intact. |
[Symbol.asyncDispose]() | Promise<void> | Same cleanup as close(); supports await using. |
The package also exports the types RemoteSkillsOptions and RemoteSkillsIntegration. Consume response streams before closing the integration. When reusing a caller-owned session, close the integration first, then close the session when your application has finished using it.
Mastra native tools
These are Mastra's existing Workspace tools, with native schemas and result formatting. The integration loads and verifies selected content before the native tool runs.
| Tool | Required input | Behavior |
|---|---|---|
skill | name: string | Loads the named skill's instructions and pins its verified contents for the session. |
skill_read | skillName: string, path: string | Reads a skill-relative UTF-8 file. Loads the skill first if necessary. Binary content fails with resource_not_text; byte access is available through the SDK. |
skill_search | query: string, skillNames: string[] | Searches text in explicitly named catalog skills, loading only those skills as needed. Both the query and skill list must be nonempty. |
Mastra composition
Pass your hooks through the hooks option. Your before hook runs before activation and can deny a call with { proceed: false }. Your after hook runs after the native tool; Mastra does not invoke it when a before hook fails or denies the call.
Retain the supplied Workspace, hooks, and instructions on the agent. Replacing hooks at construction or execution, renaming native skill tools, or calling the raw Workspace loader bypasses the required loading path. Reserve skill, skill_read, and skill_search for the native tools and avoid same-named skills from other sources.
The integration creates its own skills-only Workspace; it does not merge an existing Workspace, add filesystem or sandbox tools, or index the whole remote catalog. It runs in Node.js on the server. For skill selection and reading within an application, use the Agent tool path shown in the guide.
TanStack AI integration
remoteSkills(options: RemoteSkillsOptions): Promise<RemoteSkillSource> from @remote-skills/tanstack-ai returns a native TanStack SkillSource. Pass it to withSkills(skillSource) for catalog discovery and the automatically registered load_skill tool. Optionally add createResourceTool(skillSource) to read supporting files with read_skill_resource; omit that tool for skills that need only their SKILL.md instructions. Both loaders return content through ordinary tool calls and results. See the TanStack guide for setup.
| Option | Behavior |
|---|---|
{ client, origin } | Opens and owns one SDK session for the configured origin alias. |
{ session } | Borrows an existing SDK session; the caller retains ownership. Mutually exclusive with client and origin. |
versions | Optional skill-name-to-version-range mapping. Unknown names and empty ranges fail setup. Existing session pins remain authoritative. |
| Member | Awaited result and behavior |
|---|---|
list() | Fresh array of { name, description } from the session catalog; no instruction downloads. |
load(name) | Verified raw SKILL.md including frontmatter. TanStack strips frontmatter for its native tool result. |
listResources(name) | Verified paths under references/ and assets/; activates the selected skill if needed. |
readResource(name, path) | UTF-8 text or Uint8Array; TanStack encodes binary tool results as base64. Unsafe paths fail closed. |
session | The underlying SDK session. |
close() / [Symbol.asyncDispose]() | Drains outstanding source operations, closes owned sessions, and rejects subsequent source calls. Borrowed sessions remain caller-owned. |
Keep one source per conversation and keep it open until the response completes. Pins survive client.refresh(); later sessions can select newer artifacts. TanStack tracks loaded skills per chat() call. The source does not implement revision keys or script methods, execute content, or add host instructions. SDK error codes are preserved with diagnostic context removed. The exact supported TanStack version is declared in the package peer dependencies; the lockfile pins tested development versions.
Request failures
| Setting or condition | Behavior |
|---|---|
| Default timeout | 30 seconds per request. |
| Default retries | Up to two retries for eligible catalog and artifact GET failures. |
| Retryable HTTP status | 408, 429, and 5xx. |
| Invalid schema, policy, digest, or archive | No retry. Clients fail closed rather than returning unchecked content. |
Stable error codes
| Code | Meaning |
|---|---|
configuration_invalid | Invalid client, origin, or option configuration. |
origin_unavailable | The origin could not provide a usable response. |
request_timeout | Request exceeded its timeout. |
catalog_invalid | Catalog content or scope confirmation is invalid. |
unsupported_schema | Discovery schema is missing or unsupported. |
authentication_failed | Credentials are missing, invalid, or expired (401). |
authorization_denied | The caller lacks access (403). |
skill_not_found | The selected catalog does not contain that skill. |
version_unavailable | No advertised release matches the requested range. |
artifact_unsupported | Unsupported artifact type or encoding. |
digest_mismatch | Downloaded bytes do not match the advertised digest. |
archive_unsafe | Archive structure or entries failed safety checks. |
limit_exceeded | Configured size or file-count limit exceeded. |
resource_not_found | No matching resource exists. |
resource_not_text | Resource cannot be decoded as UTF-8 text. |
path_invalid | Resource path is invalid or escapes the skill. |
policy_denied | URL, address, or redirect rejected by network policy. |
session_closed | Operation attempted after the session closed. |
cache_corrupt | Cached data or cache coordination is invalid. |
SDK errors expose code, retryable, and sanitized context. Catalog and request errors use RemoteSkillsError in TypeScript and CatalogError in Python; cache operations can also raise CacheConfigurationError or CacheCorruptError. Diagnostics exclude credentials, response bodies, instructions, and resource contents; URL context is sanitized.