Capabilities
A capability is a script or small app your team can run safely — from the app, the API, or an AI agent. It has a name and an owner, the JSON Schema of its inputs (which becomes the form people fill in and the input agents send), and versions: every change is a new version, and runs use the one that is published.
The folder: reminix.json + one file
Section titled “The folder: reminix.json + one file”{ "slug": "refund-customer", "name": "Refund a customer", "description": "Refunds an order and notifies the customer.", "entry": "index.ts", "inputSchema": { "type": "object", "required": ["orderId"], "properties": { "orderId": { "type": "string" } } }}// index.ts — the entry; it may import other files and npm packagesimport { refund } from "./payments.ts";
export default async function run(inputs: { orderId: string }, ctx) { ctx.log(`refunding ${inputs.orderId}`); return { refunded: inputs.orderId };}The entry default-exports run(inputs, ctx) and returns JSON.
JavaScript and TypeScript both work. When you publish, the entry and
everything it imports — your other files and npm packages from the
folder’s node_modules (run npm install first) — are bundled into one
module, at most 5 MB. Node built-ins (node:crypto, node:buffer …)
are available as imports.
Calling APIs
Section titled “Calling APIs”By default a capability has no network. To call an API, list its hosts, and the secrets to attach to requests to them:
{ "hosts": ["api.stripe.com"], "secrets": { "STRIPE_KEY": { "host": "api.stripe.com", "header": "Authorization", "value": "Bearer {secret}" } }}export default async function run(inputs, ctx) { // No key in the code: Reminix adds the Authorization header on the way out. const res = await fetch("https://api.stripe.com/v1/refunds", { method: "POST", body: new URLSearchParams({ payment_intent: inputs.paymentId }), }); return await res.json();}- Requests go out only to
hosts, over HTTPS; anything else fails with “Host not allowed”, and every request is in the run’s log. - Each secret is attached only to its
host— and only if the secret itself allows that host (Secrets). The code never holds the value. (An API that echoes your credentials back in its response would reveal them to the code — don’t send secrets to one.) valuedefaults to{secret}; use it for the scheme, e.g."Bearer {secret}".- To read a secret as a plain value (
ctx.env.NAME), list it in"env": ["NAME"]— allowed only for a secret whose owner turned on “Let capabilities read the value itself”.
The capability page shows each version’s hosts and secrets, so whoever publishes sees what it can reach.
Publishing
Section titled “Publishing”reminix capabilities publish ./refund-customer # uploads a draft versionreminix capabilities publish ./refund-customer --publish # …and publishes itThe first publish creates the capability. Drafts change nothing until a version is published — by the capability’s owner, or a workspace owner or admin. An agent’s publish becomes a request a person approves. Publishing an older version again rolls back. See Governance for who can use a capability, runs that need approval, and a second person for publishing.
Through the API, with a key or token holding capabilities:write:
POST /v1/capabilities (create), POST /v1/capabilities/{slug}/versions
(upload { entry, inputSchema, code }), and
POST /v1/capabilities/{slug}/versions/{number}/publish.
Running it
Section titled “Running it”Once published, anyone in the workspace can run it:
- In the app: Capabilities → the capability. Its input schema becomes a form; Run shows the output and the log.
- From the command line:
reminix capabilities run refund-customer --input '{"orderId":"o_123"}'prints the output (--logalso prints the log). - From an agent: through the MCP server, every published
capability is a tool named
run_<slug>(run_refund_customer) taking its inputs. - From the API:
POST /v1/capabilities/{slug}/runs— see Runs.