One Full Message Flow

Connect pipeline, guard, and effect in one scenario so the runtime sequence becomes obvious

This page stops looking at one point in isolation and instead connects three hook types into one runtime path.

Scenario

You have one inbound message and want it to go through three steps:

  1. enrich it with source and page information
  2. check whether it was reviewed
  3. record one observation log

Host code

const enriched = await city.powers.scope({ agent_id: agent.id, workspace_id: workspace.id }).pipeline("chat.enrich_message", {
  text: "Please summarize this page",
});

await city.powers.scope({ agent_id: agent.id, workspace_id: workspace.id }).guard("review.require_checked", enriched);

await city.powers.scope({ agent_id: agent.id, workspace_id: workspace.id }).effect("audit.observe", enriched);

The corresponding powers

MessageAugmentPower

Owns the pipeline step:

  • add fields to the input

ReviewGuardPower

Owns the guard step:

  • decide whether the flow may continue

AuditEffectPower

Owns the effect step:

  • record what happened

Why these should not be merged into one point

Because they answer three different questions:

  • pipeline: should the value change
  • guard: may the flow continue
  • effect: should something be recorded

Once these are mixed into one point, the runtime meaning usually becomes harder to follow.

Main takeaway

Hooks do not mean "a power decides when it runs."

They mean:

  • the host defines the sequence
  • powers participate at named points in that sequence