EnginePolicies

Using policy modules

Compose policy instances and distinguish policy factories from injected strategy helpers.

Use a policy factory when the decision contract stays the same but its settings vary. Create the instances once in your source, then pass the array to both the frame runner and intent checker.

Compose instances explicitly

With createQuantityPolicy from Defining a module in scope, this replaces the quickstart's policies declaration:

const policies = [
  createQuantityPolicy({ id: "strategy-limit", maximumQuantity: 2 }),
  createQuantityPolicy({ id: "experiment-limit", maximumQuantity: 1 }),
];

Both instances receive every execution request. A quantity of two passes the first and fails the second, so the combined result rejects it. Policy order does not make a later approval override an earlier rejection.

This is useful when two independently configured constraints must hold. Each ID also gets a separate state entry beneath the shared stack key.

Access the injected framework

The quickstart reads args.modules?.policies. That object provides getPolicyStackState, runPolicyFrames, resolveFrameActions, executeResolvedAction, and the intent-check helpers. You consume it from the supplied L3 arguments; you do not import it from a server filesystem path in inline source.

Other injected frame helpers have different contracts. For example, pureSides is a top-level helper function, not modules.policies.pureSides and not a policy object.

Consume a helper inside a policy

The following optional observer can be appended to the quickstart's policy array. First configure a sessionRegime instance with ID fast; it intentionally reports waiting when that dependency or helper is unavailable.

const regimeObserver = {
  id: "regime-observer",
  description: "Inspect the injected pureSides helper without placing orders",
  intents: ["none"],
  async onFrame({ policyId, context, pureSides }) {
    const regime = context.algos?.find?.("sessionRegime", "fast");
    if (!regime || typeof pureSides !== "function") {
      return { policyId, status: "waiting", reason: "Missing fast regime or pureSides" };
    }
    const decision = await pureSides({
      regimes: {
        entry: "fast",
        exit: "fast",
        sides: 5,
        missingOppositeSide: "blocked",
      },
    });
    const entry = decision?.regimes?.entry;
    return {
      policyId,
      status: entry?.ready ? "watching" : "waiting",
      reason: entry?.reason ?? "Waiting for regime evidence",
    };
  },
};

This example observes the helper's decision only. It does not turn ready into an order. If you add an entry action, validate its side, quantity, instrument, and position conditions, then return a policy intent for resolution.

Avoid accidental cross-module coupling

Prefer explicit configuration and the supplied scope to reading another policy's private state. If one policy intentionally consumes another's output, define the dependency and its freshness rules. Frame hooks are sequential, but reading yesterday's stored value is still possible if the producer returns early today.

Continue with Intents and State and lifecycle.

On this page