Plugins

Plugin Configuration

Understand the boundary between unique Plugin instances, City-level configuration, and execution context.

Plugin Configuration

Each Plugin ID has exactly one host configuration inside a City:

host stores Plugin Config
→ City owns one Plugin instance
→ City projects a configuration snapshot for each execution
→ Plugin reads the current PluginContext.config
const city = new City({
  plugins: [web_plugin],
  workspaces: [workspace],
  plugin_host: {
    config: (plugin_id) => open_plugin_config_store(plugin_id),
    notifications: (plugin_id, agent_id) => open_notifications(plugin_id, agent_id),
  },
});

city.agents.add(agent);

PluginConfigStore.get() synchronously returns the complete current snapshot, while set(config) atomically replaces it. Agents store neither Plugin references nor configuration; every Agent sees the same Plugin configuration. A Plugin that needs multiple accounts or tenants models them inside its own Config instead of relying on a generic City named-configuration layer.

A Plugin registers Config actions during initialize(). City injects the Plugin's unique get/set store when city.plugins.invoke_config() calls one. Actions, Hooks, System providers, and Availability checks read an immutable snapshot from the current PluginContext.config.

After a Config save, the Plugin should release or refresh affected long-lived resources. Never store connections, callbacks, or client objects in Config. The Plugin still owns them by an actual domain key, such as an account or Agent, and ultimately releases them in dispose().

Table of Contents