Plugins
Agent Runtimes is extended — and extends other hosts — through the Datalayer reactor plugin platform, on both tiers. A plugin declares what it contributes; the host discovers it and never names it.
In the browser
The Loop Web workspace is built entirely from reactor plugins: the
chat, the editors, the command palette, even the theme arrive as
contributions into declared extension points (LoopViewType,
LoopEditorView, LoopFrontendTool, LoopCommand, the slots). A host
plugin that adds an editor, its agent tools, and a command is ordinary
reactor code — the Loop page carries a complete example, and the generic
machinery (@datalayer/reactor-shell, @datalayer/reactor-commands,
@datalayer/primer-theme) is documented in the reactor's own docs.
In Python
Three hooks, three surfaces:
| Hook | Surface | Discovered under |
|---|---|---|
provide_cli(cli) | The command line — a Typer application the plugin adds command groups to | datalayer.cli, datalayer.reactor.cli |
provide_slash_commands(registry) | The interactive session — the Loop REPL's slash menu | loop.plugins |
Tool hooks (before_tool_execute, …) | The agent's tool lifecycle — see Hooks | agentspec configuration |
Agent Runtimes plays both roles. As a host, the REPL discovers slash
commands from any distribution advertising under loop.plugins. As an
extension, agent_runtimes.reactor_extension packages this package's
command groups so the datalayer and reactor CLIs carry them — nothing
spawns another executable; the groups register in-process at startup.
# A distribution shipping a /deploy command for the REPL:
[project.entry-points."loop.plugins"]
my-package = "my_package.loop_plugin:plugin"
class MyLoopPlugin:
def provide_slash_commands(self, registry) -> None:
registry.try_register(SlashCommandSpec(
name="deploy",
description="Ship it",
handler=deploy,
source="my-package",
))
A plugin that cannot load — a missing optional dependency, a broken hook — costs a warning and is skipped: one bad plugin must never take the host down.