Contributing to teleton-plugins
July 11, 2026 · View on GitHub
This repository accepts plugins that comply with the Teleton SDK v2 capability model. A plugin is not marketplace-ready merely because its JavaScript imports successfully: its manifest, tool contract, dependency tree and security boundaries must all pass the repository validators.
Requirements
- Node
^22.22.2,^24.15.0, or>=26.0.0. - ESM JavaScript only.
index.js,manifest.jsonandREADME.mdin each plugin directory.package-lock.jsonwheneverpackage.jsonexists.- Strict semver versions.
scopeandcategoryon every tool.- Public SDK capabilities only.
Supported plugin structure
plugins/my-plugin/
├── index.js
├── manifest.json
├── README.md
├── package.json # optional
└── package-lock.json # required with package.json
Runtime manifest
SDK plugins must export a runtime manifest from index.js:
export const manifest = {
name: "my-plugin",
version: "1.0.0",
sdkVersion: "^2.0.0",
description: "One concise sentence",
defaultConfig: {},
secrets: {
api_key: {
required: false,
description: "API key for the upstream service",
},
},
};
The runtime and disk manifests must declare the same version and SDK range. A plugin that does not
use the SDK may omit sdkVersion in both places.
Marketplace manifest
{
"id": "my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"description": "One concise sentence",
"author": { "name": "author", "url": "https://github.com/author" },
"license": "MIT",
"entry": "index.js",
"teleton": ">=0.9.0",
"sdkVersion": "^2.0.0",
"tools": [
{ "name": "my_plugin_lookup", "description": "Look up an item" }
],
"permissions": [],
"tags": ["utility"]
}
The directory name, manifest id, runtime manifest name, compatibility entry and registry ID must
match.
Tool contract
export const tools = (sdk) => [
{
name: "my_plugin_lookup",
description: "Look up an item without changing external state",
scope: "always",
category: "data-bearing",
parameters: {
type: "object",
properties: {
query: { type: "string", description: "Item to look up" },
},
required: ["query"],
},
async execute(params) {
try {
const response = await fetch(
`https://api.example.com/items?q=${encodeURIComponent(params.query)}`,
{ signal: AbortSignal.timeout(15_000) }
);
if (!response.ok) return { success: false, error: `Upstream returned ${response.status}` };
return { success: true, data: await response.json() };
} catch (error) {
return { success: false, error: String(error?.message ?? error).slice(0, 500) };
}
},
},
];
Rules:
- Tool names match
^[a-z][a-z0-9_]{0,63}$and are globally unique. scopeis one of the SDK v2 values:open,always,dm-only,group-only,admin-only,allowlist, ordisabled.categoryisdata-bearingfor reads oractionfor side effects.- Parameters use JSON Schema and bound arrays, strings, amounts and result counts.
- Network calls use explicit timeouts and bounded response handling.
- Returned errors are concise and do not include credentials or large upstream bodies.
- Actions must remain safe under retry and require Teleton's explicit approval flow.
SDK v2 boundaries
Use only APIs declared by @teleton-agent/sdk@^2. The canonical reference is the
SDK package README.
Forbidden:
sdk.telegram.getRawClient();context.bridge,ctx.bridge, or private bridge/client traversal;- direct imports of Teleton's private runtime modules;
- direct reads of
wallet.json, wallet mnemonics or authentication stores; - arbitrary filesystem access to Teleton state;
- secrets from global environment variables.
Use instead:
sdk.telegramfor supported Telegram operations;sdk.tonfor supported wallet and TON operations;sdk.secretsfor declared credentials;sdk.storageor the isolatedsdk.dbfor state;sdk.pluginConfigfor plugin-specific configuration;sdk.logfor structured logs.
If the public SDK lacks a required capability, do not bypass it. Mark the plugin quarantined in
compatibility.json and keep it out of registry.json until a safe capability exists.
Lifecycle
Optional exports are migrate, start, stop, onMessage, and onCallbackQuery.
migrate(db)receives only the plugin's isolated database.start(ctx)receivessdk, isolateddb, sanitizedconfig,pluginConfig, andlog.- Raw bridge access is not available.
- Cleanup timers and resources in
stop().
Secrets
Declare secrets in the runtime manifest and read them through sdk.secrets:
const token = sdk.secrets.get("api_key");
if (!token) return { success: false, error: "API key is not configured" };
Never commit credentials, log them, include them in tool results, or read unrelated process environment variables.
Dependencies
Plugin dependencies are installed with lifecycle scripts disabled:
npm ci --ignore-scripts --no-audit --no-fund
Commit the generated lockfile. HIGH or CRITICAL audit findings block CI, including for quarantined plugins retained in the repository.
Compatibility and registry policy
Every plugin has exactly one entry in compatibility.json:
supported: validated against SDK v2;quarantined: preserved but deliberately incompatible with SDK v2;marketplace: true: allowed only for supported production plugins.
registry.json is the generated installable marketplace, not an archive. Examples and quarantined
plugins do not belong there. Never edit it or the generated README catalog sections manually; after
changing a manifest or compatibility.json, run:
npm run generate
Required local checks
With teleton-agent checked out as ../teleton-agent:
npm ci --ignore-scripts
npm run install:plugins
npm run validate
npm test
npm --prefix ../teleton-agent run build:sdk
npm run validate:runtime
npm run audit:plugins
CI repeats these checks using the current teleton-agent dev branch on Node 22 and Node 24.
Pull request checklist
- Plugin ID and tool names are globally unique.
- Runtime and disk manifests agree.
- Every tool has a valid scope, category and bounded schema.
- No raw Telegram client, bridge, wallet file or mnemonic access.
- Secrets are declared and use
sdk.secrets. - Dependency lockfile is committed and audit is clean.
- README documents configuration, tools and side effects.
-
compatibility.jsonis updated. -
npm run generateupdated the generated registry and README sections. - All required local checks pass.