LoopEngineBETA

Docs

Documentation

How LoopEngine works, from scaffold to durable approvals — agents, adapters, permission rules, and abilities.

Abilities

This page covers what an ability actually is, day to day — its structure, and how to publish/add/remove one. For the full design reference — why copying beats importing, secrets management in the Admin UI, and the open questions — see Ability System instead; this page is the shorter, practical version, and bin/ability-manager.ts is where the mechanics below live in the source tree.

What it is

A loopengine ability is a bundle of tool files, a skill directory, and actauth rules, installed by copying files into an agent's own tree — never as a node_modules import. The three pieces normally get hand-authored separately with nothing tying them together (a tool with no rule is blocked outright by default_decision; a tool with no skill may go unused if its purpose isn't obvious from its description alone); an ability packages all three as one shareable, installable unit instead.

Private vs. public

Nothing in the format below distinguishes the two — the difference is only where you publish and what your tools' own fetch() calls actually point at:

Private Public
Example get_order_onway/get_order_shipments_detail hardcoding one company's own API shape (its specific query params, its specific endpoints) A tool built against a genuinely multi-tenant API — Stripe, Shopify, Zendesk
Reusable by The same company's own agents and environments (staging vs. production, different mailboxes) Any company's agents — the API itself doesn't care whose tenant is calling
Published to A private registry, a scoped @company/pkg, or just a git repo — never intended for a public catalog The public npm registry

Most abilities most companies will ever write are the private kind — internal-reuse bundles like the example above, not something that could be usefully installed by a stranger's agent since nobody else's backend speaks that exact API. A public ability is the narrower case, and it's the only kind a future public catalog/marketplace (not built yet — see Ability System) would ever make sense for; a private ability has no reason to appear in one.

Scope and structure

An ability is a directory, published like any npm package:

my-order-tools/
  package.json                # name, version — an ordinary npm package
  loopengine.ability.json      # the manifest
  tools/
    get_order_onway.ts
    get_order_shipments_detail.ts
  skills/
    order-lookup/
      SKILL.md
  actauth/
    rules.yml
Manifest field Points at Notes
loopengineVersion — A semver range, checked against the installing project's own loopengine dependency before anything is written.
tools File paths Each expected to export const <camelCase>: ToolDefinition — the same shape the Web UI's HTTP tool builder already generates.
skills Directory paths Each a complete SKILL.md (+ any assets alongside it), copied as-is.
actauth One YAML file Rule objects — same name/scope/tool/decision shape as a hand-written actauth.yml.
env — Optional. Every process.env.X the ability's tools actually read, declared once rather than buried per tool file. secret: true means the Admin UI's Environment tab never echoes the value back.

No name/version in the manifest itself — those come from the ability's own sibling package.json, which already has to exist and carry real values for npm pack to treat the directory as fetchable at all. A tool or skill name that collides with one already installed doesn't refuse outright — it installs namespaced under the ability's own name instead (tools/<ability-name>__<name>.ts, skills/<ability-name>/<id>/); an actauth rule name collision does refuse, since two rules can't share one name in the same file.

Publishing

No tooling beyond loopengine.ability.json itself — npm publish from a directory shaped as above is a complete, valid ability. Public registry, a private one (a scoped @company/pkg, GitHub Packages, a self-hosted Verdaccio), or just a tagged commit in a plain git repo with no registry at all — anything npm pack itself accepts. Auth for a private target comes entirely from whatever .npmrc token or SSH key/git-credential helper is already configured in the environment running the command.

Adding

npx loopengine add-ability <spec> --agent <name>

<spec> is resolved exactly like npm pack would — a public/private package name, @company/pkg, github:org/repo#v1.0.0, git+ssh://..., or file:../local-path for testing. Refuses outright, before writing anything, on the first failing check: the version range above, then an actauth rule name collision. Once past those, tool files and skill directories get copied in, tools/index.ts and actauth.yml get patched, and provenance is recorded in agents/<name>/.loopengine-abilities.json — the merge base a future upgrade needs, and what tells the Admin UI which env vars to prompt for.

Upgrading and removing

npx loopengine upgrade-ability <abilityName> --agent <name> [--spec <spec>]
npx loopengine remove-ability <abilityName> --agent <name> [--force]

Upgrading three-way-merges each managed file against what changed upstream since install — a hand-edit survives a clean merge; a real conflict leaves <<<<<<< markers instead of silently overwriting either side. Removing deletes exactly the files provenance recorded, refusing any that look hand-modified beyond what a normal upgrade would have produced, unless --force is passed.