Policies and analytics

Author deterministic executable Policy and emit bounded custom analytics from Agent or Channel runtime code.

Before you begin

Use Policy for authority and analytics for observation. Policy code is deterministic and has no network or secrets. Analytics fields are bounded and versioned.

Steps

  1. Author executable Policy with policy() and return a decision bound to the supplied input hash:
ts
import { hashValue, policy } from "@constal/sdk";

export default policy({
  id: "support-boundary", version: "1.0.0",
  async evaluate(request) {
    const allowed = request.input.context?.["resource.operation"] === "ticket.read";
    const decision = allowed
      ? { kind: "allow" as const, explicitDeny: false, constraints: [] }
      : { kind: "deny" as const, explicitDeny: true, constraints: [], reason: "operation denied" };
    return { inputHash: request.inputHash, outputHash: await hashValue(decision), decision };
  },
});
  1. Register analytics beside the Agent that emits it:
ts
import { agent, analyticsEvent } from "@constal/sdk";

const resolved = analyticsEvent({
  id: "support.resolved", version: "1",
  dimensions: ["queue"], metrics: ["duration_ms"],
} as const);

export default agent({
  id: "support", version: "1.0.0", model: "model", analytics: [resolved],
  async onMessage(message, ctx) {
    const startedAt = Date.now();
    const turn = await ctx.turn({ system: "Resolve the request.", objective: message });
    ctx.analytics.emit(resolved, {
      dimensions: { queue: "general" },
      metrics: { duration_ms: Date.now() - startedAt },
    });
    return turn.message.content;
  },
});
  1. Deploy Policy with constal.policy.json and evaluate positive and negative normalized inputs before attachment. Deploy the Agent separately. Analytics emission records synchronous intent; tenant code receives no analytics storage or query binding.

Verify

Evaluate one allowed and one denied Policy input, then inspect an accepted Run to confirm the effective Policy hash. Emit a custom event from a controlled invocation and query it after projection. Use the live workflow endpoint—not analytics—when you need authoritative current execution state.

Next steps

Use Author a Policy for decision semantics and Instrument custom analytics for schema, cardinality, and query guidance.