What Plugins Are Not Allowed To Do
A plugin is an app within the app, with enormous freedom — because of a short list of hard rules. These aren't style preferences; they're the boundaries that keep the platform's guarantees intact. Break one and you don't just write ugly code — you break something the platform promises. Here they are, plainly.
The rules
- Don't mutate core tables at runtime. Writes to
workspace,workflow,workflow_execution,workflow_execution_log,workspace_status,entity,model,agent, theprompt*/service*/workflow_config*tables,system_context,system_wide_configuration, or the auth tables are all forbidden. Use core services (coreWorkspaceService, etc.) instead. - Don't read from another plugin's tables. Plugins are isolated; if plugin A needs plugin B's data, that's a design error.
- Don't add columns to core tables. No
ALTER TABLE circus.workspace ADD COLUMN …. - Don't bypass the manifest contract. No alternative extension mechanisms, hidden hooks, or monkey-patching of core services.
- Don't define core-level (entity-agnostic) statuses or workflows. Every status belongs to exactly one entity type; every workflow is scoped via
belongs_to_entity_id. - Don't duplicate core endpoints. If the core exposes workflow start / retry / etc., you don't.
- Don't mount routes outside your
apiRoutePrefix. Your router lives at exactly one prefix. - Don't rely on core table deletion. Core workspaces are never deleted — if you think you need workspace deletion cascading, you're confusing your plugin soft delete (on the join table) with a core hard delete.
- Don't submit
cost_usdin log calls. Cost is core-computed from consumption. - Don't update workspace status inside
resultHandler. The core does that after your handler returns.
A note on enforcement — the honest version
It's worth being precise about how these hold, because it affects how you treat them. Some are structurally guaranteed: the core genuinely never reads your tables, and FK direction is a fact of the schema. But several — "don't write to core tables," "don't add columns" — are contract rules the platform relies on you to honour, not locks it can enforce. Your plugin runs with full database access; nothing mechanically stops a rogue query against a core table. So these are a discipline, and following it is your responsibility as the developer.
The payoff for honouring them is exactly the freedom this package keeps promising: stay inside these lines and the core will load your plugin, keep its execution and financial guarantees intact, and let you build almost anything on top. The rules aren't a cage — they're what makes the open field safe to run in.