agentleFS
wundercorpwundercorp/loki/plugins/AGENTS.md

loki / plugins

AGENTS.md28 starsChanged 2 months agoMITView on GitHub

Applies on top of the root AGENTS.md. Authoring guide + canonical compat contract: website/docs/developer-guide/plugins/index.md. Per-kind guides: memory-provider-plugin.md, model-provider-plugin.md, context-engine-plugin.md, image-gen-provider-plugin.md, ... Plugins live in their own directory and work within the ABCs / hooks / ctx surface we provide. A plugin MUST NOT modify run_agent.py, cli.py, gateway/run.py, loki_cli/main.py, etc. If it needs a capability the framework lacks, widen the generic plugin surface (new hook, new ctx method) and have the plugin use it — never hardcode plugin-specific logic into core…

The file

We split this AGENTS.md into the rules it gives an agent

2 rules. About 0 are common, 0 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    If it needs a capability the framework lacks, widen the generic plugin surface (new hook, new ctx method) and have the plugin use it — …

    line 11
  2. Very specific:

    Never remove or rename PluginContext methods.

    line 68

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

plugins/ — plugin kinds, compat contract, in-tree policy

Applies on top of the root AGENTS.md. Authoring guide + canonical compat contract: website/docs/developer-guide/plugins/index.md. Per-kind guides: memory-provider-plugin.md, model-provider-plugin.md, context-engine-plugin.md, image-gen-provider-plugin.md, ...

Plugins never touch core (Teknium, May 2026)

Plugins live in their own directory and work within the ABCs / hooks / ctx surface we provide. A plugin MUST NOT modify run_agent.py, cli.py, gateway/run.py, loki_cli/main.py, etc. If it needs a capability the framework lacks, widen the generic plugin surface (new hook, new ctx method) and have the plugin use it — never hardcode plugin-specific logic into core (PR #5295 removed 95 lines of hardcoded honcho argparse from main.py). Plugin setup goes through loki memory setup → provider.post_setup(loki_home, config), never a parallel top-level command. A hook with no concrete consumer is speculative infrastructure and is rejected (root).

What may live in this tree (policy)

  • No new in-tree memory providers (May 2026). plugins/memory/ is closed (honcho, mem0, supermemory, byterover, hindsight, holographic, openviking, retaindb stay; bug fixes welcome). New backends ship as standalone repos implementing the same MemoryProvider ABC, discovered through the same path, integrated via loki memory setup / post_setup().
  • No new third-party-product plugins (June 2026). Observability/metrics backends, vendor SaaS connectors, analytics dashboards, paid-service tie-ins ship as standalone plugin repos (~/.loki/plugins/ or pip entry point) promoted in Discord #plugins-skills-and-skins. Reason: every absorbed product is our maintenance burden against a fast-moving core for a backend we don't own. observability/, kanban/, disk-cleanup/ are precedent, not an invitation. Closing such a PR is a coupling decision, not a quality judgment.
  • Reference/docs-companion plugins (example-dashboard, strike-freedom-cockpit, plugin-llm-example, plugin-llm-async-example) live in loki-example-plugins, not here.

Plugin catalog (plugin-catalog/, Sep 2026)

The ONLY discovery system for out-of-tree plugins. One YAML per entry, 40-hex SHA pin mandatory, human-merged via PR (plugin-catalog/README.md = admission policy; plugin-catalog-ci.yml clones each changed entry at its pin and runs loki plugins validate). removed.yaml is the kill list — every install path (CLI, dashboard, TUI) refuses matches; only the CLI has a loud --allow-removed. Code: loki_cli/plugin_catalog.py (loader, live refresh from /docs/api/plugin-catalog.json published by the docs build, in-tree fallback), loki_cli/plugins_cmd_catalog.py (resolution, .loki-catalog.json provenance sidecar, search/info/validate, re-pin on update, dashboard/TUI payloads). Never add a second name index: bare names resolve through the catalog or error.

Plugin kinds and their discovery systems

KindWhereDiscoveryNotes
Generalplugins/<name>/, ~/.loki/plugins/, ./.loki/plugins/, pip entry pointsPluginManager (loki_cli/plugins.py), later-winsregister(ctx) registers hooks (pre_tool_call, post_tool_call, pre_llm_call, post_llm_call, on_session_start, on_session_end), tools (ctx.register_tool), CLI subcommands (ctx.register_cli_command — argparse tree wired into loki at startup, no main.py change)
Memory providerplugins/memory/<name>/plugins/memory/__init__.py: bundled → $LOKI_HOME/plugins/ → ./.loki/plugins/ (opt-in LOKI_ENABLE_PROJECT_PLUGINS) → loki_agent.memory_providers entry points; bundled-firstActivated by name via memory.provider, so a dropped-in dir must not shadow a shipped one (reverse of general later-wins). Enumerates without importing. Implements MemoryProvider ABC (agent/memory_provider.py), orchestrated by agent/memory_manager.py: sync_turn, prefetch, shutdown, optional post_setup. cli.py with register_cli(subparser) is wired by discover_plugin_cli_commands() — only for the ACTIVE provider, so loki --help stays clean
Model providerplugins/model-providers/<name>/providers/__init__.py._discover_providers(), lazy, on first get_provider_profile()/list_providers(); bundled → $LOKI_HOME/plugins/model-providers/ → legacy providers/<name>.py__init__.py calls providers.register_provider(ProviderProfile(...)) at load; last-writer-wins so a user plugin overrides a bundled profile. PluginManager records kind: model-provider manifests but does NOT import them (would double-instantiate); manifests without kind: are auto-coerced by source heuristic (register_provider + ProviderProfile)
Context engine / image-gen / othersplugins/context_engine/, plugins/image_gen/, ...ABC + orchestrator + per-plugin directoryPlug into agent/context_engine.py, agent/image_gen_provider.py
Platform adaptersplugins/platforms/<name>/adapter.pygatewayToken-lock and scoped-secret rules in gateway/AGENTS.md (irc, feishu are canonical)

Discovery timing pitfall: discover_plugins() runs only as a side effect of importing model_tools.py. Code that reads plugin state without importing model_tools.py first must call discover_plugins() explicitly (idempotent). Hooks are invoked from model_tools.py (pre/post tool) and run_agent.py (lifecycle). When a plugin changes a default, add a migration guard keyed on an "existing config" signal (_explicitly_configured) so existing users keep the old default.

Native plugin compatibility contract (summary — canonical text in the docs page)

Compatibility is a behavior contract, not a monolithic PLUGIN_API_VERSION, a manifest-wide native api: match, or version literals on unrelated payloads. Documented surfaces stay additive:

  • Hook payload data is added as keyword fields; callbacks are signature-inspected so old narrow signatures receive only the fields they declare and **kwargs callbacks get the full payload.
  • Never remove or rename PluginContext methods; new parameters are optional with defaults and keyword-only where possible.
  • Unknown native manifest fields are ignored.
  • New provider methods get default implementations; optional callback kwargs are signature-inspected, not forwarded unconditionally.
  • A local schema version exists only for a capability with a wire or persisted contract, and old state/config/session replay is preserved or migrated.
  • Deprecations: once-per-process warning, documented replacement + migration note, ≥ 2 subsequent minor releases before removal.
  • Compat tests load frozen plugins through the real discovery path and assert outcomes — never exact registry/catalog counts, source-reading tests, or "a global version literal changed".

Sep 2026 decomposition compat window (ends 2026-09-14)

PR #102117 moved internals into <stem>_<topic> siblings. Old import paths resolve through PLUGIN-COMPAT __getattr__ blocks (listed in COMPAT_MANIFEST.md / compat_manifest.json) until loki_cli.plugin_compat.COMPAT_REMOVAL_DATE, when the commit that added them is reverted. loki_cli/plugin_compat.py is the single source: scan_plugin (AST scan), compat_report (hits across enabled external plugins, cached to LOKI_HOME/.plugin-compat-report.json, refreshed by discovery), removal_in_effect, warn_once. Surfaces: CLI banner notice, loki plugins compat (shows affected user plugins), loki doctor, post-update notices, the TUI/Desktop plugins.compat_report RPC. After the date PluginManager skips a hitting plugin unless plugins.allow_deprecated_imports: true. In-tree code and tests never use compat paths (scripts/check_compat_pointers.py in CI; -W error::loki_cli.plugin_compat.LokiPluginCompatWarning). External-plugin compat is handled ONCE here — never add per-PR re-export shims.

Tests

tests/plugins/. Load through real discovery with a temp LOKI_HOME; assert behaviour (tool registered, hook fired with expected kwargs), not counts. Opt-in telemetry rule applies to plugins too: no attribution tag ships by default (tests/plugins/memory/test_hindsight_provider.py).

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.