Downcity
PluginsHooks

Call Flow

Explain who triggers hooks and resolve points, when they run, and how host code usually calls them

Call Flow

This is the most important page because it removes the biggest misconception first:

  • hooks do not run automatically just because they are registered
  • hooks run when host code explicitly calls a named point

Two roles

To understand hooks and resolve points, separate these two roles:

plugin author

Defines:

  • which point has a handler
  • what input the handler receives
  • what it returns or when it throws

host author

Decides:

  • when to call the point
  • which value to pass in
  • what to do with the result afterward

One minimal call flow

const value1 = await agent.plugins.pipeline("chat.enrich_message", input);
await agent.plugins.guard("review.require_checked", value1);
await agent.plugins.effect("audit.observe", value1);
const role = await agent.plugins.resolve("auth.resolve_role", {
  userId: "owner",
});

Read this flow step by step:

  1. pipeline receives input and may return a richer value1
  2. guard decides whether value1 is allowed to continue
  3. effect records side effects without rewriting value1
  4. resolve answers a separate single-authority question

Why the first three are chain points

Because the most common pattern is:

  • the main flow reaches a specific step
  • the host hands the current value to plugins
  • plugins participate at that exact step

They behave like extension slots in a running pipeline.

Why resolve feels more like a final lookup

Because it is usually not about continuing to transform one shared value.

It is about:

  • the host now needs one final answer
  • it asks a named point to provide that answer

For example:

  • what is the user's effective role
  • which provider should be selected
  • which component is the final owner of this request

What happens when a plugin is disabled

This depends on the point type.

pipeline / guard / effect

If one registered plugin is currently disabled, its handler is skipped.

That means:

  • the point still runs
  • but that disabled plugin does not participate

resolve

If the plugin owning the single resolver is disabled, the point does not silently continue.

Instead:

  • resolution fails

That is because the point requires one authoritative answer.

What happens when no handler exists

pipeline / guard / effect

If no handlers are registered:

  • pipeline returns the input unchanged
  • guard passes immediately
  • effect ends immediately

resolve

If no resolver is registered:

  • it throws

That is because the host explicitly asked a question that must produce an answer.

The two key takeaways

  • hooks mean "the host controls timing, plugins provide insertion logic"
  • resolve means "the host asks for one final answer, and exactly one plugin owns it"

Next reading