Skip to main content

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

  1. Don't mutate core tables at runtime. Writes to workspace, workflow, workflow_execution, workflow_execution_log, workspace_status, entity, model, agent, the prompt* / service* / workflow_config* tables, system_context, system_wide_configuration, or the auth tables are all forbidden. Use core services (coreWorkspaceService, etc.) instead.
  2. Don't read from another plugin's tables. Plugins are isolated; if plugin A needs plugin B's data, that's a design error.
  3. Don't add columns to core tables. No ALTER TABLE circus.workspace ADD COLUMN ….
  4. Don't bypass the manifest contract. No alternative extension mechanisms, hidden hooks, or monkey-patching of core services.
  5. 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.
  6. Don't duplicate core endpoints. If the core exposes workflow start / retry / etc., you don't.
  7. Don't mount routes outside your apiRoutePrefix. Your router lives at exactly one prefix.
  8. 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.
  9. Don't submit cost_usd in log calls. Cost is core-computed from consumption.
  10. 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.