Plugins
Plugin Call Surfaces
Distinguish City management, Workspace execution, PluginContext, and the plugin_call Tool.
Plugin Call Surfaces
Plugins expose four call surfaces for different callers:
| Surface | Caller | Purpose |
|---|---|---|
city.plugins | Host application | Add or remove unique instances and invoke host/config actions |
city.plugins.scope({ agent_id: agent.id, workspace_id: workspace.id }) | Host execution code | Call Actions, Availability, or Hooks in one Agent/Workspace scope |
context.city.plugins | Plugin code | Call another Plugin Action, pipeline, or effect in the current scope |
plugin_call | Model in a Session | Call a Plugin Action provided by City |
City management surface
city.plugins.add(skill_plugin);
console.log(city.plugins.snapshots());
await city.plugins.remove("skill");city.plugins.invoke() and invoke_config() call host-management Actions registered during start();
they are not Session execution Actions.
Workspace execution surface
const result = await city.plugins.scope({ agent_id: agent.id, workspace_id: workspace.id }).run_action({
plugin: "skill",
action: "lookup",
payload: { name: "frontend-design" },
});This surface explicitly binds an Agent and Workspace, allowing City to create the correct
PluginContext.
PluginContext
const result = await context.city.plugins.run_action({
plugin: "skill",
action: "list",
payload: {},
});
await context.city.plugins.effect("audit.observe", result.data ?? null);context.session, context.agent.sessions, and context.workspace are directly callable handles.
IDs are reserved for stable identity and serialization.
Model Tool
plugin_call({
plugin: "skill",
action: "lookup",
payload: { name: "frontend-design" },
});The Tool is always bound to the current Session's Agent/Workspace execution lease and cannot observe another Agent's bindings.